# HG changeset patch # User jbe # Date 1434731098 -7200 # Node ID 97d3ca77c86a886f4cb133806909edacdb9fecae # Parent 478d6237e17adbd6c7c3028826de6c0bc91ac8f1 Code cleanup, renamed functions, added documentation for HTTP module diff -r 478d6237e17a -r 97d3ca77c86a moonbridge_http.lua --- a/moonbridge_http.lua Fri Jun 19 16:54:33 2015 +0200 +++ b/moonbridge_http.lua Fri Jun 19 18:24:58 2015 +0200 @@ -647,7 +647,7 @@ local afterbound = false -- interpret 2 bytes after boundary ("\r\n" or "--") local terminated = false -- final boundary read local bigchunk = "" - request:set_request_body_streamer(function(chunk) + request:stream_request_body(function(chunk) if chunk == nil then if not terminated then request_error(true, "400 Bad Request", "Premature end of multipart/form-data request body") @@ -808,6 +808,15 @@ send(socket:write(key, ": ", value, "\r\n")) state = old_state end + -- method to announce (and enforce) connection close after sending the + -- response: + function request:close_after_finish() + assert_not_faulty() + if state == "headers_sent" or state == "finished" then + error("All HTTP headers have already been sent") + end + close_requested = true + end -- function to terminate header section in response, optionally flushing: -- (may be called multiple times unless response is finished) local function finish_headers(with_flush) @@ -935,7 +944,7 @@ streamed_post_param_patterns[#streamed_post_param_patterns+1] = {pattern, callback} end -- method to register request body stream handler - function request:set_request_body_streamer(callback) + function request:stream_request_body(callback) if state ~= "init" then error("Cannot setup request body streamer at this stage anymore") end @@ -962,8 +971,8 @@ consume_all() end -- method to stream request body - function request:stream_request_body(callback) - request:set_request_body_streamer(function(chunk) + function request:stream_request_body_now(callback) + request:stream_request_body(function(chunk) if chunk ~= nil then callback(chunk) end @@ -972,9 +981,13 @@ end -- metamethod to read special attibutes of request object: function request_mt:__index(key, value) - if key == "body" then + if key == "faulty" then + return state == "faulty" + elseif key == "fresh" then + return state == "init" and process_body_chunk == nil + elseif key == "body" then local chunks = {} - request:stream_request_body(function(chunk) + request:stream_request_body_now(function(chunk) chunks[#chunks+1] = chunk end) self.body = table.concat(chunks) diff -r 478d6237e17a -r 97d3ca77c86a reference.txt --- a/reference.txt Fri Jun 19 16:54:33 2015 +0200 +++ b/reference.txt Fri Jun 19 18:24:58 2015 +0200 @@ -432,34 +432,32 @@ A corresponding "Connection: close" header is automatically sent. +See also request:monologue(). + + +### request:consume_input() + +Starts processing the request body (if existent) to set the values +request.post_params, request.post_params_list, request.post_metadata, and +and request.post_metadata_list and/or to call POST field stream handlers that +have been previously registered with request:stream_post_param(...) or +request:stream_post_params(...), or to call a previously registered request +body stream handler that was set with request:set_request_body_streamer(). + +This method gets invoked automatically when the POST param tables +(request.post_params, etc.) are accessed or if request.body is accessed. + ### request.cookies A table with all cookies sent by the client. -### request.defer_reading() - -Disables automatic request body processing on write. Can be called before -sending a HTTP status code to send a response before the request has been fully -received. - -CAUTION: Responding to a request before the request body has been processed may -lead to a deadlock if the browser does not process the response while trying to -send the request. Therefore, this function should only be used if: - -- the TCP stack has enough buffer space for the response (i.e. if the response - is small enough), and if -- a timer is used to cancel the response in case of a deadlock. - -It is recommended to not use this function unless certain performance tweaks -are desired. - - ### request.faulty -Normally set to false. In case of a read or write error on the client -connection, this value is set to true before a Lua error is raised. +Normally set to false. In case of a write error on the client connection or +certain other unexpected errors, this value is set to true before a Lua error +is raised. A faulty request handle must not be used, or another Lua error will be raised. @@ -485,6 +483,12 @@ body, it is required to call request:finish(). +### request.fresh + +Set to false whenever the request object has been used (e.g. data has been read +or sent out, or a stream handler was installed); true otherwise. + + ### request.get_params A table that maps field names to their corresponding GET value. If there are @@ -543,6 +547,12 @@ The HTTP request method, e.g. "HEAD", "GET", or "POST". +### request:monologue() + +Same as request:close_after_finish() but additionally discards all input data +immediately. + + ### request.path The requested path without a leading slash and without the query part (e.g. @@ -599,25 +609,6 @@ request-target in section 5.3.4 in RFC 7230). -### request:process_request_body() - -Starts processing the request body (if existent) to set the values -request.post_params, request.post_params_list, request.post_metadata, and -and request.post_metadata_list and/or to call POST field stream handlers that -have been previously registered with request:stream_post_param(...) or -request:stream_post_params(...). - -This method gets invoked automatically when the POST param tables -(request.post_params, etc.) are accessed, or if a response is sent (to avoid -deadlocks with the webbrowser). (Note: Automatic request body processing on -write may be disabled by calling request:defer_reading().) - -After this method returned, all registered POST field stream handlers have -received all data. Registration of other POST field stream handlers is not -possible after this method has been called (or after request.post_params_list -or request.post_params have been accessed). - - ### request:send_data(...) Sends data as response body. All arguments are converted via tostring(...) and @@ -672,6 +663,9 @@ as second argument. - The second time without any arguments. +Note that request:consume_input() needs to be called to enforce streaming to +finish. + ### request:stream_post_params(pattern, callback) @@ -681,15 +675,20 @@ ### request:stream_request_body(callback) -Start streaming of request body. For each chunk of the request body, the -callback function is called with the corresponding chunk. End of data is -indicated through return of request:stream_request_body(...) (not by calling -the callback without arguments). +Registeres a stream handler for the whole request body. For each chunk of the +request body, the callback function is called with the corresponding chunk. End +of data is indicated by passing a nil value to the callback functuion. -The function may be called with nil instead of a callback function. In this -case, the request body is read and discarded. Only if nil is passed instead of -a callback, then the function may also be invoked when the request body has -already been read and/or processed. In the latter case, the function performs -no operation. +Note that request:consume_input() needs to be called to enforce streaming to +finish. +### request:stream_request_body_now(callback) + +Start streaming of request body immediately. On EOF the function returns and +the callback function is *not* called with nil as argument. + +Note that request:consume_input() needs to be called to enforce streaming to +finish. + +