Simple API with Nginx and PostgreSQL
rny.io
rny.io
I see no concern about authentication, authorisation, scalability, protection from SQL injection attacks, nor making the output easily parseable by third-party applications.
None of these are issues you can simply say, "I'll deal with that later when it becomes a problem." They are reasons why an existing framework is helpful.
Any example of a web application using a database should NOT be using string concatenation for adding field values to an SQL statement. Ever. Really.
In the module he's using, there is a postgres_escape function.. so there's no reason he couldn't have used it.
It's unnecessary anyway. It would be way better would be if the parameters were bound as named parameters. Ex:
location ~ /articles/(?<id>\d+) {
postgres_pass database;
rds_json on;
postgres_query HEAD GET "SELECT * FROM articles WHERE id = $id";
postgres_rewrite HEAD GET no_rows 410;
}
See how $id has no quotes around it? The DB driver should parse the parameter and bind it as a string in that position. If you need to use it as a different data type (ex: integer) then you can do an explicit type conversion. That's how you prevent SQL injection.Not sure exactly what you mean here. The protocol and libpq support sending literal values entirely outside of the query itself. There is no reason for the DB driver to do any parsing.
I meant that libpq supports bind variables and the nginx module should be using them rather than performing a string substitution.
Django doesn't magically scale; you still need to a) learn how their ORM works and where it can be greedy or b) just use a "saner" ORM (eg. SQLAlchemy) or otherwise write your own without the need of a thousand features you don't need.
SQL... set variables with `postgres_escape` and not `set`, always.
Output... he returns appropriate responses, but between all the "RESTful" frameworks I've seen, they ALL have different opinions on what should be returned, what HTTP codes to use, etc. I'm not sure a framework helps, other than to inform you or get you stuck with their ridged paradigms.
Please make a little effort and expand on why this article is interesting instead.
For instance, people are using micro frameworks for a reason. They want less clutter and a more direct grab on what the machine is doing. With the proposed theoretical solution we get to remove one big complexity element in the setup, it is very interesting.
http://www.techempower.com/benchmarks/#section=data-r6&hw=i7...
However, you might also notice that this project uses Lua (specifically LuaJIT) to run embedded in the server. I would think this avoids the problems partially. There is even a new MVC project budding out of this for Lua/Moonscript called Lapis, if that really assuages your concerns. Seems pretty micro, so I am not sure it is meant to really handle your security concerns. It was used on a demo site for a web game shop site that made it here a few months ago. Check it out; it is pretty cool.
https://github.com/leafo/lapis
As pointed out before, few frameworks I have researched care about security. Ironically, I think web2py is the only I remember having dedicated page space on doing OWASP evaluation against their code base from a long time back: http://www.web2py.com/book/default/chapter/01#Security). Others rarely mention it, and are total crap security wise. As others pointed out, frameworks are little guarantee against security unless, like the language and dev experience itself, prepare to know what the hell you are doing.
Final point, a much cooler complement might be the "Web Application Firewall" projects built into the web server itself to block typical injection attacks. NAXSI, specifically for Nginx, is a cool project and I will look into soon. Maybe this will interest you to.
And yes, this approach should only be used for very simple APIs. If you're building something bigger, use a framework.
Riak does too - any DB that implements a RESTful interface to the database instead of a binary protocol.
CouchDB is particularly well-suited for this use-case though (I would never use Riak in that fashion).
Fantastic.
Of course, one could easily use the async API in a non-async manner, so I'm not 100% certain.
I used android async-http to talk to the server from my app to have everything online. This is an intranet app so latency is not really an issue.
i.e. PUT to "/api/blah" with {"id": 1, "name": "Joe"} could call the update_blah stored proc passing in that json.
Unfortunately, it seems a bit awkward to differentiate between empty and NULL strings. That's something to be careful of.
Also, I really think this should be included in the blog post, even if it's simple. Protecting against SQL injection is not optional, so leaving it out only muddies the comparison with more traditional frameworks. Also, there's always going to be someone that copies and pastes it without thinking much about it.
That being said, this is very cool and I hope to see more development and exploration in this area.
This behavior actually is what anyone who has used Oracle is accustomed to (empty string is NULL). I don't recall the default behavior in Postgres but Postgres is "Oracle-ish" in a lot of ways so I would be surprised if this is not the default there as well.
Don't get me wrong -- it's still a pretty neat idea. It's just there's that "other 90%" (i.e. the necessary work to create anything seriously production grade) that always comes to mind when evaluating a new interface.
I still like the idea of nginx being able to communicate with different datastores. For example, let's say you want to serve a file but it requires authentication, you can pass some signed request via query string and cross check it in session in redis/postgres wherever.
This looks like a very nice way to build small simple REST APIs especially if you're already using nginx and postgres anyway.
maybe not perfect for a whole app but maybe depending on your goals.
@subs: thanks!
[1]: https://github.com/TechEmpower/FrameworkBenchmarks/tree/mast...
This helped me setting up nginx/lua/redis setup on Ubuntu https://github.com/ehazlett/nginx-rt-log/blob/master/readme....
This setup is powerful by its simplicity. Only two layers. And stored procedures can help you do validation, so one could imagine a full Twitter like implemented this way (lest the ui, obviously)
but are there any performance benchmarks ? I suppose nginx would have a better performance.
I'd also venture that this is an order of magnitude faster and more responsive than a framework so there are definitely some plusses and minuses to consider.
After authentication, you have the credentials needed check authorization, it'd probably just involve a few changes to the SQL in the article.