27 ms·
Show HN: Hosting my website using my C web server
- cozis 2y agoHello everyone! This is a fun little project I started in my spare time and thought you'd appreciate :)
- yazzku 2y agoAppreciated indeed. I happened to want to mess around with the C11 concurrency API and write a server of sorts, mostly as a curiosity of how those constructs work out in C coming from C++.
- sim7c00 2y agoI find it an interesting excersize to read through really old bugs and CvE for http servers to see what might affect my code too. and see how to fix it. nic3 going though =) fun to roll this kind of stuff yourself!
- TZubiri 2y agoNice. I've done this in the past. But I feel like attempting to make a file serving http server is like adding preservants and high fructose corn syrup to home made baked goods. You have the opportunity to really make something custom and of high quality, hard code the paths of your files and avoid a whole class of vulnerabilities for example. Configuration files? That makes sense when programmer and sysadmin are distinct, you can just modify variables and recompile.
- jagged-chisel 2y agoNot sure if serious…
- heyoni 2y agoNot the only time it’s been brought up in this thread: https://news.ycombinator.com/item?id=41643198 https://news.ycombinator.com/item?id=41643198 I’m waiting for someone to chime in and explain why that would be a bad idea cause I can’t think of it from a security perspective.
- its-summertime 2y agoOnce at a certain level of complexity, e.g. having several hundred/thousand resources, then you start automating your hardcoded paths, and then you still can get bitten. vs just putting things in a subfolder of your repo or whatever and having the default handling not accept `..` path components
- TZubiri 2y agoBut OP isn't reaching that certain level of complexity, doesn't have thousands of resources, he is hosting his own website.
- sabas123 2y agoFrom a security perspective a lot of changes to this world would be an upgrade. However implementing security features is always a trade off, and sometimes good security is just not worth the loss of other things.
- TZubiri 2y agoMy favourite phenomenon is when (computer) security gets in the way of (actual) security. For example, you implement a super secure solution and no one hacks your website, but you end up being very unproductive and can't find a job. You lost food security. In covid, bank systems in my country were so hard to use, there were like 6 passwords to login. Not only was usability compromised in the sense of security, but people, especially old people, started lining up in banks, compromising health security. To say nothing of the scenarios were users just bypass obnoxious exaggerated security systems, like leaving a post-it note with a password on their screens.
- iveqy 2y agoI think you'll like dwm and other suckless tools. They have configuration as code and require a recompile after a configuration change.
- system7rocks 2y agoThis is amazing. Seriously, more things should be custom-coded. Why not?
- bosch_mind 2y agoFor fun, sure. Small mistake can be big security nightmare
- whiterknight 2y ago1000 lines are easier to secure than 5 million lines
- agentultra 2y ago“You can write software that has no obvious bugs or you can write software that obviously has no bugs.” I think that was ewd?
- naniwaduni 2y agoYou can, of course, also write programs that have known bugs. Or even programs that have bugs that obviously shouldn't be there, but are anyway.
- mplewis 2y agoNot if you’re the only author!
- victorbjorklund 2y agoNot if 1000 lines are written by you alone and not checked by anyone else vs 5 million lines of code written by thousands of people and checked by countless more. Linux is probably more secure than 1000 lines of C code from a junior developer.
- whiterknight 2y agoI think this is vastly overrated: - how much code actually gets read outside of top 2-3 projects? - how many of those readers can detect security problems? - why are others inherently better at detecting problems than the author? Wouldn’t 1000 lines read by 2 people be better than a million read by 10?
- marcodiego 2y agoHow about embedding the contents of the HTML files so that no access to the filesystem is required? That would make it not only faster but also safer.
- kevin_thibedeau 2y agoI recommend linking a romfs image into the program. It's a simple format and provides an easy way to manage a collection of resources.
- knowitnone 2y agodoes that mean recompile every time them HTML is changed? No thanks :)
- TZubiri 2y agoA nice intermediate I use is baking the paths into the source code, so that I only recompile when I add files, but I can hot-swap contents without even restarting the server. Although if you start caching contents in memory (which is faster) you would have to at least kill the server and restart it. Or signal a reload.
- remram 2y agoSeems like the worst of both worlds. You need to recompile for content changes, and you need to distribute multiple files.
- SPascareli13 2y agoOnly 3.4k of C code for a full http and https server? I honestly thought you would need a lot more for it to be fully compliant with the spec.
- ironhaven 2y agoHttp/1.1 is dead simple if you ignore most of the spec. If you only take get requests and set content-length on response you will be good for 99% of user agents. It’s not much more code to handle the transfer-encoding and byte-range headers. HTTPS is just http over a tls socket which is the level of abstraction you should have if you don’t roll your own crypto. It’s fun and not that bad really.
- AnotherGoodName 2y agoYeah I’ve done this for embedded devices. A website can be presented with nothing more than a raw socket and sending back a text string of http headers and html in a single text string when people connect to it. Hell if you’re really lazy you can forgo responding with the http headers and just socket.write(“hello world”) as the response and all the major browsers will render “hello world” to the user. Properly formatted http headers are just a text string extra and the html is just text. There’s not much to it.
- sph 2y agoWhy HTTP/1.1? Everybody speaks HTTP/1.0 and it is even simpler.
- matja 2y agoLack of IP(v4) addresses. HTTP/1.0 sends no Host header, so cannot implement name-based virtual hosts. HTTP/1.1 does.
- folmar 2y agoAnd TLS can be handle by kernel if you target linux only. https://docs.kernel.org/networking/tls.html https://docs.kernel.org/networking/tls.html
- xyst 2y agolooks like it’s survived the HN front page hug. Congrats.
- greenavocado 2y agoFinally a website that doesn't crash when it shows up on the front page
- rubyn00bie 2y agoUhh… doesn’t the link go to GitHub? I’m a little confused by this comment. I mean the project is neat and cool. But I imagine most folks go to GitHub and don’t go to the link showing the webpage. Am I missing something?
- wilkystyle 2y agoLink to the actual site is at the top of the GitHub page.
- afavour 2y agoAny site with a CDN in front of it can do that. Don’t get me wrong this is an awesome project but if you really care about this kind of thing in a production scenario and you’re serving mostly static content… just use a CDN. It’ll pretty much always outperform just about anything you write. It’s just boring.
- kqr 2y agoAny site that consists of static files served by a professional-grade web server like nginx on a small VPS can also trivially do that.
- interroboink 2y agoIf you're hosting static data, shouldn't HTTP cache flags be enough in most cases? Read-only cacheable data shouldn't be toppling even a modest server. Even without an explicit CDN, various nodes along the chain will be caching it. (though I confess it's been some years since I've worked in this area)
- christina97 2y agoThat’s not the case these days. Due to TLS, there is very little catching in between you and the server you’re hitting.
- ezekielmudd 2y agoI love it! It’s fast! I have always wanted to try out something like this. Good job!
- chairmansteve 2y agoI did something similar in LabView once. There were reasons.....
- danpalmer 2y ago> Show HN: Hosting my website using my own C web server "But if you actually do this, WAT" – https://www.destroyallsoftware.com/talks/wat https://www.destroyallsoftware.com/talks/wat As with much of HN, this is fun, a good thing to learn while making and reading about... but it likely needs the caveat that doing this is production isn't a good idea (although in this case the author does not appear to encourage production usage).
- x3haloed 2y agoIt’s a great way to get hacked
- deleted 2y ago[deleted]
- dailykoder 2y agoI'd assume most people would know that? But if they still put random code that someone wrote just for fun into a (serious) production system, then WAT. Edit: And sure, if the author is lucky, then maybe a handful of people will gather around the code and try to make it "production ready". But since the README doesn't say anything about the topic at all, just let people have fun and learn things along the way?
- litbear2022 2y agoYou may be interested in this https://news.ycombinator.com/item?id=27431910 https://news.ycombinator.com/item?id=27431910 > As of 2024, the althttpd instance for sqlite.org answers more than 500,000 HTTP requests per day (about 5 or 6 per second) delivering about 200GB of content per day (about 18 megabits/second) on a $40/month Linode. The load average on this machine normally stays around 0.5. About 19% of the HTTP requests are CGI to various Fossil source-code repositories.
- cozis 2y agoThis post was of great inspiration! It made me realize something like this was doable
- theideaofcoffee 2y agoAwesome! I used to think (well, I still do) that getting a barebones service up and running using the system APIs at the lowest level like this is so satisfying. It's sort of magical, really. And to see it serve real traffic! I'm kind of surprised that the vanilla poll() can put up numbers like you were seeing, but I guess it's been a while since I've had to do anything event related/benchmark at that level. I love the connection-specific functions and related structs and arrays for your connection bookkeeping, as well as the poll fd arrays. It's very reminiscent of how it's done in lots of other open source packages known for high throughput numbers, like nginx, redis, memcached. Great work!
- yard2010 2y agoWorking with c/cpp in uni exploded my mind. It's such a specific humbling experience that has a bit of anything I love - engineering, history, culture, linguistics, etc. It made me think that anyone should know and try every possible language (programming or otherwise) - "thinking" in a language is such a unique experience. The different contexts make everything feel different, even though it's more of the same. The perspective change, and changes the subjective experience. For example - to really understand the nature of linux or git, you have to speak its language and understand the nuances that are usually lost in translation. Tangibly, to understand the true subjective meaning of the word "forest" in russian one has to speak and understand russian. The context changes the perspective, so sometimes it changes everything.
- ggliv 2y agoThis is a neat perspective. I’ve heard conversation on how working with different programming languages affects how you code (“learn Haskell, it’ll make you think more functionally!”) but for some reason I never connected it to the linguistic side of things. I remember learning about the effects of language on cognition in a psychology course I took a while ago, it’s interesting to think about how that could apply more broadly.
- ryandrake 2y agoIt’s kind of sad how C has gotten the reputation as this dangerous and scary dark art that only wizards can successfully wield. C was my first love, it’s what we used throughout university, it’s what our operating systems and basic tools are all written in... If you go to your favorite language and step down into the actual implementation of, for example, your network calls, you’re eventually going to get to poll() and write() written in C. It’s useful to know and be fluent in regardless of whether you intend to work on large projects in C.
- kristianpaul 2y agoNot to compare but i realice this is something you can do with rust with few lines https://github.com/actix/actix-web/tree/master/actix-http https://github.com/actix/actix-web/tree/master/actix-http
- theideaofcoffee 2y agoLook ma, I can do it in python! $ python3 -m http.server
- Alifatisk 2y agoOr Ruby $ ruby -run -e httpd .
- ustad 2y agoYou call that a few lines of code!?
- p0w3n3d 2y agobut not in 76 KB
- cozis 2y agoit's just a few lines because you're hiding the other ones
- Ono-Sendai 2y agoMy blog (https://forwardscattering.org/ https://forwardscattering.org/) uses a C++ web server too: https://github.com/Ono-Sendai/blog https://github.com/Ono-Sendai/blog
- deleted 2y ago[deleted]
- gonzus 2y agoKudos for your project -- it is great fun and a learning experience to implement your own HTTP server in a low(er)-level language. One question: you say that "Transfer-Encoding: Chunked responds with 411 Length Required, prompting the client to resend with Content-Length". Is there a reason for doing this (security perhaps), or is it just a choice?
- gonzus 2y agoSorry for answering myself. I paid more attention now, and it seems this is disabling chunked transfer encoding from the client to the server, which makes sense from a security / reliability PoV. Disabling it from server to client does not (IMHO).
- v3ss0n 2y agoNginx is C web server.
- nineteen999 2y agoSo is Apache and OpenBSD httpd and probably too many others to name. Node.js is written in C/C++ as is Litespeed, probably Cloudflare Server as well. Microsoft IIS is written in C++. So that accounts for about the top 5 ...
- v3ss0n 2y agoHeh ,Then python and php are included as C web servers too
- ifail_for_fun 2y agocool project, but the readme has a disingenuous comparison bench against nginx. why even put it there?
- cynicalsecurity 2y agoWhy? How is this better than running nginx or Apache2?
- rauli_ 2y agoSometimes it's just fun.
- cromulent 2y agoGreat project. Down for me. $ curl http://playin.coz.is/index.html http://playin.coz.is/index.html curl: (7) Failed to connect to playin.coz.is port 80 after 166 ms: Couldn't connect to server
- arethuza 2y agoThat exact command line worked for me - might there be something on your end blocking outgoing plain HTTP requests?
- justmarc 2y agoIt's a fantastic way to make a random, newly written web server in C safe and secure.
- cozis 2y agoHey, just checked. Server didn't crash. I wonder what happened?
- rwmj 2y agoCool! I also wrote my own C web server (sources linked below) which ran a commercial website for a while. It's amazing how small and light you can make an HTTP/1.1 webserver. The commercial site ran on a machine with 128MB of RAM and 1 CPU (sic) and routinely served a large proportion of schools in the UK with a closed source interactive, web-based chat system. However that was 20 years ago when the internet was a slightly less hostile place. He mentions bots make great fuzzers, but I think he should also do a bit of actual fuzzing. http://git.annexia.org/?p=rws.git;a=tree http://git.annexia.org/?p=rws.git;a=tree Requires: http://git.annexia.org/?p=c2lib.git;a=tree http://git.annexia.org/?p=c2lib.git;a=tree http://git.annexia.org/?p=pthrlib.git;a=tree http://git.annexia.org/?p=pthrlib.git;a=tree
- kragen 2y agothis looks much more practical than my own small and lightweight http/1.0 webserver, but i'm guessing that rws is not nearly as small and lightweight: http://canonical.org/~kragen/sw/dev3/server.s http://canonical.org/~kragen/sw/dev3/server.s http://canonical.org/~kragen/sw/dev3/httpdito-readme http://canonical.org/~kragen/sw/dev3/httpdito-readme the really surprising thing about that was that when your memory map only has five 4k pages in it, linux gets really fast at forking
- rwmj 2y agoIt operated in the real world (of 20 years ago), and supported in-process dlopened modules which is how the web-chat was implemented, so it was somewhat non-trivial.
- kragen 2y agoalso, i'm assuming, comet, and thus long-lived connections that were in communication with each other, whereas httpdito spawns off a separate child process for each request and thus can fob off all the memory allocation and i/o multiplexing work onto the kernel comet was a pretty compelling reason to write your own web server 20 years ago
- p0w3n3d 2y agoI like the string handling, especially #define LIT(S) ((string) {.data=(S), .size=sizeof(S)-1}) #define STR(S) ((string) {.data=(S), .size=strlen(S)})
- p0w3n3d 2y agoI wonder how small the hosting machine can get btw. 8 bit atari seems to small (76 kb of compiled code on my arm64, but it wouldn't get much smaller), however some atmega would suffice I guess
- xmodem 2y ago> No reverse proxies required! This is one that has always baffled me. If there's no specific reason that a reverse proxy is helpful, I will often hang an app with an embedded Jetty out on the internet without one. This has never lead to any problems. Infra or security people will see this and ask why I don't have an nginx instance in front of it. When I ask why I need one, the answers are all hand-wavy security or performance, lacking any specifics. The most specific answer I received once was slow loris, which hasn't been an issue for years. Is reverse proxying something we've collectively decided to cargo cult, or is there some reason why it's a good idea that applies in the general case that I'm missing?
- arielcostas 2y agoI think people do it out of habit at this time. In many cases it makes sense to handle TLS termination and compression, but in other instances it really is there for no reason. Proxying is always less-performing than serving directly since you add another layer in between, right? Or am I missing something?
- xmodem 2y agoJetty implements both TLS and compression, though in environments where I don't already have automated certificate issuance infrastructure in place I have occasionally deployed caddy as a reverse proxy just for the TLS termination.
- fny 2y agoMost web applications are not written in Java. NGINX also allows static assets to be served directly while side-stepping the application server. This is a boon for interpreted languages.
- xmodem 2y agoAnd that is a perfectly valid performance reason for adding an nginx layer in front. It does not IMO justify it in the general case however.
- seumars 2y ago>I enjoy making my own tools and I'm a bit tired of hearing that everything needs to be "battle-tested." So what it will crash? Bugs can be fixed :^) I love it
- knowitnone 2y ago[flagged]
- tptacek 2y agoBe respectful. Anyone sharing work is making a contribution, however modest. https://news.ycombinator.com/showhn.html https://news.ycombinator.com/showhn.html
- brennopost 2y agoMaking a HTTP/1.1 server is so fun and teaches so much about networking. I highly recommend anyone interested in networking or web development give it a try.
- kopirgan 2y agoLike this sort of approach.. Go back to basics and use what's strictly required. Remember McNealy (?) once said you can choose dozen different shapes Microsoft word uses to highlight spelling errors or something to that effect. There's lots of bloat in practically every software not sure how much it affects performance but it's nice to build something from scratch. Congrats to developer
- synergy20 2y agoI use lighttpd which is lighter and simpler than nginx
- petee 2y agoAside, if you want to write C apps but aren't comfortable writing the public facing parts, 'Kore' is a great framework with some handy builtins like ACME cert management, Pgsql, curl, websockets, etc. Essentially build and run modules, and they can be combined (including mixing Lua/Python + C.) https://kore.io/ https://kore.io/
- adamrezich 2y agoVery cool! I was working on something similar at one point, but I sort of gave up on it when I wanted to move it from the "toy server that works on localhost" stage to something that I could actually deploy in the wild. I got overwhelmed by decision paralysis for how to proceed: should I just use a reverse proxy? Or should I rewrite my backend code to be some kind of plugin for some existing server software? If so, what kind of plugin, and for which software? It's very inspirational to see that you've just said screw it, I'm going to host my own HTTPS server, and also hey reddit, do your worst, try to break it. Now I want to work on my similar project again. For anyone similarly inspired, but who doesn't know where to begin making an HTTP server, check out this excellent tutorial that walks you through everything you need to make an HTTP/1.0 server, and then grow it to handle HTTP/1.1: https://www2.cs.uh.edu/~gnawali/courses/cosc6377-f12/p1/http.html https://www2.cs.uh.edu/~gnawali/courses/cosc6377-f12/p1/http...
- panzi 2y agoReminds me of that Chaos Communication Congress talk about a blog/web server written in C, but with a bunch of security features (immutable storage, dropped privileges, blog has no access to TLS certificate, etc.): https://www.youtube.com/watch?v=TaE28fJVPTk https://www.youtube.com/watch?v=TaE28fJVPTk
- jpc0 2y ago> No Transfer-Encoding: Chunked (responds with 411 Length Required, prompting the client to resend with Content-Length I've always wanted to undertake a project similar to this but chunked encoding has always been the thing that put me off the idea... I never even though about just not supporting that :) I've written many http/1.1 servers in the past but only for internal stuff that I also controlled the clients. Guess perfection was the enemy of good for me.
- broknbottle 2y agoNice, now lets see Paul Allen's web server.
- Turboblack 2y agosome time ago (about 20 years) I used smallhttpserv - a program that weighs a couple of dozen kilobytes and works even in early Windows surprisingly, it still works