diff --git a/UserManual.md b/UserManual.md index 20b1f324..ac458367 100644 --- a/UserManual.md +++ b/UserManual.md @@ -302,35 +302,40 @@ print current weekday name, one can write:
Today is: - print(os.date("%A")) ?> + mg.write(os.date("%A")) ?>
-Note that this example uses function `print()`, which prints data to the -web page. Using function `print()` is the way to generate web content from -inside Lua code. In addition to `print()`, all standard library functions +Note that this example uses function `mg.write()`, which prints data to the +web page. Using function `mg.write()` is the way to generate web content from +inside Lua code. In addition to `mg.write()`, all standard library functions are accessible from the Lua code (please check reference manual for details), -and also information about the request is available in `request_info` object, +and also information about the request is available in `mg.request_info` object, like request method, all headers, etcetera. Please refer to `struct mg_request_info` definition in [mongoose.h](https://github.com/valenok/mongoose/blob/master/mongoose.h) -to see what kind of information is present in `request_info` object. Also, +to see what kind of information is present in `mg.request_info` object. Also, [page.lp](https://github.com/valenok/mongoose/blob/master/test/page.lp) and [prime_numbers.lp](https://github.com/valenok/mongoose/blob/master/examples/lua/prime_numbers.lp) contains some example code that uses `request_info` and other functions(form submitting for example). +Mongoose exports the following to the Lua server page: -One substantial difference of mongoose's Lua Pages and PHP is that Mongoose -expects Lua page to output HTTP headers. Therefore, **at the very beginning of -every Lua Page must be a Lua block that outputs HTTP headers**, like this: + mg.read() -- reads a chunk from POST data, returns it as a string + mg.write(str) -- writes string to the client + mg.include(path) -- sources another Lua file + mg.redirect(uri) -- internal redirect to a given URI + mg.onerror(msg) -- error handler, can be overridden + mg.version -- a string that holds Mongoose version + mg.request_info -- a table with request information + + +**IMPORTANT: Mongoose does not send HTTP headers for Lua pages. Therefore, +every Lua Page must begin with HTTP reply line and headers**, like this: print('HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n') ?> ... the rest of the web page ... -It is easy to do things like redirects, for example: - - print('HTTP/1.0 302 Found\r\nLocation: http://google.com\r\n\r\n') ?> - To serve Lua Page, mongoose creates Lua context. That context is used for all Lua blocks within the page. That means, all Lua blocks on the same page share the same context. If one block defines a variable, for example, that diff --git a/examples/lua/prime_numbers.lp b/examples/lua/prime_numbers.lp index b3edc129..a162f242 100644 --- a/examples/lua/prime_numbers.lp +++ b/examples/lua/prime_numbers.lp @@ -1,8 +1,5 @@ - - -- Lua server pages have full control over the output, including HTTP - -- headers they send to the client. Send HTTP headers: - print('HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n') -?> +HTTP/1.0 200 OK +Content-Type: text/htmlPrime numbers from 0 to 100, calculated by Lua:
@@ -18,7 +15,7 @@ end for i = 1, 100 do - if is_prime(i) then print('' .. i .. ' ') end + if is_prime(i) then mg.write('' .. i .. ' ') end end ?> @@ -27,15 +24,16 @@- POST data: [ print(read())?>] - request method: [ print(request_info.request_method) ?>] - IP/port: [ print(request_info.remote_ip, ':', request_info.remote_port) ?>] - URI: [ print(request_info.uri) ?>] - HTTP version [ print(request_info.http_version) ?>] + POST data: [ mg.write(mg.read())?>] + request method: [ mg.write(mg.request_info.request_method) ?>] + IP/port: [ mg.write(mg.request_info.remote_ip, ':', + mg.request_info.remote_port) ?>] + URI: [ mg.write(mg.request_info.uri) ?>] + HTTP version [ mg.write(mg.request_info.http_version) ?>] HEADERS: - for name, value in pairs(request_info.http_headers) do - print(name, ':', value, '\n') + for name, value in pairs(mg.request_info.http_headers) do + mg.write(name, ':', value, '\n') end ?>diff --git a/mod_lua.c b/mod_lua.c new file mode 100644 index 00000000..248ce0b3 --- /dev/null +++ b/mod_lua.c @@ -0,0 +1,259 @@ +#include
This is an example Lua server page served by Mongoose web server. Mongoose has Lua, Sqlite, and other functionality built in the binary. This example page stores the request in the Sqlite database, and shows all requests done previously.
-Today is print(os.date("%A")) ?> +
Today is mg.write(os.date("%A")) ?>
+ -- for k,v in pairs(_G) do mg.write(k, '\n') end + -- Open database local db = sqlite3.open('requests.db') -- Setup a trace callback, to show SQL statements we'll be executing. - -- db:trace(function(data, sql) print('Executing: ' .. sql .. '\n') end, nil) + -- db:trace(function(data, sql) mg.write('Executing: ', sql: '\n') end, nil) -- Create a table if it is not created already db:exec([[ @@ -27,24 +28,26 @@ all requests done previously. timestamp NOT NULL, method NOT NULL, uri NOT NULL, - user_agent + addr ); ]]) + -- Add entry about this request local stmt = db:prepare( 'INSERT INTO requests VALUES(NULL, datetime("now"), ?, ?, ?);'); - stmt:bind_values(request_info.request_method, request_info.uri, - request_info.http_headers['User-Agent']) + stmt:bind_values(mg.request_info.request_method, + mg.request_info.uri, + mg.request_info.remote_port) stmt:step() stmt:finalize() -- Show all previous records - print('Previous requests:\n') + mg.write('Previous requests:\n') stmt = db:prepare('SELECT * FROM requests ORDER BY id DESC;') while stmt:step() == sqlite3.ROW do local v = stmt:get_values() - print(v[1] .. ' ' .. v[2] .. ' ' .. v[3] .. ' ' + mg.write(v[1] .. ' ' .. v[2] .. ' ' .. v[3] .. ' ' .. v[4] .. ' ' .. v[5] .. '\n') end diff --git a/test/unit_test.c b/test/unit_test.c index 096d9dcc..40c90745 100644 --- a/test/unit_test.c +++ b/test/unit_test.c @@ -467,13 +467,13 @@ static void test_lua(void) { ASSERT(lua_gettop(L) == 0); check_lua_expr(L, "'hi'", "hi"); - check_lua_expr(L, "request_info.request_method", "POST"); - check_lua_expr(L, "request_info.uri", "/foo/bar"); - check_lua_expr(L, "request_info.num_headers", "2"); - check_lua_expr(L, "request_info.remote_ip", "0"); - check_lua_expr(L, "request_info.http_headers['Content-Length']", "12"); - check_lua_expr(L, "request_info.http_headers['Connection']", "close"); - (void) luaL_dostring(L, "post = read()"); + check_lua_expr(L, "mg.request_info.request_method", "POST"); + check_lua_expr(L, "mg.request_info.uri", "/foo/bar"); + check_lua_expr(L, "mg.request_info.num_headers", "2"); + check_lua_expr(L, "mg.request_info.remote_ip", "0"); + check_lua_expr(L, "mg.request_info.http_headers['Content-Length']", "12"); + check_lua_expr(L, "mg.request_info.http_headers['Connection']", "close"); + (void) luaL_dostring(L, "post = mg.read()"); check_lua_expr(L, "# post", "12"); check_lua_expr(L, "post", "hello world!"); lua_close(L);