Always close POST-connections (circumvents some strange browser behaviour in Firefox...
[project/luci.git] / libs / httpd / luasrc / httpd / server.lua
index 1b54b30..fd4db14 100644 (file)
@@ -2,6 +2,7 @@
 
 HTTP server implementation for LuCI - helper class
 (c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
+(c) 2008 Steven Barth <steven@midlink.org>
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
@@ -19,6 +20,7 @@ require("socket.http")
 require("luci.util")
 
 READ_BUFSIZE = 1024
+VERSION = 0.2
 
 
 VHost = luci.util.class()
@@ -105,11 +107,19 @@ function Server.error_overload(self, socket)
 end
 
 
-function Server.process( self, thread )
+function Server.process( self, client )
 
        -- Setup sockets and sources
-       local client = thread.socket
+       local thread = {
+               receive = function(self, ...) return luci.httpd.corecv(client, ...) end,
+               send = function(self, ...) return luci.httpd.cosend(client, ...) end,
+               close = function(self, ...) return client:close(...) end,
+               getfd = function(self, ...) return client:getfd(...) end,
+               dirty = function(self, ...) return client:dirty(...) end
+       }
+       
        client:settimeout( 0 )
+       
        local sourcein  = ltn12.source.empty()
        local sourcehdr = luci.http.protocol.header_source( thread )
        local sinkerr   = ltn12.sink.file( io.stderr )
@@ -119,20 +129,16 @@ function Server.process( self, thread )
        local reading = { client }
 
        local message, err
-
-       socket.sleep(5)
        
        repeat
                -- parse headers
                message, err = luci.http.protocol.parse_message_header( sourcehdr )
 
                if not message then
-                       self:error( client, 400, err )
+                       self:error( thread, 400, err )
                        break
                end     
                
-               coroutine.yield()
-               
                -- keep-alive
                if message.http_version == 1.1 then
                        close = (message.env.HTTP_CONNECTION == "close")
@@ -149,7 +155,7 @@ function Server.process( self, thread )
                        if message.http_version == 1.1 and message.headers['Expect'] and
                                message.headers['Expect'] == '100-continue'
                        then
-                               client:send("HTTP/1.1 100 Continue\r\n\r\n")
+                               thread:send("HTTP/1.1 100 Continue\r\n\r\n")
                        end
                        
                        if message.headers['Transfer-Encoding'] and
@@ -159,12 +165,14 @@ function Server.process( self, thread )
                                sourcein = socket.source("by-length", thread,
                                 tonumber(message.env.CONTENT_LENGTH))
                        else
-                               self:error( client, 411, luci.http.protocol.statusmsg[411] )
+                               self:error( thread, 411, luci.http.protocol.statusmsg[411] )
                                break;
                        end
-                       
+
+                       -- FIXME: Close for POST requests
+                       close = true
                else
-                       self:error( client, 405, luci.http.protocol.statusmsg[405] )
+                       self:error( thread, 405, luci.http.protocol.statusmsg[405] )
                        break;
                        
                end
@@ -172,22 +180,18 @@ function Server.process( self, thread )
 
                local host = self.vhosts[message.env.HTTP_HOST] or self.host
                if not host then
-                       self:error( client, 500, "Unable to find matching host" )
+                       self:error( thread, 500, "Unable to find matching host" )
                        break;
                end
                
-               coroutine.yield()
-               
                local response, sourceout = host:process(
                        message, sourcein, sinkerr,
                        client, io.stderr 
                )
                if not response then
-                       self:error( client, 500, "Error processing handler" )
+                       self:error( thread, 500, "Error processing handler" )
                end
                
-               coroutine.yield()
-               
                -- Post process response
                local sinkmode = close and "close-when-done" or "keep-open"
                
@@ -208,20 +212,22 @@ function Server.process( self, thread )
                end
                
                
-               local sinkout = socket.sink(sinkmode, client)
+               local sinkout = socket.sink(sinkmode, thread)
                
                local header =
                        message.env.SERVER_PROTOCOL .. " " ..
                        tostring(response.status) .. " " ..
                        luci.http.protocol.statusmsg[response.status] .. "\r\n"
 
+               header = header .. "Server: LuCI HTTPd/" .. tostring(VERSION) .. "\r\n"
+
                
                for k,v in pairs(response.headers) do
                        header = header .. k .. ": " .. v .. "\r\n"
                end
                
-               client:send(header .. "\r\n")
-               
+               thread:send(header .. "\r\n")
+
                if sourceout then
                        local eof = false
                        repeat