Apache > HTTP Server > Documentation > Version 2.4 > Modules

Apache Module mod_lua

Available Languages:  en  |  fr 

Description:Provides Lua hooks into various portions of the httpd request processing
Module Identifier:lua_module
Source File:mod_lua.c
Compatibility:2.3 and later


This module allows the server to be extended with scripts written in the Lua programming language. The extension points (hooks) available with mod_lua include many of the hooks available to natively compiled Apache HTTP Server modules, such as mapping requests to files, generating dynamic responses, access control, authentication, and authorization

More information on the Lua programming language can be found at the the Lua website.


This module holds a great deal of power over httpd, which is both a strength and a potential security risk. It is not recommended that you use this module on a server that is shared with users you do not trust, as it can be abused to change the internal workings of httpd.

Support Apache!



Bugfix checklist

See also


Basic Configuration

The basic module loading directive is

LoadModule lua_module modules/mod_lua.so

mod_lua provides a handler named lua-script, which can be used with a SetHandler or AddHandler directive:

<Files "*.lua">
    SetHandler lua-script

This will cause mod_lua to handle requests for files ending in .lua by invoking that file's handle function.

For more flexibility, see LuaMapHandler.


Writing Handlers

In the Apache HTTP Server API, the handler is a specific kind of hook responsible for generating the response. Examples of modules that include a handler are mod_proxy, mod_cgi, and mod_status.

mod_lua always looks to invoke a Lua function for the handler, rather than just evaluating a script body CGI style. A handler function looks something like this:

-- example handler require "string" --[[ This is the default method name for Lua handlers, see the optional function-name in the LuaMapHandler directive to choose a different entry point. --]] function handle(r) r.content_type = "text/plain" if r.method == 'GET' then r:puts("Hello Lua World!\n") for k, v in pairs( r:parseargs() ) do r:puts( string.format("%s: %s\n", k, v) ) end elseif r.method == 'POST' then r:puts("Hello Lua World!\n") for k, v in pairs( r:parsebody() ) do r:puts( string.format("%s: %s\n", k, v) ) end elseif r.method == 'PUT' then -- use our own Error contents r:puts("Unsupported HTTP method " .. r.method) r.status = 405 return apache2.OK else -- use the ErrorDocument return 501 end return apache2.OK end

This handler function just prints out the uri or form encoded arguments to a plaintext page.

This means (and in fact encourages) that you can have multiple handlers (or hooks, or filters) in the same script.


Writing Authorization Providers

mod_authz_core provides a high-level interface to authorization that is much easier to use than using into the relevant hooks directly. The first argument to the Require directive gives the name of the responsible authorization provider. For any Require line, mod_authz_core will call the authorization provider of the given name, passing the rest of the line as parameters. The provider will then check authorization and pass the result as return value.

The authz provider is normally called before authentication. If it needs to know the authenticated user name (or if the user will be authenticated at all), the provider must return apache2.AUTHZ_DENIED_NO_USER. This will cause authentication to proceed and the authz provider to be called a second time.

The following authz provider function takes two arguments, one ip address and one user name. It will allow access from the given ip address without authentication, or if the authenticated user matches the second argument:

require 'apache2' function authz_check_foo(r, ip, user) if r.useragent_ip == ip then return apache2.AUTHZ_GRANTED elseif r.user == nil then return apache2.AUTHZ_DENIED_NO_USER elseif r.user == user then return apache2.AUTHZ_GRANTED else return apache2.AUTHZ_DENIED end end

The following configuration registers this function as provider foo and configures it for URL /:

LuaAuthzProvider foo authz_provider.lua authz_check_foo
<Location "/">
  Require foo john_doe

Writing Hooks

Hook functions are how modules (and Lua scripts) participate in the processing of requests. Each type of hook exposed by the server exists for a specific purpose, such as mapping requests to the file system, performing access control, or setting mime types:

