def getRequestResponse(self, environ): env = environ.get headers = Headers(list(self.translateHeaders(environ))) protocol = tuple(map(int, env("SERVER_PROTOCOL")[5:].split("."))) request = wrappers.Request(None, env("REQUEST_METHOD"), env("wsgi.url_scheme"), env("PATH_INFO"), protocol, env("QUERY_STRING")) request.remote = wrappers.Host(env("REMOTE_ADDR"), env("REMTOE_PORT")) request.headers = headers request.script_name = env("SCRIPT_NAME") request.wsgi_environ = environ request.body = env("wsgi.input") response = wrappers.Response(None, request) response.gzip = "gzip" in request.headers.get("Accept-Encoding", "") return request, response
def simple(self, sock, code, message=""): """Simple Response Events Handler Send a simple response. """ short, long = RESPONSES.get(code, ( "???", "???", )) message = message or short response = wrappers.Response(sock) response.body = message response.status = "%s %s" % (code, message) if response.status[:3] == "413" and response.protocol == "HTTP/1.1": # Request Entity Too Large response.close = True response.headers.add_header("Connection", "close") self.push(Response(response), "response", self.channel)
def read(self, sock, data): """Read Event Handler Process any incoming data appending it to an internal buffer. Split the buffer by the standard HTTP delimiter CRLF and create Raw Event per line. Any unfinished lines of text, leave in the buffer. """ if sock in self._clients: request, response = self._clients[sock] if response.done: del self._clients[sock] if sock in self._clients: request, response = self._clients[sock] request.body.write(data) contentLength = int(request.headers.get("Content-Length", "0")) if not request.body.tell() == contentLength: return else: requestline, data = data.split("\n", 1) requestline = requestline.strip() method, path, protocol = requestline.split(" ", 2) scheme, location, path, params, qs, frag = urlparse(path) protocol = tuple(map(int, protocol[5:].split("."))) request = wrappers.Request(sock, method, scheme, path, protocol, qs) response = wrappers.Response(sock, request) self._clients[sock] = request, response if frag: error = HTTPError(request, response, 400) return self.push(error, "httperror", self.channel) if params: path = "%s;%s" % (path, params) # Unquote the path+params (e.g. "/this%20path" -> "this path"). # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2 # # But note that "...a URI must be separated into its components # before the escaped characters within those components can be # safely decoded." http://www.ietf.org/rfc/rfc2396.txt, sec 2.4.2 path = "%2F".join(map(unquote, quoted_slash.split(path))) # Compare request and server HTTP protocol versions, in case our # server does not support the requested protocol. Limit our output # to min(req, server). We want the following output: # request server actual written supported response # protocol protocol response protocol feature set # a 1.0 1.0 1.0 1.0 # b 1.0 1.1 1.1 1.0 # c 1.1 1.0 1.0 1.0 # d 1.1 1.1 1.1 1.1 # Notice that, in (b), the response will be "HTTP/1.1" even though # the client only understands 1.0. RFC 2616 10.5.6 says we should # only return 505 if the _major_ version is different. if not request.protocol[0] == request.server_protocol[0]: error = HTTPError(request, response, 505) return self.push(error, "httperror", self.channel) rp = request.protocol sp = request.server_protocol response.protocol = "HTTP/%s.%s" % min(rp, sp) headers, body = parseHeaders(StringIO(data)) request.headers = headers request.body.write(body) if headers.get("Expect", "") == "100-continue": return self.simple(sock, 100) contentLength = int(headers.get("Content-Length", "0")) if not request.body.tell() == contentLength: return # Persistent connection support if request.protocol == (1, 1): # Both server and client are HTTP/1.1 if request.headers.get("Connection", "").lower() == "close": response.close = True else: # Either the server or client (or both) are HTTP/1.0 if request.headers.get("Connection", "").lower() != "keep-alive": response.close = True request.body.seek(0) self.push(Request(request, response), "request", "web")