6 ms·
Show HN: A little web server in C
A little web server written in C for Linux.
Supports: CGI, Reverse Proxy.
Single threaded using I/O multiplexing (select).
- password4321 3y agoI use dufs when I need a webserver for minor things, and reverse proxy to it through Caddy if things get serious enough to need an SSL certificate. https://github.com/sigoden/dufs https://github.com/sigoden/dufs
- rahmeero 3y agoInteresting. Would be good to get more info, beyond having to read the code. Curious to know how it compares to micro_httpd [1] which is about 200 lines of C. Or others like thttpd and tiny_httpd. [1] https://acme.com/software/thttpd/benchmarks.html https://acme.com/software/thttpd/benchmarks.html
- forgotmypw17 3y agoThank you so much for sharing this! This is exactly the type of web server I'm looking for my project.
- mazidodo 3y ago[flagged]
- whartung 3y agoI dunno. I haven't written a multiplexing I/O server. I haven't written a CGI forking process. I haven't written a reverse proxy handler. Heck, I haven't written C in years. All sorts of reason why someone might want to write one of these. There's even a bunch of free tools to help test it (and who doesn't like free tests!). Until you put fingers to keyboard, you just don't know, it's all book learnin'.
- tmountain 3y agoGood for you. Great way to learn!
- deleted 3y ago[deleted]
- csdvrx 3y ago> Until you put fingers to keyboard, you just don't know, it's all book learnin'. This! Also writing a HTTP server seems like a hacker rite of passage, like creating your own lightsaber for a Jedi. So last Christmas, I did just that :) Personally, I like retrocomputing so I did mine in perl. I learned a lot of things, and I added a few "modern features" as extras like mDNS and cosmopolitan, because it's more fun to use something.local that 127.0.0.1) It's on https://github.com/csdvrx/PerlPleBean https://github.com/csdvrx/PerlPleBean and if you want to dig into mDNS, check the Bonjour part on https://github.com/csdvrx/PerlPleBean/blob/main/experiments/bonjour-server.pl https://github.com/csdvrx/PerlPleBean/blob/main/experiments/... It's very fun to be able to launch just one executable and then curl whatever.local
- robdelacruz 3y agoLove your project and enjoyed reading your extended README file. Perl and retrocomputing gives me a warm feeling inside.
- csdvrx 3y agoThanks! I've got to get back at it :)
- lionkor 3y agoShameless plug for when I attempted something similar, though multithreaded with pthreads: https://github.com/lionkor/http https://github.com/lionkor/http
- sgloutnikov 3y agoHere's also althttpd [0]. Heard Richard Hipp mention it and fossil in an interview. [0] https://sqlite.org/althttpd/doc/trunk/althttpd.md https://sqlite.org/althttpd/doc/trunk/althttpd.md
- qwertywert_ 3y agoThe amount of written functions/libs for opening c sockets has to be in the 100,000s at this point. And they are all slightly different.
- skulk 3y agoCool project, but this project demonstrates the reason I've stopped writing things in C. The standard library has garbage string functions and it seems every project has its own version of this file: https://github.com/robdelacruz/lkwebserver/blob/main/lkstring.c https://github.com/robdelacruz/lkwebserver/blob/main/lkstrin... It's fun to write this (and read others' versions) the first 3 or 4 times, but it gets old quickly.
- xmonkee 3y agoI have the same issue, but I blame the absence of good package management. If it had that, one of the thousands of these libraries would have won out and become quasi-standard.
- le-mark 3y agoI always thought the glib part of gtk was really nice for this, but adoption is spotty at best.
- ranger_danger 3y agoglib is a massive dependency just for this, and I think many would argue that gtk in general is not a good idea for painless cross-platform development in 2023.
- alex_lav 3y agoThis is how I felt writing Go. Writing the same nongeneric functions with slightly different type signatures and/or endless interfaces and/or interface{} signatures. It's 2023.
- 2h 3y agonever mind than MANY people dont need generics, and that generics have a significant compilation and runtime cost, in terms of time and memory. who cares right? and never mind that Go has had generics for over a year now right? sometimes having a small, stripped down language is better than having a huge bloated monster. I would point to examples, but you know what they are.
- samtho 3y agoThis may sound sort of “old man waves at cloud” of me but one thing I’ve found sad is the gross over-complication of later versions of standards such that the sort of project linked here may not be as practical for something like HTTP/3 for example. Similarly, the large, muddled tool chain that is “required” to make modern JavaScript applications makes it hard for newer learners to really understand what is going on because the minimal code version still needs its own transpiler, build system, linter, process managers, etc. Maybe we need all this complexity, but I suspect that some of the overzealous, solve-everything systems design we have come accustomed to is mainly serving to create a larger problem set instead of creating elegant abstractions that are agreed upon.
- skaushik92 3y agoI see what you’re saying and agree that HTTP3 is complicated but I would that since it’s a backwards compatible standard, the added complexities are completely optional. For most use cases the basic protocol is perfectly suitable and only as the scale evolves does it require the additional complexity.
- samtho 3y agoI understand what you’re saying, but if someone decides to post a link to their project that is an HTTP/3 server in under X lines of code but only implements HTTP/2 features, is it really an HTTP/3 web server?
- fsckboy 3y agothe HTTP/3 standard for servers is not backward compatible with HTTP/2 servers, it is backward compatible with HTTP/2 clients. And vice versa And therefore, an HTTP/2 server calling itself compatible with HTTP/3 clients is OK
- samtho 3y agoIt might be OK on a technical level, but my concern is where someone is showing off a project they used to supposedly learn how to implement HTTP/3 but only goes far enough to use an HTTP/2 implementation because fully implementing 3 is too complex or not worth it.
- adamrezich 3y agothis is a great opportunity to ask something I've been wondering about for awhile: what are the best options out there for hosting websites built as HTTP-serving executables (either Windows or Linux)? is it possible to do this relatively cheaply? I ask because I've been working on a framework[0] for building websites in a compiled language recently, and while it's been a ton of fun to build and test locally as a hobby project, I have absolutely no idea if it's even remotely financially viable to host a (small- to medium-sized) website made this way, compared to all of the managed hosting solutions out there for PHP/Node/etc. I don't want/need to pay for a whole dedicated server—I just want to serve HTTP (eventually HTTPS) from a single executable, using one or more SQLite database files. ideally, it would cost as close to your typical shared PHP host as possible. I have almost zero experience with "cloud" hosting—I made a small game with Node on Azure years ago, and accidentally racked up charges just playing around with it in development—so I don't know if this, or AWS, or whatever else is a viable solution for this. I've seen that it is indeed possible to host a single executable on Azure, but I haven't actually tried it myself, or determined what the pricing for this would end up being. [0] https://github.com/rezich/Newf https://github.com/rezich/Newf
- easytiger 3y agoYou need a VPS. Hundreds of providers available.
- torstenvl 3y agoNot exactly what you're looking for, but I'd use lighttpd and a CGI program.
- zokier 3y agoFor AWS simplest thing is to throw it into docker container (`FROM scratch` can work) and run in Fargate (AWS' container runtime). But its not super-cheap solution; baseline cost is something like $20/mo for Fargate and additional $20/mo for load-balancer. Lambda can work too, but it is in some ways bit more involved. Cheapest AWS solution would be just EC2 instances (=basic virtual machines). t3a.nano instances cost just $3.5/mo and do not require additional load-balancers. The modern cloudy approach would be to look into stuff like CloudFlare Workers, iirc they can run WASM, so if you manage to compile your code to that then it might work.
- leetrout 3y agoReminded me of a small C webserver: G-WAN http://gwan.com/ http://gwan.com/
- davidw 3y agoFor fun, does anyone have something like this in Rust? Curious about that language and this sort of thing would be fun to look at.
- imran-iq 3y agoIsnt it in the book? https://doc.rust-lang.org/stable/book/ch20-01-single-threaded.html https://doc.rust-lang.org/stable/book/ch20-01-single-threade...
- kragen 3y agoif you like this, you might like httpdito http://canonical.org/~kragen/sw/dev3/httpdito-readme http://canonical.org/~kragen/sw/dev3/httpdito-readme http://canonical.org/~kragen/sw/dev3/server.s http://canonical.org/~kragen/sw/dev3/server.s it's a 2-kilobyte executable written in i386 assembly that can handle 20000 requests per second on my laptop, but only serves up files from the filesystem; no cgi or reverse proxy instead of being single-threaded or preforking it just forks a child per request
- jaza 3y ago> If you don’t do that part, it will be over 4kB instead of under 2kB. If you really care about that, you’re probably insane. Love it!
- amadvance 3y agoTake care that select() is not good for a webserver. From manpage: WARNING: select() can monitor only file descriptors numbers that are less than FD_SETSIZE (1024)—an unreasonably low limit for many modern applications—and this limitation will not change. All modern applications should instead use poll(2) or epoll(7), which do not suffer this limitation.
- pjc50 3y agoLol. 22 years ago, I worked for Zeus Web Server, which was built entirely around one-process-per-core webserving off select(), and it was so much faster than Apache for serving static content that the developers had built a business out of it. At the time it could saturate a gigabit ethernet link off the largest HP-UX server we could find. Sure, you should use the modern interfaces, but 1024 connections per process can get you surprisingly far.
- robdelacruz 3y agoThanks for this. Saw the bug you logged on github too. Agree that poll() should be used instead to avoid the FD_SETSIZE limitation. Maybe in the future when littlekitten webserver grows to be a big cat...
- stevefan1999 3y agoI hate to say it, old man, we have Rust today and we can do things as efficient and as performant as you while being safer overall. We have tokio to handle all the IO stuff, we have hyper to handle HTTP parsing, and we even have tungstenite to handle websocket out of the box. While I appreciate your work but it will not be practical to write C anymore in the modern age. Well, unless you need to target something LLVM isn't there yet and maybe you need some weird GCC toolchain (cough cough AVR)
- easytiger 3y ago> While I appreciate your work but it will not be practical to write C anymore in the modern age. been hearing that for 20 years
- capableweb 3y agoIf you goal is to just reuse as much stuff as possible, which you seem allude to, then you should just use Apache/nginx/caddy directly. But the goal here doesn't seem to be that, so it makes sense to implement it without using as many libraries as possible. Both approaches are valid and serve different purposes, you seem to have misunderstood the purpose here.
- raxxorraxor 3y agoPeople will use C just to get away from Rustafaris (I know...) out of spite some day.
- easytiger 3y agoLike the people who took up python to get away from the unbearable Ruby zealots. Religious wars will persist
- robdelacruz 3y agoConfession: I write in C because it's fun and feels like you can do anything in it. Agree it's probably not the most practical or commercial-friendly solution. I like C!
- icar 3y agohttps://github.com/robdelacruz/lkwebserver/issues/2#issue-1713599224 https://github.com/robdelacruz/lkwebserver/issues/2#issue-17...