X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=libs%2Fhttpd%2Fluasrc%2Fhttpd%2Fserver.lua;h=2bb44bd022734eb371ae1066a6e818df9864b2c4;hp=7f973ac03cce72e73cdd2f40726c48df454e40c8;hb=4f630d647c7191ac9d8fd2dfcc8e93746faf391a;hpb=a038da390d7fd3a75b5a1045afbb4d9782556c57 diff --git a/libs/httpd/luasrc/httpd/server.lua b/libs/httpd/luasrc/httpd/server.lua index 7f973ac03..2bb44bd02 100644 --- a/libs/httpd/luasrc/httpd/server.lua +++ b/libs/httpd/luasrc/httpd/server.lua @@ -18,6 +18,7 @@ require("luci.util") READ_BUFSIZE = 1024 + VHost = luci.util.class() function VHost.__init__(self, handler) @@ -25,76 +26,75 @@ function VHost.__init__(self, handler) self.dhandler = {} end -function VHost.process(self, ...) - -- TODO: Dispatch handler -end - -function VHost.sethandler(self, handler, match) - if match then - self.dhandler[match] = handler - else - self.handler = handler - end -end +function VHost.process(self, request, sourcein, sinkout, sinkerr) + local handler = self.handler + local uri = request.env.REQUEST_URI:match("^([^?]*)") + -- SCRIPT_NAME + request.env.SCRIPT_NAME = "" -Server = luci.util.class() + -- Call URI part + request.env.PATH_INFO = uri -function Server.__init__(self, ip, port, base) - self.socket = socket.bind(ip, port) - self.socket:settimeout(0, "t") - self.clhandler = client_handler - self.errhandler = error503 - self.host = nil - self.vhosts = {} - - -- Clone another server - if base then - getmetatable(self).__index = base + for k, dhandler in pairs(self.dhandler) do + if k == uri or k.."/" == uri:sub(1, #k+1) then + handler = dhandler + request.env.SCRIPT_NAME = k + request.env.PATH_INFO = uri:sub(#k+1) + break; + end end -end --- Sets a vhost -function Server.setvhost(self, vhost, name) - if name then - self.vhosts[name] = vhost + if handler then + handler:process(request, sourcein, sinkout, sinkerr) + return true else - self.host = vhost + return false end end -function Server.error400(self, client, msg) - client:send( "HTTP/1.0 400 Bad request\r\n" ) - client:send( "Content-Type: text/plain\r\n\r\n" ) +function VHost.set_default_handler(self, handler) + self.handler = handler +end - if msg then - client:send( msg .. "\r\n" ) - end - client:close() +function VHost.set_handler(self, match, handler) + self.dhandler[match] = handler end -function Server.error503(self, client) - client:send( "HTTP/1.0 503 Server unavailable\r\n" ) - client:send( "Content-Type: text/plain\r\n\r\n" ) - client:send( "There are too many clients connected, try again later\r\n" ) -end -function Server.process(self, ...) - -- TODO: Dispatch vhost + +Server = luci.util.class() + +function Server.__init__(self, host) + self.clhandler = client_handler + self.errhandler = error503 + self.host = host + self.vhosts = {} end +function Server.set_default_vhost(self, vhost) + self.host = vhost +end -function Server.client_handler(self, client) +-- Sets a vhost +function Server.set_vhost(self, name, vhost) + self.vhosts[name] = vhost +end - client:settimeout( 0 ) +function Server.create_daemon_handlers(self) + return function(...) return self:process(...) end, + function(...) return self:error503(...) end +end +function Server.create_client_sources(self, client) -- Create LTN12 block source local block_source = function() - coroutine.yield() + -- Yielding here may cause chaos in coroutine based modules, be careful + -- coroutine.yield() local chunk, err, part = client:receive( READ_BUFSIZE ) @@ -108,6 +108,7 @@ function Server.client_handler(self, client) end + -- Create LTN12 line source local line_source = ltn12.source.simplify( function() @@ -139,14 +140,55 @@ function Server.client_handler(self, client) end end ) - coroutine.yield(client) + return block_source, line_source +end - -- parse message - local message, err = luci.http.protocol.parse_message_header( line_source ) +function Server.error400(self, socket, msg) + socket:send( "HTTP/1.0 400 Bad request\r\n" ) + socket:send( "Content-Type: text/plain\r\n\r\n" ) - if message then + if msg then + socket:send( msg .. "\r\n" ) + end + + socket:close() +end + +function Server.error500(self, socket, msg) + socket:send( "HTTP/1.0 500 Internal Server Error\r\n" ) + socket:send( "Content-Type: text/plain\r\n\r\n" ) + + if msg then + socket:send( msg .. "\r\n" ) + end + + socket:close() +end + +function Server.error503(self, socket) + socket:send( "HTTP/1.0 503 Server unavailable\r\n" ) + socket:send( "Content-Type: text/plain\r\n\r\n" ) + socket:send( "There are too many clients connected, try again later\r\n" ) + socket:close() +end + +function Server.process(self, client) + + client:settimeout( 0 ) + local sourcein, sourcehdr = self:create_client_sources(client) + local sinkerr = ltn12.sink.file(io.stderr) + + -- FIXME: Add keep-alive support + local sinkout = socket.sink("close-when-done", client) + + coroutine.yield() + + -- parse headers + local message, err = luci.http.protocol.parse_message_header( sourcehdr ) + + if message then -- If we have a HTTP/1.1 client and an Expect: 100-continue header then -- respond with HTTP 100 Continue message if message.http_version == 1.1 and message.headers['Expect'] and @@ -155,19 +197,18 @@ function Server.client_handler(self, client) client:send("HTTP/1.1 100 Continue\r\n\r\n") end - - local s, e = luci.http.protocol.parse_message_body( block_source, message ) - - -- XXX: debug - luci.util.dumptable( message ) - - if not s and e then - self:error400( client, e ) + local host = self.vhosts[message.env.HTTP_HOST] or self.host + if host then + if host:process(message, sourcein, sinkout, sinkerr) then + sinkout() + else + self:error500( client, "No suitable path handler found" ) + end + else + self:error500( client, "No suitable host handler found" ) end else self:error400( client, err ) + return nil end - - -- send response - self:error400( client, "Dummy response" ) end