I'm a noob at nginx and lua. But I'm trying to design a REST interface.

The plan is to create a location entry that will match URIs like this:

curl -i -X GET 'http://localhost/widgets/widget?name=testname&loc=20000' -H "Accept:application/json"


curl -i -X POST 'http://localhost/widgets/widget?name=testname&loc=20000&price=10.12' -H "Accept:application/json"

I want to return data like this:

HTTP/1.1 201 Created
Server: nginx/1.6.2
Date: Wed, 25 Feb 2015 13:32:24 GMT
Content-Type: application/json; charset=utf-8


What I've come up with so far:

Within the location block / context, I'm going to test what the request method is (GET vs. POST vs. DELETE) and then execute logic inside separate lua files to do all the CRUD operations. So for example, notice the following quasi pseudo code:

  #curl -i -X GET 'http://localhost/widgets/widget?name=testname&loc=20000' -H "Accept:application/json"
    location /widgets/widget {
            default_type "text/pain";
            #ifisEvil... unless done inside lua
            content_by_lua '

                    if ngx.var.request_method == 'GET' then
                            add logic to call "read_widget.lua"
                            somehow save results from read_widget.lua in string
                            response.body = results_string
                            convert results_string to json format.
                            return results_string_as_json 
                    elseif ngx.var.request_method = 'POST' then
                            add logic to call "create_widget.lua"
                            same logic as GET...
                    elseif ngx.var.request_method = 'DELETE' then
                            add logic to call "delete_widget.lua"
                            same logic as GET...


  1. Is this the right approach to take? Specifically, is it possible to call methods in external files and return large amounts of data from them back in the nginx.conf file?
  2. Even if it's possible, is it a good idea? These external files will contain logic to connect to the datasource, massage the data and then prepare the correct HTTP response... like 201 for new resources, 404's etc etc.

Thanks everyone.

2 Answers 2


Yes, it is a fair architecture - the concept of a web server taking requests and the passing the call on to another server to process is almost certainly best practice in all cases. At least theoretically you could then hosts your logic files on one or more application servers if load gets too great. Even if this doesn't apply to you right now, its still good to have the flexibility, especially if you end up reusing some of this code in the future.

However, write your 'business logic' files so they do not have any understanding of the http request, so they return normal error codes that are translated into something more http-y by the webserver side of things.

You might also like to see some helper code like lua-resty-rack


If I were you, I would definitely check out Lapis. It's a very lightweight and fast Lua framework for OpenResty. I've really been enjoying it and predict it will have a bright future!


With it you can easily write a REST API that returns json with code as simple as:

app:get("list_users", "/users", function(self)
    local users = Users:select() 
    return { json = { users } }

A post can be done like this:

app:post("/user/new", json_params(function(self)
    self.user = Users:create({
        email = self.params.email,
        password = self.params.password,
        fname = self.params.fname,
        lname = self.params.lname
    return { json = { self.user } }

The other HTTP verbs can all be handled with similar ease.

Also, as you might expect with anything built to leverage OpenResty, Lapis benchmarks are insanely good: https://www.techempower.com/benchmarks/#section=data-r12&hw=peak&test=query

To boot, the author of Lapis also wrote a CoffeeScript-like language for Lua called MoonScript which is quite nice @ moonscript dot org

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.