Raphters, a web framework for C
github.com
github.com
On the other hand, if I was going to release a web framework, I might do more to abstract request variables (provide a params hash like Rails, or a Rack-style request hash). Also: I'd probably build it on libevent's evhttp instead of demanding that users plug my C code into FCGI.
But if you're going to do a C web framework (and... really? you sure about that?), that's probably how you should do it.
Which, these days, isn't a huge deal. Both of these are decent:
https://github.com/ry/http-parser
https://github.com/mongrel/mongrel/blob/master/ext/http11/ht...
I've never used either but I'm looking at gevent for a project, and I noticed that they switched to libev: http://software.schmorp.de/pkg/libev.html ... do you know what "limitations and bugs" in libevent they speak of? I poked through the mailing list for libev and couldn't find anything specific.
My guess about "limitations" of libevent is that it's primarily that libevent is anchored to global state and needs to own the event loop for the program. So, for instance, to get it working in Cocoa apps, I have to spawn off a libevent thread. And I can only have one of them.
But this isn't really a big deal for me; once I got the libevent thread working, everything was peachy for me.
In no other context do I ever, ever have any need to do anything funky with how I include libevent; 90% of programs that use libevent are designed from the outset to use libevent and don't benefit from flexibility about the event library.
Libevent vs. libev really seems like a Linux vs. BSD kind of debate. I'd always choose libevent over libev, but you can apparently get a performance improvement (which is probably going to be marginal compared to other simple things you can do to speed up an evented program) by going with libev. And it looks like if you're doing clientside dev, like building a new browser or file transfer client, that libev is easier to embed.
Honestly, in addition, I'd like to see something like Rack for C. The "gateway interfaces" for C are too implementation-specific (CGI, FastCGI, SCGI, web server extensions/modules, etc). It would be something more abstract that would run on-top of a web server interface.
void application_main(web_request *request, web_response *response)
{
char body[1024];
snprintf(body, sizeof(body), "Hello, %s", request->param("username"));
response->status(200);
response->header("Content-Type", "text/html");
response->write(body);
response->end();
} response_set_status(200);
response_set_header("Content-Type", "text/html");
response_write(body);
response_end();
The awkwardness of which, to me, demonstrates the superiority of C++ in this regard. response_complete(200, body, response_header("Content-Type", "text/html"));There are various solutions that still allow you to pass a set of closures without being particularly more ugly than anything else is in C, for instance, see http://library.gnome.org/devel/gobject/stable/chapter-signal... . C++ still ends up nicer, my point is just that you can do good things in C and there are libraries that implement the stuff for you.
That said, if I were really going this route I probably would try to go with some sort of minimal C++. Then again, my opinion is suspect, as I would never go this route anyhow. Web developers writing in languages that don't permit buffer overflows write software that has all the security of a colander; adding the ability to write good, solid buffer overflows as well hardly seems like a step up. You can write secure C code, but you can write secure PHP code, too. Existence proofs of secure code aren't very interesting.
It's a beautiful sentiment. It hasn't worked. Handing them new vectors to screw up in is not going to solve the problem.
It also doesn't matter. Hand a developer a tool that requires them to continuously pay attention to an issue and no matter how good they are, at some point they will slip, because they're human. We've tried "teach them about security" a couple hundred times, maybe it's time we try "devise a language that can't trivially express an insecure application". C will not be the language that implements that, it completely lacks any of the necessary primitives, by design.
response_set_status(response, 200);
no issues with global state, threading (if correctly mutexed), etc...
http://pocoproject.org/docs/Poco.Net.HTTPResponse.html
http://pocoproject.org/docs/Poco.Net.html
Doing this in C seems silly to me.
response_set_status(handle, 200);
My point was that the syntax in the example was C++.Yes. My preference in web apps (esp in C) is also to deal directly with http requests and responses. Although I wouldn't necessarily call that the "more abstract" approach. To an extent, each of these gateway interfaces is a different leaky abstraction for http.
char *hsafe(const char *input);
But where does hsafe get the memory for the string from? It can't use input (the filtered result is larger than the input). Does it malloc? Now you have to free the result. Does it do the inet_ntoa() thing with the static variable? Now you can't chain it (or use threads, but you wouldn't want to do that anyways).Maybe you can do an arena for each connection, so it's:
char *hsafe(request_t *r, char *str)
But that's still sort of painful.† In an admittedly artificial way.
Which is to say it's only a problem if you are doing it by hand on a per field basis. Which leads to your next point:
> Maybe you can do an arena for each connection, so it's:
> char *hsafe(request_t *r, char *str)
> But that's still sort of painful.
This is only painful if you are doing it by hand every time you use the parameter. If the framework handles it for you, so that you always get the sanitized result, it strikes me as no different than any other language.r->param("input"); // presanitized, lazily created, pooled in r
r->param_raw("input"); // if you want to live dangerously
Why is this worse in straight C than in something like Python that is doing the same thing but with an interpreted layer between you and the C?
Certainly it's harder if you decide that you are going to work from the ground up in straight ANSI C, but there's lots of good pool memory allocators out there. I'd either use one I had laying around, or just link in the one from the Apache Portable Runtime: http://apr.apache.org/docs/apr/1.4/group__apr__pools.html
The framework author could easily hide this behind the scenes, so that the user would find the string creation and destruction just as seamless as in Perl or Python. Use it and forget it, and the pool would be freed along with the Request. Thus my question, and my confusion, was why you finished with "But that's still sort of painful."
Then again, if you have a sane string handling library in C instead of messing around with strcpy/strcat, malloc/free and fixed-sized buffers, I guess it could be made more convenient.
so that the user would find the string creation and destruction just as seamless as in Perl or Python
If you manage to do that, please send me the link :)
write_quot(response,"this < should be safe >");
Not perfect (you still need to deal with allocating temporaries if you want to inspect the contents before sending to the client), but: it (a) matches what's actually going on under the hood, (b) makes the simple cases safe, (c) provides a decent interface for safely extending the available formatters. (They would write their output to the stream, then free all temporary resources themselves before returning.)(Further, I've had enough influence from statically-typed-land that I'd personally want to create tainted wrapper structs so that the compiler helps prevent user data from being passed to an unquoted write... but that's just me.)
What I'd really like to see is not so much a web framework in Lua (there are a few, I'm working on another one, and it's really not hard to make one either), but rather one that's mostly C but lets you use Lua, say, for templates or controller functions. That could be pretty interesting for very small devices, or for squeezing lots of performance out of a larger one, all while stilling letting you program the bulk of your code in a higher level language.
Embed the Power of Lua into NginX https://github.com/chaoslawful/lua-nginx-module
And if the server is not high-performing, mongrel2 + $something can be a very good choice. (And has a more liberal license).
But of course, the tastes differ - so the more, the merrier. as soon as the folks do not get pwned.
But yeah, LuaJIT recently added support PPC and soon will add ARM, so point well taken - to do what I'm thinking of, it may not really be necessary to have anything in C.
(Or more probably since it's 2011, I'd try an nginx module (or lightty), although I have never looked at any of those projects code yet).
Building response stuff in C is pretty high maintenance stuff though.
I'm at work so I can't setup a server to test, however after summoning my inner compiler my changes seem sane. But you should look them over (check the pull on github https://github.com/DanielWaterworth/Raphters/pull/2).
I'll be around if you want to discuss a proper fix for some of the issues. Albeit it will take a pretty major rewrite.
I've write code that looks nearly identical to C in Haskell all the time. (Except, of course, that `alloca` is faster than malloc and is garbage-collected.)