diff options
author | André Malo <nd@apache.org> | 2013-06-12 15:35:32 +0000 |
---|---|---|
committer | André Malo <nd@apache.org> | 2013-06-12 15:35:32 +0000 |
commit | 32b70d27a4f055c0c7c2032c6a1b27f133acf5a4 (patch) | |
tree | 925620842f5f95093835432227af1acebba5636d /docs/manual/mod/mod_lua.html.en | |
parent | 03f38181b475e7457b691b040ba769f4c82a0a78 (diff) | |
download | httpd-32b70d27a4f055c0c7c2032c6a1b27f133acf5a4.tar.gz |
update transformation
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1492246 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'docs/manual/mod/mod_lua.html.en')
-rw-r--r-- | docs/manual/mod/mod_lua.html.en | 1006 |
1 files changed, 925 insertions, 81 deletions
diff --git a/docs/manual/mod/mod_lua.html.en b/docs/manual/mod/mod_lua.html.en index 8475aa08fa..6150b8e87b 100644 --- a/docs/manual/mod/mod_lua.html.en +++ b/docs/manual/mod/mod_lua.html.en @@ -50,10 +50,18 @@ Until it is declared stable, usage and behavior may change at any time, even between stable releases of the 2.4.x series. Be sure to check the CHANGES file before upgrading.</div> +<div class="warning"><h3>Warning</h3> +<p>This module holds a great deal of power over httpd, which is both a +strength and a potential security risk. It is <strong>not</strong> 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.</p> +</div> + </div> <div id="quickview"><h3 class="directives">Directives</h3> <ul id="toc"> <li><img alt="" src="../images/down.gif" /> <a href="#luaauthzprovider">LuaAuthzProvider</a></li> +<li><img alt="" src="../images/down.gif" /> <a href="#luacodecache">LuaCodeCache</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#luahookaccesschecker">LuaHookAccessChecker</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#luahookauthchecker">LuaHookAuthChecker</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#luahookcheckuserid">LuaHookCheckUserID</a></li> @@ -63,6 +71,9 @@ Be sure to check the CHANGES file before upgrading.</div> <li><img alt="" src="../images/down.gif" /> <a href="#luahooktranslatename">LuaHookTranslateName</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#luahooktypechecker">LuaHookTypeChecker</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#luainherit">LuaInherit</a></li> +<li><img alt="" src="../images/down.gif" /> <a href="#luainputfilter">LuaInputFilter</a></li> +<li><img alt="" src="../images/down.gif" /> <a href="#luamaphandler">LuaMapHandler</a></li> +<li><img alt="" src="../images/down.gif" /> <a href="#luaoutputfilter">LuaOutputFilter</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#luapackagecpath">LuaPackageCPath</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#luapackagepath">LuaPackagePath</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#luaquickhandler">LuaQuickHandler</a></li> @@ -76,8 +87,10 @@ Be sure to check the CHANGES file before upgrading.</div> <li><img alt="" src="../images/down.gif" /> <a href="#writingauthzproviders">Writing Authorization Providers</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#writinghooks">Writing Hooks</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#datastructures">Data Structures</a></li> +<li><img alt="" src="../images/down.gif" /> <a href="#functions">Built in functions</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#logging">Logging Functions</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#apache2">apache2 Package</a></li> +<li><img alt="" src="../images/down.gif" /> <a href="#modifying_buckets">Modifying contents with Lua filters</a></li> <li><img alt="" src="../images/down.gif" /> <a href="#databases">Database connectivity</a></li> </ul><ul class="seealso"><li><a href="#comments_section">Comments</a></li></ul></div> <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> @@ -106,6 +119,9 @@ ending in <code>.lua</code> by invoking that file's <code>handle</code> function. </p> +<p>For more flexibility, see <code class="directive">LuaMapHandler</code>. +</p> + </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> <div class="section"> <h2><a name="writinghandlers" id="writinghandlers">Writing Handlers</a></h2> @@ -120,7 +136,7 @@ something like this:</p> <pre class="prettyprint lang-lua"> -<strong>example.lua</strong> +<strong>example.lua</strong><br /> -- example handler require "string" @@ -132,19 +148,27 @@ require "string" --]] function handle(r) r.content_type = "text/plain" - r:puts("Hello Lua World!\n") 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 - else + 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 </pre> @@ -187,7 +211,7 @@ without authentication, or if the authenticated user matches the second argument:</p> <pre class="prettyprint lang-lua"> -<strong>authz_provider.lua</strong> +<strong>authz_provider.lua</strong><br /> require 'apache2' @@ -221,18 +245,90 @@ LuaAuthzProvider foo authz_provider.lua authz_check_foo <p>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 filesystem, -performing access control, or setting mimetypes. General purpose hooks -that simply run at handy times in the request lifecycle exist as well.</p> +a specific purpose, such as mapping requests to the file system, +performing access control, or setting mime types:</p> + +<table class="bordered"><tr class="header"> + <th>Hook phase</th> + <th>mod_lua directive</th> + <th>Description</th> + </tr> +<tr> + <td>Quick handler</td> + <td><code class="directive"><a href="#luaquickhandler">LuaQuickHandler</a></code></td> + <td>This is the first hook that will be called after a request has + been mapped to a host or virtual host</td> + </tr> +<tr class="odd"> + <td>Translate name</td> + <td><code class="directive"><a href="#luahooktranslatename">LuaHookTranslateName</a></code></td> + <td>This phase translates the requested URI into a filename on the + system. Modules such as <code class="module"><a href="../mod/mod_alias.html">mod_alias</a></code> and + <code class="module"><a href="../mod/mod_rewrite.html">mod_rewrite</a></code> operate in this phase.</td> + </tr> +<tr> + <td>Map to storage</td> + <td><code class="directive"><a href="#luahookmaptostorage">LuaHookMapToStorage</a></code></td> + <td>This phase maps files to their physical, cached or external/proxied storage. + It can be used by proxy or caching modules</td> + </tr> +<tr class="odd"> + <td>Check Access</td> + <td><code class="directive"><a href="#luahookaccesschecker">LuaHookAccessChecker</a></code></td> + <td>This phase checks whether a client has access to a resource. This + phase is run before the user is authenticated, so beware. + </td> + </tr> +<tr> + <td>Check User ID</td> + <td><code class="directive"><a href="#luahookcheckuserid">LuaHookCheckUserID</a></code></td> + <td>This phase it used to check the negotiated user ID</td> + </tr> +<tr class="odd"> + <td>Check Authorization</td> + <td><code class="directive"><a href="#luahookauthchecker">LuaHookAuthChecker</a></code> or + <code class="directive"><a href="#luaauthzprovider">LuaAuthzProvider</a></code></td> + <td>This phase authorizes a user based on the negotiated credentials, such as + user ID, client certificate etc. + </td> + </tr> +<tr> + <td>Check Type</td> + <td><code class="directive"><a href="#luahooktypechecker">LuaHookTypeChecker</a></code></td> + <td>This phase checks the requested file and assigns a content type and + a handler to it</td> + </tr> +<tr class="odd"> + <td>Fixups</td> + <td><code class="directive"><a href="#luahookfixups">LuaHookFixups</a></code></td> + <td>This is the final "fix anything" phase before the content handlers + are run. Any last-minute changes to the request should be made here.</td> + </tr> +<tr> + <td>Content handler</td> + <td>fx. <code>.lua</code> files or through <code class="directive"><a href="#luamaphandler">LuaMapHandler</a></code></td> + <td>This is where the content is handled. Files are read, parsed, some are run, + and the result is sent to the client</td> + </tr> +<tr class="odd"> + <td>Logging</td> + <td>(none)</td> + <td>Once a request has been handled, it enters several logging phases, + which logs the request in either the error or access log</td> + </tr> +</table> -<p>Hook functions are passed the request object as their only argument. +<p>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 +they'll return OK, DONE, or DECLINED, which you can write in Lua as <code>apache2.OK</code>, <code>apache2.DONE</code>, or <code>apache2.DECLINED</code>, or else an HTTP status code.</p> + <pre class="prettyprint lang-lua"> -<strong>translate_name.lua</strong> +<strong>translate_name.lua</strong><br /> -- example hook that rewrites the URI to a filesystem path. require 'apache2' @@ -248,15 +344,16 @@ end </pre> + <pre class="prettyprint lang-lua"> -<strong>translate_name2.lua</strong> +<strong>translate_name2.lua</strong><br /> --[[ 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: It is currently undefined as to whether this runs before or after - mod_alias. + Note: Use the early/late flags in the directive to make it run before + or after mod_alias. --]] require 'apache2' @@ -279,176 +376,326 @@ end <dd> <p>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 (see httpd.h - until we get better docs here) many of which are writeable as + 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.)</p> - <table class="bordered"> - - <tr> + <table class="bordered"><tr class="header"> <th><strong>Name</strong></th> <th><strong>Lua type</strong></th> <th><strong>Writable</strong></th> + <th><strong>Description</strong></th> + </tr> +<tr> + <td><code>allowoverrides</code></td> + <td>string</td> + <td>no</td> + <td>The AllowOverride options applied to the current request.</td> </tr> - <tr> +<tr class="odd"> <td><code>ap_auth_type</code></td> <td>string</td> <td>no</td> + <td>If an authentication check was made, this is set to the type + of authentication (f.x. <code>basic</code>)</td> </tr> - <tr> +<tr> <td><code>args</code></td> <td>string</td> <td>yes</td> + <td>The query string arguments extracted from the request + (f.x. <code>foo=bar&name=johnsmith</code>)</td> </tr> - <tr> +<tr class="odd"> <td><code>assbackwards</code></td> <td>boolean</td> <td>no</td> + <td>Set to true if this is an HTTP/0.9 style request + (e.g. <code>GET /foo</code> (with no headers) )</td> </tr> - - <tr> +<tr> + <td><code>auth_name</code></td> + <td>string</td> + <td>no</td> + <td>The realm name used for authorization (if applicable).</td> + </tr> +<tr class="odd"> + <td><code>banner</code></td> + <td>string</td> + <td>no</td> + <td>The server banner, f.x. <code>Apache HTTP Server/2.4.3 openssl/0.9.8c</code></td> + </tr> +<tr> + <td><code>basic_auth_pw</code></td> + <td>string</td> + <td>no</td> + <td>The basic auth password sent with this request, if any</td> + </tr> +<tr class="odd"> <td><code>canonical_filename</code></td> <td>string</td> <td>no</td> + <td>The canonical filename of the request</td> </tr> - <tr> +<tr> <td><code>content_encoding</code></td> <td>string</td> <td>no</td> + <td>The content encoding of the current request</td> </tr> - <tr> +<tr class="odd"> <td><code>content_type</code></td> <td>string</td> <td>yes</td> + <td>The content type of the current request, as determined in the + type_check phase (f.x. <code>image/gif</code> or <code>text/html</code>)</td> </tr> - <tr> +<tr> <td><code>context_prefix</code></td> <td>string</td> <td>no</td> + <td /> </tr> - <tr> +<tr class="odd"> <td><code>context_document_root</code></td> <td>string</td> <td>no</td> + <td /> </tr> - - <tr> +<tr> <td><code>document_root</code></td> <td>string</td> <td>no</td> + <td>The document root of the host</td> </tr> - <tr> +<tr class="odd"> <td><code>err_headers_out</code></td> <td>table</td> <td>no</td> + <td>MIME header environment for the response, printed even on errors and + persist across internal redirects</td> </tr> - <tr> +<tr> <td><code>filename</code></td> <td>string</td> <td>yes</td> + <td>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.</td> </tr> - <tr> +<tr class="odd"> <td><code>handler</code></td> <td>string</td> <td>yes</td> + <td>The name of the <a href="../handler.html">handler</a> that should serve this request, f.x. + <code>lua-script</code> if it is to be served by mod_lua. This is typically set by the + <code class="directive"><a href="../mod/mod_mime.html#addhandler">AddHandler</a></code> or <code class="directive"><a href="../mod/core.html#sethandler">SetHandler</a></code> + 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. + </td> </tr> - - <tr> +<tr> <td><code>headers_in</code></td> <td>table</td> <td>yes</td> + <td>MIME header environment from the request. This contains headers such as <code>Host, + User-Agent, Referer</code> and so on.</td> </tr> - <tr> +<tr class="odd"> <td><code>headers_out</code></td> <td>table</td> <td>yes</td> + <td>MIME header environment for the response.</td> </tr> - <tr> +<tr> <td><code>hostname</code></td> <td>string</td> <td>no</td> + <td>The host name, as set by the <code>Host:</code> header or by a full URI.</td> </tr> - <tr> +<tr class="odd"> + <td><code>is_https</code></td> + <td>boolean</td> + <td>no</td> + <td>Whether or not this request is done via HTTPS</td> + </tr> +<tr> + <td><code>is_initial_req</code></td> + <td>boolean</td> + <td>no</td> + <td>Whether this request is the initial request or a sub-request</td> + </tr> +<tr class="odd"> + <td><code>limit_req_body</code></td> + <td>number</td> + <td>no</td> + <td>The size limit of the request body for this request, or 0 if no limit.</td> + </tr> +<tr> <td><code>log_id</code></td> <td>string</td> <td>no</td> + <td>The ID to identify request in access and error log.</td> </tr> - <tr> +<tr class="odd"> <td><code>method</code></td> <td>string</td> <td>no</td> + <td>The request method, f.x. <code>GET</code> or <code>POST</code>.</td> </tr> - <tr> +<tr> <td><code>notes</code></td> <td>table</td> <td>yes</td> + <td>A list of notes that can be passed on from one module to another.</td> + </tr> +<tr class="odd"> + <td><code>options</code></td> + <td>string</td> + <td>no</td> + <td>The Options directive applied to the current request.</td> </tr> - <tr> +<tr> <td><code>path_info</code></td> <td>string</td> <td>no</td> + <td>The PATH_INFO extracted from this request.</td> </tr> - <tr> +<tr class="odd"> + <td><code>port</code></td> + <td>number</td> + <td>no</td> + <td>The server port used by the request.</td> + </tr> +<tr> <td><code>protocol</code></td> <td>string</td> <td>no</td> + <td>The protocol used, f.x. <code>HTTP/1.1</code></td> </tr> - <tr> +<tr class="odd"> <td><code>proxyreq</code></td> <td>string</td> <td>yes</td> + <td>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.</td> </tr> - <tr> +<tr> <td><code>range</code></td> <td>string</td> <td>no</td> + <td>The contents of the <code>Range:</code> header.</td> + </tr> +<tr class="odd"> + <td><code>remaining</code></td> + <td>number</td> + <td>no</td> + <td>The number of bytes remaining to be read from the request body.</td> + </tr> +<tr> + <td><code>server_built</code></td> + <td>string</td> + <td>no</td> + <td>The time the server executable was built.</td> + </tr> +<tr class="odd"> + <td><code>server_name</code></td> + <td>string</td> + <td>no</td> + <td>The server name for this request.</td> </tr> - <tr> +<tr> + <td><code>some_auth_required</code></td> + <td>boolean</td> + <td>no</td> + <td>Whether some authorization is/was required for this request.</td> + </tr> +<tr class="odd"> <td><code>subprocess_env</code></td> <td>table</td> <td>yes</td> + <td>The environment variables set for this request.</td> </tr> - <tr> +<tr> + <td><code>started</code></td> + <td>number</td> + <td>no</td> + <td>The time the server was (re)started, in seconds since the epoch (Jan 1st, 1970)</td> + </tr> +<tr class="odd"> <td><code>status</code></td> <td>number</td> <td>yes</td> + <td>The (current) HTTP return code for this request, f.x. <code>200</code> or <code>404</code>.</td> </tr> - <tr> +<tr> <td><code>the_request</code></td> <td>string</td> <td>no</td> + <td>The request string as sent by the client, f.x. <code>GET /foo/bar HTTP/1.1</code>.</td> </tr> - <tr> +<tr class="odd"> <td><code>unparsed_uri</code></td> <td>string</td> <td>no</td> + <td>The unparsed URI of the request</td> </tr> - <tr> +<tr> <td><code>uri</code></td> <td>string</td> <td>yes</td> + <td>The URI after it has been parsed by httpd</td> </tr> - <tr> +<tr class="odd"> <td><code>user</code></td> <td>string</td> <td>yes</td> + <td>If an authentication check has been made, this is set to the name of the authenticated user.</td> </tr> - <tr> +<tr> <td><code>useragent_ip</code></td> <td>string</td> <td>no</td> + <td>The IP of the user agent making the request</td> </tr> - </table> +</table> + </dd> + </dl> +</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> +<div class="section"> +<h2><a name="functions" id="functions">Built in functions</a></h2> + +<p>The request_rec object has (at least) the following methods:</p> - <p>The request_rec has (at least) the following methods:</p> +<pre class="prettyprint lang-lua"> +r:flush() -- flushes the output buffer. + -- Returns true if the flush was successful, false otherwise. - <pre class="prettyprint lang-lua"> - r:addoutputfilter(name|function) -- add an output filter - </pre> +while we_have_stuff_to_send do + r:puts("Bla bla bla\n") -- print something to client + r:flush() -- flush the buffer (send to client) + r:sleep(0.5) -- fake processing time and repeat +end +</pre> - <pre class="prettyprint lang-lua"> +<pre class="prettyprint lang-lua"> +r:addoutputfilter(name|function) -- add an output filter: + +r:addoutputfilter("fooFilter") -- add the fooFilter to the output stream +</pre> + + +<pre class="prettyprint lang-lua"> +r:sendfile(filename) -- sends an entire file to the client, using sendfile if supported by the current platform: + +if use_sendfile_thing then + r:sendfile("/var/www/large_file.img") +end +</pre> + + +<pre class="prettyprint lang-lua"> r:parseargs() -- returns two tables; one standard key/value table for regular GET data, -- and one for multi-value data (fx. foo=1&foo=2&foo=3): @@ -467,23 +714,288 @@ local POST, POSTMULTI = r:parsebody(1024*1024) r:puts("Your name is: " .. POST['name'] or "Unknown") </pre> - <pre class="prettyprint lang-lua"> - r:puts("hello", " world", "!") -- print to response body - </pre> +<pre class="prettyprint lang-lua"> +r:puts("hello", " world", "!") -- print to response body, self explanatory +</pre> - <pre class="prettyprint lang-lua"> - r:write("a single string") -- print to response body - </pre> - - <pre class="prettyprint lang-lua"> +<pre class="prettyprint lang-lua"> +r:write("a single string") -- print to response body, self explanatory +</pre> + + +<pre class="prettyprint lang-lua"> +r:escape_html("<html>test</html>") -- Escapes HTML code and returns the escaped result +</pre> + + +<pre class="prettyprint lang-lua"> +r:base64_encode(string) -- Encodes a string using the Base64 encoding standard: + +local encoded = r:base64_encode("This is a test") -- returns VGhpcyBpcyBhIHRlc3Q= +</pre> + + +<pre class="prettyprint lang-lua"> +r:base64_decode(string) -- Decodes a Base64-encoded string: + +local decoded = r:base64_decode("VGhpcyBpcyBhIHRlc3Q=") -- returns 'This is a test' +</pre> + + +<pre class="prettyprint lang-lua"> +r:md5(string) -- Calculates and returns the MD5 digest of a string (binary safe): + +local hash = r:md5("This is a test") -- returns ce114e4501d2f4e2dcea3e17b546f339 +</pre> + + +<pre class="prettyprint lang-lua"> +r:sha1(string) -- Calculates and returns the SHA1 digest of a string (binary safe): + +local hash = r:sha1("This is a test") -- returns a54d88e06612d820bc3be72877c74f257b561b19 +</pre> + + +<pre class="prettyprint lang-lua"> +r:escape(string) -- URL-Escapes a string: + +local url = "http://foo.bar/1 2 3 & 4 + 5" +local escaped = r:escape(url) -- returns 'http%3a%2f%2ffoo.bar%2f1+2+3+%26+4+%2b+5' +</pre> + + +<pre class="prettyprint lang-lua"> +r:unescape(string) -- Unescapes an URL-escaped string: + +local url = "http%3a%2f%2ffoo.bar%2f1+2+3+%26+4+%2b+5" +local unescaped = r:escape(url) -- returns 'http://foo.bar/1 2 3 & 4 + 5' +</pre> + + +<pre class="prettyprint lang-lua"> +r:mpm_query(number) -- Queries the server for MPM information using ap_mpm_query: + +local mpm = r.mpm_query(14) +if mpm == 1 then + r:puts("This server uses the Event MPM") +end +</pre> + + +<pre class="prettyprint lang-lua"> +r:expr(string) -- Evaluates an <a href="../expr.html">expr</a> string. + +if r:expr("%{HTTP_HOST} =~ /^www/") then + r:puts("This host name starts with www") +end +</pre> + + +<pre class="prettyprint lang-lua"> +r:scoreboard_process(a) -- Queries the server for information about the process at position <code>a</code>: + +local process = r:scoreboard_process(1) +r:puts("Server 1 has PID " .. process.pid) +</pre> + + +<pre class="prettyprint lang-lua"> +r:scoreboard_worker(a, b) -- Queries for information about the worker thread, <code>b</code>, in process <code>a</code>: + +local thread = r:scoreboard_worker(1, 1) +r:puts("Server 1's thread 1 has thread ID " .. thread.tid .. " and is in " .. thread.status .. " status") +</pre> + + + +<pre class="prettyprint lang-lua"> +r:clock() -- Returns the current time with microsecond precision +</pre> + + +<pre class="prettyprint lang-lua"> +r:requestbody(filename) -- Reads and returns the request body of a request. + -- If 'filename' is specified, it instead saves the + -- contents to that file: + +local input = r:requestbody() +r:puts("You sent the following request body to me:\n") +r:puts(input) +</pre> + + +<pre class="prettyprint lang-lua"> +r:add_input_filter(filter_name) -- Adds 'filter_name' as an input filter +</pre> + + +<pre class="prettyprint lang-lua"> +r.module_info(module_name) -- Queries the server for information about a module + +local mod = r.module_info("mod_lua.c") +if mod then + for k, v in pairs(mod.commands) do + r:puts( ("%s: %s\n"):format(k,v)) -- print out all directives accepted by this module + end +end +</pre> + + +<pre class="prettyprint lang-lua"> +r:loaded_modules() -- Returns a list of modules loaded by httpd: + +for k, module in pairs(r:loaded_modules()) do + r:puts("I have loaded module " .. module .. "\n") +end +</pre> + + +<pre class="prettyprint lang-lua"> +r:runtime_dir_relative(filename) -- Compute the name of a run-time file (e.g., shared memory "file") + -- relative to the appropriate run-time directory. +</pre> + + +<pre class="prettyprint lang-lua"> +r:server_info() -- Returns a table containing server information, such as + -- the name of the httpd executable file, mpm used etc. +</pre> + + +<pre class="prettyprint lang-lua"> +r:set_document_root(file_path) -- Sets the document root for the request to file_path +</pre> + + + + +<pre class="prettyprint lang-lua"> +r:set_context_info(prefix, docroot) -- Sets the context prefix and context document root for a request +</pre> + + +<pre class="prettyprint lang-lua"> +r:os_escape_path(file_path) -- Converts an OS path to a URL in an OS dependent way +</pre> + + +<pre class="prettyprint lang-lua"> +r:escape_logitem(string) -- Escapes a string for logging +</pre> + + +<pre class="prettyprint lang-lua"> +r.strcmp_match(string, pattern) -- Checks if 'string' matches 'pattern' using strcmp_match (globs). + -- fx. whether 'www.example.com' matches '*.example.com': + +local match = r.strcmp_match("foobar.com", "foo*.com") +if match then + r:puts("foobar.com matches foo*.com") +end +</pre> + + +<pre class="prettyprint lang-lua"> +r:set_keepalive() -- Sets the keepalive status for a request. Returns true if possible, false otherwise. +</pre> + + +<pre class="prettyprint lang-lua"> +r:make_etag() -- Constructs and returns the etag for the current request. +</pre> + + +<pre class="prettyprint lang-lua"> +r:send_interim_response(clear) -- Sends an interim (1xx) response to the client. + -- if 'clear' is true, available headers will be sent and cleared. +</pre> + + +<pre class="prettyprint lang-lua"> +r:custom_response(status_code, string) -- Construct and set a custom response for a given status code. + -- This works much like the ErrorDocument directive: + +r:custom_response(404, "Baleted!") +</pre> + + +<pre class="prettyprint lang-lua"> +r.exists_config_define(string) -- Checks whether a configuration definition exists or not: + +if r.exists_config_define("FOO") then + r:puts("httpd was probably run with -DFOO, or it was defined in the configuration") +end +</pre> + + +<pre class="prettyprint lang-lua"> +r:state_query(string) -- Queries the server for state information +</pre> + + +<pre class="prettyprint lang-lua"> +r:stat(filename) -- Runs stat() on a file, and returns a table with file information: + +local info = r:stat("/var/www/foo.txt") +if info then + r:puts("This file exists and was last modified at: " .. info.modified) +end +</pre> + + +<pre class="prettyprint lang-lua"> +r:regex(string, pattern, [flags]) -- Runs a regular expression match on a string, returning captures if matched: + +local matches = r:regex("foo bar baz", [[foo (\w+) (\S*)]]) +if matches then + r:puts("The regex matched, and the last word captured ($2) was: " .. matches[2]) +end + +-- Example ignoring case sensitivity: +local matches = r:regex("FOO bar BAz", [[(foo) bar]], 1) + +-- Flags can be a bitwise combination of: +-- 0x01: Ignore case +-- 0x02: Multiline search +</pre> + + +<pre class="prettyprint lang-lua"> +r:sleep(number_of_seconds) -- Puts the script to sleep for a given number of seconds. + -- This can be a floating point number like 1.25 for extra accuracy. +</pre> + + +<pre class="prettyprint lang-lua"> r:dbacquire(dbType[, dbParams]) -- Acquires a connection to a database and returns a database class. - -- See '<a href="#databases">Database connectivity</a>' for details. - </pre> + -- See '<a href="#databases">Database connectivity</a>' for details. +</pre> + + +<pre class="prettyprint lang-lua"> +r:ivm_set("key", value) -- Set an Inter-VM variable to hold a specific value. + -- These values persist even though the VM is gone or not being used, + -- and so should only be used if MaxConnectionsPerChild is > 0 + -- Values can be numbers, strings and booleans, and are stored on a + -- per process basis (so they won't do much good with a prefork mpm) + +r:ivm_get("key") -- Fetches a variable set by ivm_set. Returns the contents of the variable + -- if it exists or nil if no such variable exists. + +-- An example getter/setter that saves a global variable outside the VM: +function handle(r) + -- First VM to call this will get no value, and will have to create it + local foo = r:ivm_get("cached_data") + if not foo then + foo = do_some_calcs() -- fake some return value + r:ivm_set("cached_data", foo) -- set it globally + end + r:puts("Cached data is: ", foo) +end +</pre> - </dd> - </dl> </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> <div class="section"> @@ -522,10 +1034,54 @@ r:dbacquire(dbType[, dbParams]) -- Acquires a connection to a database and retur <dd>HTTP status code</dd> <dt>apache2.PROXYREQ_NONE, apache2.PROXYREQ_PROXY, apache2.PROXYREQ_REVERSE, apache2.PROXYREQ_RESPONSE</dt> <dd>internal constants used by <code class="module"><a href="../mod/mod_proxy.html">mod_proxy</a></code></dd> + <dt>apache2.AUTHZ_DENIED, apache2.AUTHZ_GRANTED, apache2.AUTHZ_NEUTRAL, apache2.AUTHZ_GENERAL_ERROR, apache2.AUTHZ_DENIED_NO_USER</dt> + <dd>internal constants used by <code class="module"><a href="../mod/mod_authz_core.html">mod_authz_core</a></code></dd> + </dl> <p>(Other HTTP status codes are not yet implemented.)</p> </div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> <div class="section"> +<h2><a name="modifying_buckets" id="modifying_buckets">Modifying contents with Lua filters</a></h2> + + <p> + Filter functions implemented via <code class="directive"><a href="#luainputfilter">LuaInputFilter</a></code> + or <code class="directive"><a href="#luaoutputfilter">LuaOutputFilter</a></code> are designed as + three-stage non-blocking functions using coroutines to suspend and resume a + function as buckets are sent down the filter chain. The core structure of + such a function is: + </p> + <pre class="prettyprint lang-lua"> +function filter(r) + -- Our first yield is to signal that we are ready to receive buckets. + -- Before this yield, we can set up our environment, check for conditions, + -- and, if we deem it necessary, decline filtering a request alltogether: + if something_bad then + return -- This would skip this filter. + end + -- Regardless of whether we have data to prepend, a yield MUST be called here. + -- Note that only output filters can prepend data. Input filters must use the + -- final stage to append data to the content. + coroutine.yield([optional header to be prepended to the content]) + + -- After we have yielded, buckets will be sent to us, one by one, and we can + -- do whatever we want with them and then pass on the result. + -- Buckets are stored in the global variable 'bucket', so we create a loop + -- that checks if 'bucket' is not nil: + while bucket ~= nil do + local output = mangle(bucket) -- Do some stuff to the content + coroutine.yield(output) -- Return our new content to the filter chain + end + + -- Once the buckets are gone, 'bucket' is set to nil, which will exit the + -- loop and land us here. Anything extra we want to append to the content + -- can be done by doing a final yield here. Both input and output filters + -- can append data to the content in this phase. + coroutine.yield([optional footer to be appended to the content]) +end + </pre> + +</div><div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> +<div class="section"> <h2><a name="databases" id="databases">Database connectivity</a></h2> <p> @@ -533,11 +1089,13 @@ r:dbacquire(dbType[, dbParams]) -- Acquires a connection to a database and retur on the most popular database engines (mySQL, PostgreSQL, FreeTDS, ODBC, SQLite, Oracle) as well as mod_dbd. </p> - <p>Connecting and firing off queries is as easy as:</p> + <p>The example below shows how to acquire a database handle and return information from a table:</p> <pre class="prettyprint lang-lua"> -function handler(r) - local database, err = r:dbacquire("mysql", "server=localhost&user=root&database=mydb") +function handle(r) + -- Acquire a database handle + local database, err = r:dbacquire("mysql", "server=localhost,user=root,dbname=mydb") if not err then + -- Select some information from it local results, err = database:select(r, "SELECT `name`, `age` FROM `people` WHERE 1") if not err then local rows = results(0) -- fetch all rows synchronously @@ -555,7 +1113,7 @@ end </pre> <p> - To utilize <code class="module"><a href="../mod/mod_dbd.html">mod_dbd</a></code>, simply specify <code>mod_dbd</code> + To utilize <code class="module"><a href="../mod/mod_dbd.html">mod_dbd</a></code>, specify <code>mod_dbd</code> as the database type, or leave the field blank: </p> <pre class="prettyprint lang-lua"> @@ -579,7 +1137,7 @@ local result, errmsg = database:select(r, "SELECT * FROM `people` WHERE 1") -- Create and run a prepared statement: local statement, errmsg = database:prepare(r, "DELETE FROM `tbl` WHERE `age` > %u") if not errmsg then - local result, errmsg = statement:query(20) -- run the statement with age >20 + local result, errmsg = statement:query(20) -- run the statement with age > 20 end -- Fetch a prepared statement from a DBDPrepareSQL directive: @@ -707,13 +1265,53 @@ collectgarbage() -- close the handle via GC <p>After a lua function has been registered as authorization provider, it can be used with the <code class="directive"><a href="../mod/mod_authz_core.html#require">Require</a></code> directive:</p> -<div class="example"><pre class="prettyprint lang-config"> +<pre class="prettyprint lang-config"> LuaRoot /usr/local/apache2/lua LuaAuthzProvider foo authz.lua authz_check_foo <Location /> - Require foo bar + Require foo johndoe </Location> </pre> + +<pre class="prettyprint lang-lua"> +require "apache2" +function authz_check_foo(r, who) + if r.user ~= who then return apache2.AUTHZ_DENIED + return apache2.AUTHZ_GRANTED +end +</pre> + + + + +</div> +<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> +<div class="directive-section"><h2><a name="LuaCodeCache" id="LuaCodeCache">LuaCodeCache</a> <a name="luacodecache" id="luacodecache">Directive</a></h2> +<table class="directive"> +<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Configure the compiled code cache.</td></tr> +<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>LuaCodeCache stat|forever|never</code></td></tr> +<tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>LuaCodeCache stat</code></td></tr> +<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host, directory, .htaccess</td></tr> +<tr><th><a href="directive-dict.html#Override">Override:</a></th><td>All</td></tr> +<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Experimental</td></tr> +<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_lua</td></tr> +</table><p> + Specify the behavior of the in-memory code cache. The default + is stat, which stats the top level script (not any included + ones) each time that file is needed, and reloads it if the + modified time indicates it is newer than the one it has + already loaded. The other values cause it to keep the file + cached forever (don't stat and replace) or to never cache the + file.</p> + + <p>In general stat or forever is good for production, and stat or never + for development.</p> + + <div class="example"><h3>Examples:</h3><pre class="prettyprint lang-config"> +LuaCodeCache stat +LuaCodeCache forever +LuaCodeCache never + </pre> </div> @@ -805,7 +1403,7 @@ end <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> <div class="directive-section"><h2><a name="LuaHookFixups" id="LuaHookFixups">LuaHookFixups</a> <a name="luahookfixups" id="luahookfixups">Directive</a></h2> <table class="directive"> -<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Provide a hook for the fixups phase of request +<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Provide a hook for the fixups phase of a request processing</td></tr> <tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>LuaHookFixups /path/to/lua/script.lua hook_function_name</code></td></tr> <tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host, directory, .htaccess</td></tr> @@ -838,7 +1436,48 @@ processing</td></tr> <tr><th><a href="directive-dict.html#Override">Override:</a></th><td>All</td></tr> <tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Experimental</td></tr> <tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_lua</td></tr> -</table><p>...</p> +</table> + <p>Like <code class="directive">LuaHookTranslateName</code> but executed at the + map-to-storage phase of a request. Modules like mod_cache run at this phase, + which makes for an interesting example on what to do here:</p> + <pre class="prettyprint lang-config"> + LuaHookMapToStorage /path/to/lua/script.lua check_cache + </pre> + + <pre class="prettyprint lang-lua"> +require"apache2" +cached_files = {} + +function read_file(filename) + local input = io.open(filename, "r") + if input then + local data = input:read("*a") + cached_files[filename] = data + file = cached_files[filename] + input:close() + end + return cached_files[filename] +end + +function check_cache(r) + if r.filename:match("%.png$") then -- Only match PNG files + local file = cached_files[r.filename] -- Check cache entries + if not file then + file = read_file(r.filename) -- Read file into cache + end + if file then -- If file exists, write it out + r.status = 200 + r:write(file) + r:info(("Sent %s to client from cache"):format(r.filename)) + return apache2.DONE -- skip default handler for PNG files + end + end + return apache2.DECLINED -- If we had nothing to do, let others serve this. +end + </pre> + + + </div> <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> <div class="directive-section"><h2><a name="LuaHookTranslateName" id="LuaHookTranslateName">LuaHookTranslateName</a> <a name="luahooktranslatename" id="luahooktranslatename">Directive</a></h2> @@ -903,7 +1542,29 @@ end <tr><th><a href="directive-dict.html#Override">Override:</a></th><td>All</td></tr> <tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Experimental</td></tr> <tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_lua</td></tr> -</table><p>...</p> +</table><p> + This directive provides a hook for the type_checker phase of the request processing. + This phase is where requests are assigned a content type and a handler, and thus can + be used to modify the type and handler based on input: + </p> + <pre class="prettyprint lang-config"> + LuaHookTypeChecker /path/to/lua/script.lua type_checker + </pre> + + <pre class="prettyprint lang-lua"> + function type_checker(r) + if r.uri:match("%.to_gif$") then -- match foo.png.to_gif + r.content_type = "image/gif" -- assign it the image/gif type + r.handler = "gifWizard" -- tell the gifWizard module to handle this + r.filename = r.uri:gsub("%.to_gif$", "") -- fix the filename requested + return apache2.OK + end + + return apache2.DECLINED + end + </pre> + + </div> <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> <div class="directive-section"><h2><a name="LuaInherit" id="LuaInherit">LuaInherit</a> <a name="luainherit" id="luainherit">Directive</a></h2> @@ -926,6 +1587,162 @@ end directives from parent configuration sections.</p> </div> <div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> +<div class="directive-section"><h2><a name="LuaInputFilter" id="LuaInputFilter">LuaInputFilter</a> <a name="luainputfilter" id="luainputfilter">Directive</a></h2> +<table class="directive"> +<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Provide a Lua function for content input filtering</td></tr> +<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>LuaInputFilter filter_name /path/to/lua/script.lua function_name</code></td></tr> +<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config</td></tr> +<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Experimental</td></tr> +<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_lua</td></tr> +<tr><th><a href="directive-dict.html#Compatibility">Compatibility:</a></th><td>2.5.0 and later</td></tr> +</table> +<p>Provides a means of adding a Lua function as an input filter. +As with output filters, input filters work as coroutines, +first yielding before buffers are sent, then yielding whenever +a bucket needs to be passed down the chain, and finally (optionally) +yielding anything that needs to be appended to the input data. The +global variable <code>bucket</code> holds the buckets as they are passed +onto the Lua script: +</p> + +<pre class="prettyprint lang-config"> +LuaInputFilter myInputFilter /www/filter.lua input_filter +<FilesMatch "\.lua> + SetInputFilter myInputFilter +</FilesMatch> +</pre> + +<pre class="prettyprint lang-lua"> +--[[ + Example input filter that converts all POST data to uppercase. +]]-- +function input_filter(r) + print("luaInputFilter called") -- debug print + coroutine.yield() -- Yield and wait for buckets + while bucket do -- For each bucket, do... + local output = string.upper(bucket) -- Convert all POST data to uppercase + coroutine.yield(output) -- Send converted data down the chain + end + -- No more buckets available. + coroutine.yield("&filterSignature=1234") -- Append signature at the end +end +</pre> + +<p> +The input filter supports denying/skipping a filter if it is deemed unwanted: +</p> +<pre class="prettyprint lang-lua"> +function input_filter(r) + if not good then + return -- Simply deny filtering, passing on the original content instead + end + coroutine.yield() -- wait for buckets + ... -- insert filter stuff here +end +</pre> + +<p> +See "<a href="#modifying_buckets">Modifying contents with Lua +filters</a>" for more information. +</p> + +</div> +<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> +<div class="directive-section"><h2><a name="LuaMapHandler" id="LuaMapHandler">LuaMapHandler</a> <a name="luamaphandler" id="luamaphandler">Directive</a></h2> +<table class="directive"> +<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Map a path to a lua handler</td></tr> +<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>LuaMapHandler uri-pattern /path/to/lua/script.lua [function-name]</code></td></tr> +<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host, directory, .htaccess</td></tr> +<tr><th><a href="directive-dict.html#Override">Override:</a></th><td>All</td></tr> +<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Experimental</td></tr> +<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_lua</td></tr> +</table> + <p>This directive matches a uri pattern to invoke a specific + handler function in a specific file. It uses PCRE regular + expressions to match the uri, and supports interpolating + match groups into both the file path and the function name. + Be careful writing your regular expressions to avoid security + issues.</p> + <div class="example"><h3>Examples:</h3><pre class="prettyprint lang-config"> + LuaMapHandler /(\w+)/(\w+) /scripts/$1.lua handle_$2 + </pre> +</div> + <p>This would match uri's such as /photos/show?id=9 + to the file /scripts/photos.lua and invoke the + handler function handle_show on the lua vm after + loading that file.</p> + +<pre class="prettyprint lang-config"> + LuaMapHandler /bingo /scripts/wombat.lua +</pre> + + <p>This would invoke the "handle" function, which + is the default if no specific function name is + provided.</p> + +</div> +<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> +<div class="directive-section"><h2><a name="LuaOutputFilter" id="LuaOutputFilter">LuaOutputFilter</a> <a name="luaoutputfilter" id="luaoutputfilter">Directive</a></h2> +<table class="directive"> +<tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Provide a Lua function for content output filtering</td></tr> +<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>LuaOutputFilter filter_name /path/to/lua/script.lua function_name</code></td></tr> +<tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config</td></tr> +<tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Experimental</td></tr> +<tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_lua</td></tr> +<tr><th><a href="directive-dict.html#Compatibility">Compatibility:</a></th><td>2.5.0 and later</td></tr> +</table> +<p>Provides a means of adding a Lua function as an output filter. +As with input filters, output filters work as coroutines, +first yielding before buffers are sent, then yielding whenever +a bucket needs to be passed down the chain, and finally (optionally) +yielding anything that needs to be appended to the input data. The +global variable <code>bucket</code> holds the buckets as they are passed +onto the Lua script: +</p> + +<pre class="prettyprint lang-config"> +LuaOutputFilter myOutputFilter /www/filter.lua output_filter +<FilesMatch "\.lua> + SetOutputFilter myOutputFilter +</FilesMatch> +</pre> + +<pre class="prettyprint lang-lua"> +--[[ + Example output filter that escapes all HTML entities in the output +]]-- +function output_filter(r) + coroutine.yield("(Handled by myOutputFilter)<br/>\n") -- Prepend some data to the output, + -- yield and wait for buckets. + while bucket do -- For each bucket, do... + local output = r:escape_html(bucket) -- Escape all output + coroutine.yield(output) -- Send converted data down the chain + end + -- No more buckets available. +end +</pre> + +<p> +As with the input filter, the output filter supports denying/skipping a filter +if it is deemed unwanted: +</p> +<pre class="prettyprint lang-lua"> +function output_filter(r) + if not r.content_type:match("text/html") then + return -- Simply deny filtering, passing on the original content instead + end + coroutine.yield() -- wait for buckets + ... -- insert filter stuff here +end +</pre> + +<p> +See "<a href="#modifying_buckets">Modifying contents with Lua filters</a>" for more +information. +</p> + +</div> +<div class="top"><a href="#page-header"><img alt="top" src="../images/up.gif" /></a></div> <div class="directive-section"><h2><a name="LuaPackageCPath" id="LuaPackageCPath">LuaPackageCPath</a> <a name="luapackagecpath" id="luapackagecpath">Directive</a></h2> <table class="directive"> <tr><th><a href="directive-dict.html#Description">Description:</a></th><td>Add a directory to lua's package.cpath</td></tr> @@ -970,7 +1787,14 @@ LuaPackagePath /scripts/lib/?/init.lua <tr><th><a href="directive-dict.html#Override">Override:</a></th><td>All</td></tr> <tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Experimental</td></tr> <tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_lua</td></tr> -</table><p>...</p> +</table> + <p> + This phase is run immediately after the request has been mapped to a virtal host, + and can be used to either do some request processing before the other phases kick + in, or to serve a request without the need to translate, map to storage et cetera. + As this phase is run before anything else, directives such as <code class="directive"><a href="../mod/core.html#location"><Location></a></code> or <code class="directive"><a href="../mod/core.html#directory"><Directory></a></code> are void in this phase, just as + URIs have not been properly parsed yet. + </p> <div class="note"><h3>Context</h3><p>This directive is not valid in <code class="directive"><a href="../mod/core.html#directory"><Directory></a></code>, <code class="directive"><a href="../mod/core.html#files"><Files></a></code>, or htaccess context.</p></div> @@ -995,14 +1819,14 @@ LuaPackagePath /scripts/lib/?/init.lua <div class="directive-section"><h2><a name="LuaScope" id="LuaScope">LuaScope</a> <a name="luascope" id="luascope">Directive</a></h2> <table class="directive"> <tr><th><a href="directive-dict.html#Description">Description:</a></th><td>One of once, request, conn, thread -- default is once</td></tr> -<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>LuaScope once|request|conn|thread</code></td></tr> +<tr><th><a href="directive-dict.html#Syntax">Syntax:</a></th><td><code>LuaScope once|request|conn|thread|server [min] [max]</code></td></tr> <tr><th><a href="directive-dict.html#Default">Default:</a></th><td><code>LuaScope once</code></td></tr> <tr><th><a href="directive-dict.html#Context">Context:</a></th><td>server config, virtual host, directory, .htaccess</td></tr> <tr><th><a href="directive-dict.html#Override">Override:</a></th><td>All</td></tr> <tr><th><a href="directive-dict.html#Status">Status:</a></th><td>Experimental</td></tr> <tr><th><a href="directive-dict.html#Module">Module:</a></th><td>mod_lua</td></tr> </table> - <p>Specify the lifecycle scope of the Lua interpreter which will + <p>Specify the life cycle scope of the Lua interpreter which will be used by handlers in this "Directory." The default is "once"</p> <dl> @@ -1013,10 +1837,30 @@ LuaPackagePath /scripts/lib/?/init.lua request scoped.</dd> <dt>conn:</dt> <dd>Same as request but attached to the connection_rec</dd> + <dt>thread:</dt> <dd>Use the interpreter for the lifetime of the thread handling the request (only available with threaded MPMs).</dd> + <dt>server:</dt> <dd>This one is different than others because the + server scope is quite long lived, and multiple threads + will have the same server_rec. To accommodate this, + server scoped Lua states are stored in an apr + resource list. The <code>min</code> and <code>max</code> arguments + specify the minimum and maximum number of Lua states to keep in the + pool.</dd> </dl> + <p> + Generally speaking, the <code>thread</code> and <code>server</code> scopes + execute roughly 2-3 times faster than the rest, because they don't have to + spawn new Lua states on every request (especially with the event MPM, as + even keepalive requests will use a new thread for each request). If you are + satisfied that your scripts will not have problems reusing a state, then + the <code>thread</code> or <code>server</code> scopes should be used for + maximum performance. While the <code>thread</code> scope will provide the + fastest responses, the <code>server</code> scope will use less memory, as + states are pooled, allowing f.x. 1000 threads to share only 100 Lua states, + thus using only 10% of the memory required by the <code>thread</code> scope. + </p> </div> </div> |