14 ms·
Show HN: I built a web framework in C
- guerrilla 1y agoFor fun or why?
- hmry 1y agoScience isn't about why, it's about why not.
- ashtonjamesd 1y agoFor fun! And because I wanted to create a framework that makes coding in C feel like a high level language (mainly for fun though).
- cozzyd 1y agoI think it makes lots of sense when adding e.g. a live view to some C daemon running on a single board computer. Obviously in these cases you're not generally on the public Internet and your clients are trusted.
- yodon 1y ago[flagged]
- johnisgood 1y agoUse static analysis (Coverity, Coccinelle, sparse), enable KASAN/UBSAN, follow the SEI C Coding standard or MISRA C, and rely on the review process. Many popular C projects do really well. Projects that you probably use. Memory-safe languages eliminate vulnerability classes, but well-engineered C has proven viable for security-critical <insert whatever you want> infrastructure. The real question is whether the framework maintains that standard, not whether C is inherently unsuitable, thus the security concerns are legitimate but not absolute. I think you are being a bit too dismissive, and your comment puts nothing concrete on the table.
- yodon 1y agoYou CAN write good code in any language. The issue is, as you say, that memory-safe languages eliminate entire vulnerability classes, vulnerability classes that are among the most trivially exploitable. Can write safe code does not mean always writes safe code. A web server needs to be safe code, always.
- hu3 1y agoThis tired, flamewar-prone argument of gatekeeping new code in C/C++. Oh the irony coming from someone who wrote this some days ago: > One of the highest priorities for the HN algorithm is to promote good interactions and discourage bad interactions. The logic is if you have a lot of people bickering with each other, regardless of the topic, it normalizes bad behavior. HN is trying to sustain itself as a forum with great discussions.
- yodon 1y agoI notice you chose to attack me rather than attacking the assertion that memory-safe languages are inherently safer than memory-unsafe languages like C. Yes, you CAN write memory safe code in C. You DO write memory safe code in languages like Java, Python, PHP, and C#. Critically, the maintenance programmer also writes memory safe code when working in a memory safe language. The maintenance programmer is not guaranteed to write memory safe code when working in a language like C. If any of the above is incorrect, I'm interested in learning more.
- hu3 1y agoThere's nothing to dispute in your assertion, because you're technically correct. However it's just not constructive and repetitive. You're basically walking into a bar and yelling that alcohol is unhealthy.
- dang 1y agoWhat was incorrect (to use your word) in your posts in this thread was your misalignment with the intended spirit of the site. You responded with generic/shallow objections to someone's creative work. That's one of the failure modes of internet discussion, which is why both the HN guidelines (https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html) and the Show HN guidelines (https://news.ycombinator.com/showhn.html https://news.ycombinator.com/showhn.html) ask commenters not to do this. It's true that the repliers crossed into the red as well, but fundamentally that's a healthy immune response going a little too far.
- camillomiller 1y ago[flagged]
- alwahi 1y agoa saas in prolog...
- sixtyj 1y agoDon’t forget Fortran… /s
- wolfgangbabad 1y ago[flagged]
- Joeboy 1y agoA computer program written in a programming language.
- osigurdson 1y agoCobol and C are very different in terms of modern relevance.
- JKCalhoun 1y agoI'm stupid — is this to create web apps that run on the server? More or less replacing PHP or whatever?
- ashtonjamesd 1y agoRight now, it's just a framework for building backends. So yes, server-side applications. However, I have thought about implementing a templating engine for serving HTML files.
- sixtyj 1y agoEdit: I am considering to delete the following paragraph as it seems that my hands were quicker than my brain :) I'm sorry, but it's like scratching your left ear with your right hand. But for fun, yeah, there are worse things people do. Good luck and have fun. Now here's where most of us will probably be sarcastic, but it's certainly a good way to explore whatever others consider bullshit. Edit: Pls read the following comment. I would hire him/her because I consider this as a waste of OP skills and he/she would be useful in many more projects. TLDR; it was not a hate. I am sorry if it sounds so.
- ashtonjamesd 1y agoTrue. Also, I love the C language and I don't get joy out of writing in many other languages. Additionally, I've wanted to make something like this just to learn more about how web servers work. I appreciate your thoughts.
- sixtyj 1y agoIt is not about threat. It is about that life is too short to do things that are almost nonsense. Ofc everyone of us consider “nonsense” in different way. I wish OP good luck. It was not sarcastic, I really do, and would like to hire him/her for the skills. But for mankind, this project is almost useless… I apologize if this sounds harsh.
- EGreg 1y agoTake a look at https://www.reddit.com/r/programming/comments/225ovy/okws_okcupids_open_source_c_web_application_server/ https://www.reddit.com/r/programming/comments/225ovy/okws_ok... This was years ago (20 years ago?)
- alwahi 1y ago[flagged]
- ashtonjamesd 1y agoC finds a way.
- firemelt 1y agou should post this to people that write web with javascript
- gwbas1c 1y agoI don't understand the example. Does it even compile? It's been a long time since I've used C, so maybe it's using some syntax that I'm unaware of? IE: What defines "home" that is referenced as an argument to the "appRoute" function, and then passed to the "get" function to set up the "/home" route? Is "home" defined in lavandula.h, or is this really pseudocode?
- deleted 1y ago[deleted]
- diath 1y agoIt's a macro: #define appRoute(name) HttpResponse name(AppContext ctx)
- ashtonjamesd 1y agoHi, sorry maybe I should've added a comment for that. The 'appRoute' is a macro that expands to a function signature. The macro is: '#define appRoute(name) HttpResponse name(AppContext ctx)' and the parameter I passed as 'home' is expanded into the function name. The reason is because all controller function signatures are the same, so just writing 'appRoute' allows the developer to save time writing endpoints! It is a tradeoff between readability and development speed. And one of the ideas behind the framework is succint and minimal code.
- gwbas1c 1y agoSo it creates a function called "home", and that is what you pass to get? Makes sense, thanks!
- nodesocket 1y agoThanks for explaining. I was also a bit confused at a first where the home variable being passed into get() was coming from.
- hofrogs 1y ago"appRoute(home)" is a macro that expands to a function called "home": #define appRoute(name) HttpResponse name(AppContext ctx)
- lubesGordi 1y agoWell I don't know about others here, but I think its cool. If you can make the setup super readable and get the performance of C then why not? Especially now when you can get claude to write a bunch of the framework for you. Add in whatever you need whenever you need it and you automatically have a platform independent web framework that's no bigger than what you need and likely decently performant.
- maybewhenthesun 1y agoMaintainer nightmare checklist: - Web framework : inherently hard to maintain due to communication over evolving standards. Check. - AI written code where nobody knows howwhatwhenwhy!? Check. - Written in C. Check. bwahahahaha! edit: semi-joking. As I actually like the simplicity of pure C. But the combination of AI written,network-facing and C makes me shudder.
- ashtonjamesd 1y agoHaha, I have used AI in some parts of it - mainly the JSON part because I could not wrap my head around it for the life of me. But I am proud that 90% is self written!
- jvanderbot 1y agoThat is excellent. Well done.
- le-mark 1y agoIn that case the json parse function might be a bit of a challenge. It should actually be pretty straight forward with the builder functionality you’ve got in there. Loop over the input and use a state machine (switch block with a state variable) keep track of what you’re doing. Oh and you’ll need to recurse or otherwise use a stack to keep the nesting levels correct. Ie objects that contain arrays or objects, arrays that contain arrays, etc.
- isubkhankulov 1y agoI can see this becoming a trend. People putting badges on their repo as to how artisanal, organic and “authentic” their code is.
- p0w3n3d 1y agoGreat work! Thank you! That's what I've been looking for for a long time. Still probably I'm going to continue learning golang in most situations, because that's where the money is (i.e. job offers), but I will create a hobby project based on your framework. --- EDIT --- > 5 hours ago Ohh it's fresh. I almost smell the freshly baked buns with my mind
- ashtonjamesd 1y agoThat's amazing to hear and motivates me to solidify the framework further. I appreciate you showing interest! :) I'd love to hear about your project when you get round to it.
- fallingmeat 1y agowow that’s a lot of HATE for a really well organized project with some great ideas. Killer job Ashton, you just built some skills they can’t take away from you.
- ashtonjamesd 1y agoThank you, that means a lot! :)
- freetonik 1y agoI hope you don't feel discouraged by some comments questioning the meaningfulness of this. It's a cool project, and you obviously put some thought into it. Congrats!
- freetonik 1y agoIn addition, OP clearly describes themselves as a "Fanatical C Developer", so that's enough justification in my book! :)
- Teknomadix 1y agoDoing what you love is fully justified in 2025.
- ashtonjamesd 1y agoNo of course not, I understand where they are coming from in all honesty. Thank you that means a lot!
- dang 1y agoOfftopic (sorry) but this thread is such a good example of the contrarian dynamic that I can't resist! The "contrarian dynamic" (https://hn.algolia.com/?dateRange=all&page=0&prefix=true&query=%22contrarian%20dynamic%22&sort=byDate&type=comment https://hn.algolia.com/?dateRange=all&page=0&prefix=true&que...) is the tendency for reflexively negative comments to show up early with shallow/generic objections to a submission, followed by a later wave of comments objecting to the objections and defending the submission. The latter tend to get upvoted—rightly so, since they are more positive and usually more substantive. This puts the thread in the paradoxical-but-common state where the top comments are objecting to how prominent the bottom comments are! (Or, rather, were.) That's odd, but at least it's better than having the negative ones at the top. In this case, these 5 comments all appear higher in the thread: https://news.ycombinator.com/item?id=45528218 https://news.ycombinator.com/item?id=45528218 https://news.ycombinator.com/item?id=45527967 https://news.ycombinator.com/item?id=45527967 https://news.ycombinator.com/item?id=45527886 https://news.ycombinator.com/item?id=45527886 https://news.ycombinator.com/item?id=45527879 https://news.ycombinator.com/item?id=45527879 https://news.ycombinator.com/item?id=45527728 https://news.ycombinator.com/item?id=45527728 ... than the negative(ish) ones that were posted earlier: https://news.ycombinator.com/item?id=45527887 https://news.ycombinator.com/item?id=45527887 https://news.ycombinator.com/item?id=45527480 https://news.ycombinator.com/item?id=45527480 https://news.ycombinator.com/item?id=45527387 https://news.ycombinator.com/item?id=45527387 https://news.ycombinator.com/item?id=45527278 https://news.ycombinator.com/item?id=45527278 https://news.ycombinator.com/item?id=45527259 https://news.ycombinator.com/item?id=45527259 Some of those were only slightly negative and probably not meant that way, but yeah, the early impact of running into a bunch of these leads to a WTF feeling. Ultimately I think this has to do with the reflexive/reflective distinction: https://hn.algolia.com/?dateRange=all&page=0&prefix=true&sort=byDate&type=comment&query=reflective%20reflex%20by:dang https://hn.algolia.com/?dateRange=all&page=0&prefix=true&sor.... That's probably the clearest way of describing the difference between the kind of comments we want on this site vs. the kind we don't want.
- tobyhinloopen 1y ago[flagged]
- ashtonjamesd 1y agoHaha, the example could be better. All of the other things combined, I would say it could be called a framework. There are some more examples in doc/
- levkk 1y agoThat's awesome. With macros, you can go far and most modern web frameworks use whatever complex tools their language allows (like metaprogramming in Rails). Mad props for building this. It's hard and it's fun! As to other comments in the thread about the "why": why not. For the love of the craft.
- ashtonjamesd 1y agoThank you so much! I appreciate it :) And yes, totally agree.
- sroerick 1y agoHi, I think this is great. I've really enjoyed working with Jetzig, which is sort of similar. I also love the BSD C CGI Postgres stack. I'm just a CRUDmonkey with mostly python skills, so getting to explore low language and memory concepts is a lot of fun for me. People will whine and moan about how this is not practical, but as embedded devices become more ubiquitous I think a clear value add may actually emerge. I've been playing with the pico calc, and if I was building something as a "mobile app" for that I would much rather reach for C for my framework code. Cheers, great work
- faxmeyourcode 1y agoThis is some of the cleanest, modern looking, beautiful C code I've seen in a while. I know it's not the kernel, and there's probably good reasons for lots of #ifdef conditionals, random underscored types, etc in bigger projects, but this is actually a great learning piece to teach folks the beauty of C. I've also never seen tests written this way in C. Great work. C was the first programming language I learned when I was still in middle/high school, raising the family PC out of the grave by installing free software - which I learned was mostly built in C. I never had many options for coursework in compsci until I was in college, where we did data structures and algorithms in C++, so I had a leg up as I'd already understood pointers. :-) Happy to see C appreciated for what it is, a very clean and nice/simple language if you stay away from some of the nuts and bolts. Of course, the accessibility of the underlying nuts and bolts is one of the reasons for using C, so there's a balance.
- ashtonjamesd 1y agoWow! That really means a lot because I always make a lot of effort to make sure my code is just that :) Appreciate you saying that!
- jacquesm 1y agoYou've done a couple of things right: very few dependencies, simple, easy to understand code. C gets hairy when you try to be clever. I'm busy writing some of the most optimized-but-still-portable code that I've ever written and it is very interesting to see how even a slight difference in how you express something can cause a massive difference in execution speed (especially, obviously, in inner loops). Your code is clearly written from what your comfort zone with C is and I'm really impressed by the restraint on display. At the same time, some of the code feels a bit repetitive and would benefit from more universal mechanisms. But that would require more effort and I'm not even sure if that is productive. One part where I see this is in the argument parsing code as well as in the way you handle strings, it is all coded very explicitly, which substantially increases the chance of making a mistake. Another limitation is that using AI to help you write the code means you don't actually understand what it does, and this in turn may expose you to side effects that you are not able to eliminate because you did not consider them while writing, it is as if someone else gave you that code and asked you to trust them they did not make any mistakes.
- capestart 1y ago[dead]
- jacquesm 1y agoIf you're going to use local allocation of short lived buffers then don't use malloc but use alloca. That's much cleaner. http.c around line 398, that looks wrong.
- gpm 1y agoI've been told that modern compilers really don't like alloca, is that wrong?
- jacquesm 1y agoI don't know who told you. But it's a lot slower than malloc, and requires you to do a bunch of bookkeeping, which is easy to mess up if you have multiple exits from your function.
- CyberDildonics 1y agoalloca is just a couple of instructions to allocate more memory on the stack, it is much faster than malloc for pretty much every reason including locality and the fact that it doesn't have to be freed because it goes away after the current scope.
- 1718627440 1y agoIs there a difference between: T * ptr = alloca (size); and char buffer[size]; T * ptr = &buffer; under the assumption that this happens at the top-level of a function?
- CyberDildonics 1y agoNot that I know of
- lelanthran 1y ago> But it's a lot slower than malloc How would it be slower? Isn't it simply bumping the stack pointer?
- deleted 1y ago[deleted]
- globalnode 1y agoI like this, thanks for sharing. I recently did some work with a python web server using the basehttpserver and it was amazingly easy. Pythons even got built in tls support, would that be doable in your server? Its not that necessary with reverse proxies but its still nice for hobby projects.
- ashtonjamesd 1y agoYes, I'm sure that is something I can add to it. I will add it to the backlog of things to do :)
- coreyp_1 1y agoI'm wanting to do the same thing. I've also already written a language (in C) to generate HTML (a template language), so these two go hand-in-hand!
- kahlonel 1y agoThat's a great example of how to write C in 2025. Congrats and well done.
- lelanthran 1y ago> That's a great example of how to write C in 2025. Congrats and well done. This project is an awful example of how to write C. No checking of return values, leaking memory with realloc, over-engineered parsing (what should be 8 lines is +200). I can understand it as a learning project, and even if it wasn't, I can sorta understand that sometimes bugs creep in ("oops, forgot to use a tmp variable for realloc in one out of 10 places") but this is not what is happening: This is not how you write C!
- codegeek 1y agoPeople, stop trying to be so serious and nitpick this project. This is a great example of an actual HN worthy share. Someone built a cool project and explored the possibilities with C. This is not something we need to analyze with "oh can it replace PHP" etc. Good job OP. Now if you can add HTML templating, this may become a complete framework :)
- ashtonjamesd 1y agoThank you, I really appreciate you saying that! Yes it's on the backlog and will be fun to implement :)
- whatamidoingyo 1y agoAs someone learning C for fun, I agree. This project is awesome!
- hgs3 1y agoThe code is very readable and well organized. My only major critique is that there's very little error checking, e.g. there are many calls to snprintf and malloc without checking the result. There is also an unused loop here [1]. As an aside, I don't see any support for parallelization. That's fine for an initial implementation, but web servers do benefit from threading off requests. If you go that route (pun intended) you might consider using something like libuv [2]. [1] https://github.com/ashtonjamesd/lavandula/blob/51d86a284dc7d11aaaa3e0fac5fb1278a9051529/src/http.c#L398-L400 https://github.com/ashtonjamesd/lavandula/blob/51d86a284dc7d... [2] https://github.com/libuv/libuv https://github.com/libuv/libuv
- ashtonjamesd 1y agoThank you for the feedback, it is appreciated! I did intend to implement parallelization as a later feature so it's good to bring it up.
- OutputRiff 1y agoThe repo looks fantastic! I'd love to see a demo and didn't seen one readily available in the readme. I had such a bad experience with GWT back in the Java days of my life that I've steered clear of any "server" language for web frameworks since. I'd love for that to change though. I definitely will be trying this out.
- defraudbah 1y agogithub is giving me 503, the project is too good for mS Thanks for sharing, this looks amazing
- dboon 1y agoC is really, really ripe for tooling and modern libraries. There are a lot of great ones already that don’t resemble what I’ll call university C in the slightest (i.e. the C most of us remember writing; awful, bug filled, segfaulting) I’ve been building out my C standard library replacement in earnest for a little while. If you like this framework, check it out. https://github.com/tspader/sp https://github.com/tspader/sp
- le-mark 1y agoThat’s quite impressive, I love this c renaissance! I noticed your project requires c++ compiler as well, I didn’t study it to understand why? Do you plan to keep that requirement?
- elevation 1y agoNice work! I like the little test framework you built. Have you considered making runTest a macro so that you can print the name of the test along with the test result?
- ashtonjamesd 1y agoThat's a very good idea actually and I had wanted to do that but it didn't click that you could do that with a macro! Thank you, I'll will implement that :)
- elevation 1y agoFor the ultimate in readable test reports, you can prettify the test name by: * dropping the prefix "test_" * substituting the "_" characters in the function for whitespace * uppercasing the first letter of each word. So `test_tokenize_simple_model` becomes "Tokenize Simple Model".
- jcmontx 1y agoI often forget how similar to Golang C looks and feels
- EasyMark 1y agoMaybe more chronologically correct to say "how very similar to C that golang looks"
- elevation 1y agoI have considered porting a couple production apps from python to C; at this stage in their lifecycle they would benefit more from C's execution speed than from python's development speed. Your work is a nice reference, it is neat to see someone else working in this space!
- dariosalvi78 1y agoHow compatible is this with embedded devices? How much does this depend on OS APIs?
- sim7c00 1y agoreally nicely written. inrespect this is maybe known / unneeded comment, but why bother with basic auth at all, especially when there is no TLS? i understand other auth schemes are more complicated, and maybe theres no desire to pull in big libraries. just that if theres no TLS or proper auth, you can also just skip basic auth. its only use would be to trick someone who's not familiar (unlikely with such a repo but not impossible) into a false sense of security. ofc, not really an issue with the code, and its an excellent base to look into how this stuff works and if you want since its pretty clean and easy to ready, expand upon it. well done! love ppl churning out good ol C projects. respect!
- severino 1y ago> why bother with basic auth at all, especially when there is no TLS? Maybe to have some "basic" auth for an embedded device web interface or something like that? I suppose it's better than nothing. I've devices which prompt for username and password with no TLS either.
- sweetjuly 1y agoIt's fairly common to use something like nginx as a forward proxy and do TLS there. IPv4 and NAT makes this essentially mandatory if you want to host multiple services due to eSNI. You wouldn't necessarily have protection inside the server network (which isn't great) but you at least get protection everywhere else.
- kjs3 1y agoBasic auth can keep the crawlers out, for one thing.
- orochimaaru 1y agoThis is very cool. I may take the same concepts you have and do this in rust and zig for fun and learning. Yeah, I know those languages have a the frameworks but nothing really beats understanding something like doing it ground up on your own.
- leptons 1y agoDoes it do HTTPS? I'd be interested to try it on ESP32 but it has to support HTTPS.
- krowek 1y agoCurious, why did you decide to go with your own test helpers rather than using something like check?
- cyberax 1y agoUhh... This is an example why C is so bad for network-facing stuff: https://github.com/ashtonjamesd/lavandula/blob/2dbefe6da16bf40de26e87d7aaea59210daffe59/src/http.c#L399 https://github.com/ashtonjamesd/lavandula/blob/2dbefe6da16bf... - is it intended? https://github.com/ashtonjamesd/lavandula/blob/2dbefe6da16bf40de26e87d7aaea59210daffe59/src/http.c#L308 https://github.com/ashtonjamesd/lavandula/blob/2dbefe6da16bf... - pain....
- badsectoracula 1y agoI get the first one but what is the issue with the second one? It looks like a fairly standard dynamic array with separate size and capacity.
- jacquesm 1y agoMissing null pointer check on return, leaks memory because it overwrites the original pointer.
- badsectoracula 1y agoI didn't notice that, but TBH is this a realistic concern? Is there an actual platform nowadays where realloc (and malloc, for that matter) ever fails, at least outside (small) embedded environments? I've being using realloc for decades and the only time i had to worry about it failing was in DOS. Nowadays it feels like worrying about realloc failing is similar to worrying about fclose failing.
- 1718627440 1y agoIt is still mandated by the standard, so absence of checking can lead the compiler to conclude UB and optimize stuff away. Also it is commonly made to return NULL for testing.
- badsectoracula 1y ago> It is still mandated by the standard, so absence of checking can lead the compiler to conclude UB and optimize stuff away. The compiler can only prove that malloc/realloc may return NULL, not that it will or it will not return NULL - it is impossible for a compiler to know that as that is runtime behavior. So the most the compiler can do is remove checks for NULL in case subsequent code is written with the assumption that the pointer is valid (i.e. you use `malloc`, then try to use the pointer it returned, then you try to check if it is valid - the compiler may decide to remove that last because your earlier use assumed the pointer is valid). > Also it is commonly made to return NULL for testing. This is done explicitly by the developer though, it is not "normal" behavior, so the developer is opting in to that (and as i wrote earlier, testing for that case doesn't seem to be practical nowadays unless you target some limited environment).
- SvenL 1y agoI like it. I was looking for something like this and I will take a look into it.
- entelechy0 1y ago[dead]
- ranger_danger 1y agowhich version of C does this conform to?
- Maksadbek 1y agoCouldn't believe my eyes, this is the cleanest C code I've ever seen!!
- mistivia 1y agoIt's very dangerous to write a http parser from scratch in C. This can be very vulnerable without rigorous testing. To get a useful web framework for production in C, I think it's a better idea to start from libmicrohttpd, libevent_http, or even fastcgi, which are battle-tested.
- jacquesm 1y agoI don't think anybody here is going to use this for production, but just in case you're tempted: don't.
- wallmountedtv 1y agoI hear this comment warnings, and can easily see this myself being true. But, how could one actually make a reasonably safe http server in C from scratch? That would honestly sound like an amazing book, just walking through all the ways it's horrible chapter by chapter, and how to structure the code instead, slowly. Like an accelerated history to create such a matured http library.
- throwaway2037 1y agoI like your idea for the book. I hope that Robert Nystrom writes it.
- koito17 1y agoThe README gets straight to the point and I really like that. Additionally, the .env file parser is quite clean. https://github.com/ashtonjamesd/lavandula/blob/main/src/dotenv.c https://github.com/ashtonjamesd/lavandula/blob/main/src/dote... However, it doesn't seem that the parser supports comments. I guess a "good first issue" for anyone interested in contributing would be extending the `skipWhitespace` function to detect `#` tokens and skip the rest of the line when present. Would also need to handle edge cases like env vars having values containing `#` tokens inside (but these will be quoted, so it's probably not too tricky to handle.)
- koolba 1y agoWhy is there an env file parser at all?
- jpc0 1y agoSo what happens when the env value happens to actually have a # in it? So you then need to implement escaping which can go from a very simple implementation to an actual lookahead parser EDIT: Actually I agree, this parser is already very overbuilt and should be able to handle comments. Generally an env parser is a few lines a best… you need to read a line, look for the first instance of the separator, generally no reason to build a full parser for that, env is an absurdly simple format if you don’t want features like comments. Hell even an ini format parser is simple to implement in the same style.
- lelanthran 1y ago> Additionally, the .env file parser is quite clean. I didn't find it clean; it's so over-engineered that you won't easily be able to spot bugs in it. What you want is (assuming you have a string-trimming function): while ((fgets (name, sizeof name, inputf)) { if (!(value = strchr (name, '='))) { continue; } *value++ = 0; strtrim(name); strtrim(value); if (!*name) { continue; } // Now store `name` and `value` } > I guess a "good first issue" for anyone interested in contributing would be extending the `skipWhitespace` function to detect `#` tokens and skip the rest of the line when present. Or do it before processing: // First statement of while loop char *comment = strchr (name, '#'); if (comment) *comment = 0; // Continue with processing `name` The way it's done in the linked code raises a ton of red flags.
- BiraIgnacio 1y agoGreat work, thanks for this!
- OneLessThing 1y agoThere is a heap overflow in the http parser. Should I spoil it or let people find it on their own?
- OneLessThing 1y agoHeres a link to the the problem I found: https://alew.is/lava.html https://alew.is/lava.html
- 1718627440 1y agoThis sounds essentially like Heartbleed. Btw, you have a syntax error on line 13, the style tag isn't closed. Otherwise clean webpage.
- 201984 1y agoVery nice! A couple of notes: you'll want to use non-blocking I/O and an event loop to prevent one slow client from locking up the whole server. You should also check for partial read and write calls, so that if a client sends a couple bytes at a time, you can buffer up their full response and still be able to respond to it. A fixed size buffer for requests isn't ideal either since POST requests can easily blow through your 4096 byte buffer. You might also want to look into using an AF_INET6 socket. You can still accept IPv4 connections, but you'll also gain IPv6 basically for free, and in 2025, you really should support IPv6.
- lebimas 1y agoReal question, how did you learn how to code this well? I found your LinkedIn from your Github, and as someone who is just committing to becoming a SWE at 26, having learned a bit of Python and Matlab in college, and a bit of Java in high school, yet never fully grasped it and thus avoided it for as long as possible, I'm impressed by people who have this caliber of abilities at such a young age. Are there any tips or bits of advice you (or anyone else on HN for that matter) would give to someone who really wants to be the best they can possibly be at coding?
- ashtonjamesd 1y agoHi, I have been coding on GitHub for about 2 years. There's no trick other than enjoying it and relentlessly programming for fun. You probably know this, but if you enjoy something, you'll likely be better at it than someone who doesn't! More concrete advice would be to become an expert on the fundamentals and then try to tackle large projects, things that you think you could definitely not do, but do them anyway.
- lebimas 1y agoI appreciate the response! Was there any structured curriculum you used for learning the fundamentals? As someone who isn’t in a CS program, I was wondering where a good place to start would be
- ashtonjamesd 1y agoNo problem! With C, I started with the K&R book. This provided a great foundation for C and some fundamental CS concepts. I am unsure of the best way to obtain a more structured curriculum outside of college, as that is how I received mine. There are many YouTube video courses to choose from if that is the type of content you learn best from. And many for CS fundamentals. I would also highly recommend a combination of project-based learning with theory, as that will accelerate your understanding quite a bit. You could try looking for a programming buddy on Reddit on r/programming, too! Having someone at a similar skill level to you will make learning easier as you both share knowledge.
- faichai 1y agoSome unsolicited feedback: I think the appRoute macro obfuscates the types and signatures, and introduces some unnecessary indirection. I would get rid of it. Related, the AppContext type could be renamed RequestContext or ControllerContext or something as its App + HTTP Request + DB and not just the App. Otherwise, I agree with other commenters that this is some of the cleanest C code I’ve seen in a while! Great effort!
- ashtonjamesd 1y agoThank you for the feedback! I agree it does obfuscate the signature, possibly too much. I think it's okay as long as the user has the option to do both, with this made clear in the docs. Also, yes I agree, RequestContext makes more sense!
- z3ratul163071 1y agoawesome! hope hw vendors will adopt it so their management web pages are less ass than they actually are currently.
- ak39 1y agoNice. Is if a one thread per request model? Does it support async await type of architecture?
- jll29 1y agoThanks for sharing; small is beautiful. A couple of points of feedback: - check return value from malloc(); - consider using your own arena allocator (which gets a larger block of memory with a one-time call of malloc, then calls an in-process allocator that assigns part of that block); - use a library prefix e.g. Lavandula_ before API functions like get() or runApp() to avoid name collisions. - The JSON function is not spec-compliant; why not use an existing library? (I understand external dependecies may introduce unwanted bloat, but in this case, there are many compact and efficient options.)
- 1718627440 1y ago> consider using your own arena allocator (which gets a larger block of memory with a one-time call of malloc, then calls an in-process allocator that assigns part of that block); This is what malloc already does. Unless you intend to have multiple different arenas in your program, this is just unnecessary complexity.
- shevy-java 1y agoVery courageous. I would have fatigued in the middle, probably using ruby or python instead.
- lordleft 1y agoI am convinced that well written C code is more aesthetically pleasing than well written code in other languages. Great job and thanks for sharing.
- Silphendio 1y agoChoosing names like `App`, `ok` or `get` in a language without namespaces is a bold choice.
- chuliomartinez 1y ago[dead]
- notepad0x90 1y agoOP, Turn on CodeQL workflows in GH, you'll thank me later! Even if your code is bug free, it makes it easier to find out when common mistakes are introduced later on. Especially since you're asking for help with features and others will be doing PRs. Great project. I remember using mongoose a while back that's also written in C. Personally, the more library independent and self-sufficient it is, the more I'm likely to use it. Like, if you can even avoid using the stdlib! Even thought that sounds crazy (but a server in C is a bit crazy anyways?). The more standalone it is, the more transformable and embeddable it can be.
- kopirgan 1y agoI created something similar few months back, just to learn. Integrated with sqlite. It is fun to try but I realised there is a huge Mt. Everest to climb to make it anything close to fit for use. https://github.com/fullobug/gttp https://github.com/fullobug/gttp
- hollowonepl 1y agoAlthough I don’t like pascal notation in C (I’m conservative snake style forever kind of guy myself) I agree with others who praise clarity. I have done something similar some time ago but more like a production ready ExpressJs alike framework in C++ using only STL and Boost. Definitely C/C++ can be considered as a very productive environment free of all the “modern web” dependency hell many other coding platforms introduce by default.