Hook phase mod_lua directive Description
Quick handler LuaQuickHandler This is the first hook that will be called after a request has been mapped to a host or virtual host
Translate name LuaHookTranslateName This phase translates the requested URI into a filename on the system. Modules such as mod_alias and mod_rewrite operate in this phase.
Map to storage LuaHookMapToStorage This phase maps files to their physical, cached or external/proxied storage. It can be used by proxy or caching modules
Check Access LuaHookAccessChecker This phase checks whether a client has access to a resource. This phase is run before the user is authenticated, so beware.
Check User ID LuaHookCheckUserID This phase it used to check the negotiated user ID
Check Authorization LuaHookAuthChecker or LuaAuthzProvider This phase authorizes a user based on the negotiated credentials, such as user ID, client certificate etc.
Check Type LuaHookTypeChecker This phase checks the requested file and assigns a content type and a handler to it
Fixups LuaHookFixups This is the final "fix anything" phase before the content handlers are run. Any last-minute changes to the request should be made here.
Content handler fx. .lua files or through LuaMapHandler This is where the content is handled. Files are read, parsed, some are run, and the result is sent to the client
Logging LuaHookLog Once a request has been handled, it enters several logging phases, which logs the request in either the error or access log. Mod_lua is able to hook into the start of this and control logging output.

Hook functions are passed the request object as their only argument (except for LuaAuthzProvider, which also gets passed the arguments from the Require directive). They can return any value, depending on the hook, but most commonly they'll return OK, DONE, or DECLINED, which you can write in Lua as apache2.OK, apache2.DONE, or apache2.DECLINED, or else an HTTP status code.

-- example hook that rewrites the URI to a filesystem path. require 'apache2' function translate_name(r) if r.uri == "/translate-name" then r.filename = r.document_root .. "/find_me.txt" return apache2.OK end -- we don't care about this URL, give another module a chance return apache2.DECLINED end
--[[ example hook that rewrites one URI to another URI. It returns a apache2.DECLINED to give other URL mappers a chance to work on the substitution, including the core translate_name hook which maps based on the DocumentRoot. Note: Use the early/late flags in the directive to make it run before or after mod_alias. --]] require 'apache2' function translate_name(r) if r.uri == "/translate-name" then r.uri = "/find_me.txt" return apache2.DECLINED end return apache2.DECLINED end

Data Structures


The request_rec is mapped in as a userdata. It has a metatable which lets you do useful things with it. For the most part it has the same fields as the request_rec struct, many of which are writable as well as readable. (The table fields' content can be changed, but the fields themselves cannot be set to different tables.)

Name Lua type Writable Description
allowoverrides string no The AllowOverride options applied to the current request.
ap_auth_type string no If an authentication check was made, this is set to the type of authentication (f.x. basic)
args string yes The query string arguments extracted from the request (f.x. foo=bar&name=johnsmith)
assbackwards boolean no Set to true if this is an HTTP/0.9 style request (e.g. GET /foo (with no headers) )
auth_name string no The realm name used for authorization (if applicable).
banner string no The server banner, f.x. Apache HTTP Server/2.4.3 openssl/0.9.8c
basic_auth_pw string no The basic auth password sent with this request, if any
canonical_filename string no The canonical filename of the request
content_encoding string no The content encoding of the current request
content_type string yes The content type of the current request, as determined in the type_check phase (f.x. image/gif or text/html)
context_prefix string no
context_document_root string no
document_root string no The document root of the host
err_headers_out table no MIME header environment for the response, printed even on errors and persist across internal redirects
filename string yes The file name that the request maps to, f.x. /www/example.com/foo.txt. This can be changed in the translate-name or map-to-storage phases of a request to allow the default handler (or script handlers) to serve a different file than what was requested.
handler string yes The name of the handler that should serve this request, f.x. lua-script if it is to be served by mod_lua. This is typically set by the AddHandler or SetHandler directives, but could also be set via mod_lua to allow another handler to serve up a specific request that would otherwise not be served by it.
headers_in table yes MIME header environment from the request. This contains headers such as Host, User-Agent, Referer and so on.
headers_out table yes MIME header environment for the response.
hostname string no The host name, as set by the Host: header or by a full URI.
is_https boolean no Whether or not this request is done via HTTPS
is_initial_req boolean no Whether this request is the initial request or a sub-request
limit_req_body number no The size limit of the request body for this request, or 0 if no limit.
log_id string no The ID to identify request in access and error log.
method string no The request method, f.x. GET or POST.
notes table yes A list of notes that can be passed on from one module to another.
options string no The Options directive applied to the current request.
path_info string no The PATH_INFO extracted from this request.
port number no The server port used by the request.
protocol string no The protocol used, f.x. HTTP/1.1
proxyreq string yes Denotes whether this is a proxy request or not. This value is generally set in the post_read_request/translate_name phase of a request.
range string no The contents of the Range: header.
remaining number no The number of bytes remaining to be read from the request body.
server_built string no The time the server executable was built.
server_name string no The server name for this request.