📄 http.py
字号:
#============================================================================# This library is free software; you can redistribute it and/or# modify it under the terms of version 2.1 of the GNU Lesser General Public# License as published by the Free Software Foundation.## This library is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU# Lesser General Public License for more details.## You should have received a copy of the GNU Lesser General Public# License along with this library; if not, write to the Free Software# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA##============================================================================# Parts of this library are derived from Twisted:# Copyright (C) 2001 Matthew W. Lefkowitz## Copyright (C) 2005 Mike Wray <mike.wray@hp.com>#============================================================================from mimetools import Messagefrom cStringIO import StringIOimport mathimport socketimport timeimport cgiCONTINUE = 100SWITCHING_PROTOCOLS = 101OK = 200CREATED = 201ACCEPTED = 202NON_AUTHORITATIVE_INFORMATION = 203NO_CONTENT = 204RESET_CONTENT = 205PARTIAL_CONTENT = 206MULTI_STATUS = 207MULTIPLE_CHOICE = 300MOVED_PERMANENTLY = 301FOUND = 302SEE_OTHER = 303NOT_MODIFIED = 304USE_PROXY = 305TEMPORARY_REDIRECT = 307BAD_REQUEST = 400UNAUTHORIZED = 401PAYMENT_REQUIRED = 402FORBIDDEN = 403NOT_FOUND = 404NOT_ALLOWED = 405NOT_ACCEPTABLE = 406PROXY_AUTH_REQUIRED = 407REQUEST_TIMEOUT = 408CONFLICT = 409GONE = 410LENGTH_REQUIRED = 411PRECONDITION_FAILED = 412REQUEST_ENTITY_TOO_LARGE = 413REQUEST_URI_TOO_LONG = 414UNSUPPORTED_MEDIA_TYPE = 415REQUESTED_RANGE_NOT_SATISFIABLE = 416EXPECTATION_FAILED = 417INTERNAL_SERVER_ERROR = 500NOT_IMPLEMENTED = 501BAD_GATEWAY = 502SERVICE_UNAVAILABLE = 503GATEWAY_TIMEOUT = 504VERSION_NOT_SUPPORTED = 505INSUFFICIENT_STORAGE_SPACE = 507NOT_EXTENDED = 510NO_BODY_CODES = [ NO_CONTENT, NOT_MODIFIED ] STATUS = { CONTINUE : "Continue", SWITCHING_PROTOCOLS : "Switching protocols", OK : "OK", CREATED : "Created", ACCEPTED : "Accepted", NON_AUTHORITATIVE_INFORMATION : "Non-authoritative information", NO_CONTENT : "No content", RESET_CONTENT : "Reset content", PARTIAL_CONTENT : "Partial content", MULTI_STATUS : "Multi-status", MULTIPLE_CHOICE : "Multiple choice", MOVED_PERMANENTLY : "Moved permanently", FOUND : "Found", SEE_OTHER : "See other", NOT_MODIFIED : "Not modified", USE_PROXY : "Use proxy", TEMPORARY_REDIRECT : "Temporary redirect", BAD_REQUEST : "Bad request", UNAUTHORIZED : "Unauthorized", PAYMENT_REQUIRED : "Payment required", FORBIDDEN : "Forbidden", NOT_FOUND : "Not found", NOT_ALLOWED : "Not allowed", NOT_ACCEPTABLE : "Not acceptable", PROXY_AUTH_REQUIRED : "Proxy authentication required", REQUEST_TIMEOUT : "Request timeout", CONFLICT : "Conflict", GONE : "Gone", LENGTH_REQUIRED : "Length required", PRECONDITION_FAILED : "Precondition failed", REQUEST_ENTITY_TOO_LARGE : "Request entity too large", REQUEST_URI_TOO_LONG : "Request URI too long", UNSUPPORTED_MEDIA_TYPE : "Unsupported media type", REQUESTED_RANGE_NOT_SATISFIABLE : "Requested range not satisfiable", EXPECTATION_FAILED : "Expectation failed", INTERNAL_SERVER_ERROR : "Internal server error", NOT_IMPLEMENTED : "Not implemented", BAD_GATEWAY : "Bad gateway", SERVICE_UNAVAILABLE : "Service unavailable", GATEWAY_TIMEOUT : "Gateway timeout", VERSION_NOT_SUPPORTED : "HTTP version not supported", INSUFFICIENT_STORAGE_SPACE : "Insufficient storage space", NOT_EXTENDED : "Not extended", }def getStatus(code): return STATUS.get(code, "unknown")MULTIPART_FORM_DATA = 'multipart/form-data'URLENCODED = 'application/x-www-form-urlencoded'parseQueryArgs = cgi.parse_qsdef timegm(year, month, day, hour, minute, second): """Convert time tuple in GMT to seconds since epoch, GMT""" EPOCH = 1970 assert year >= EPOCH assert 1 <= month <= 12 days = 365*(year-EPOCH) + calendar.leapdays(EPOCH, year) for i in range(1, month): days = days + calendar.mdays[i] if month > 2 and calendar.isleap(year): days = days + 1 days = days + day - 1 hours = days*24 + hour minutes = hours*60 + minute seconds = minutes*60 + second return secondsdef stringToDatetime(dateString): """Convert an HTTP date string to seconds since epoch.""" parts = dateString.split(' ') day = int(parts[1]) month = int(monthname.index(parts[2])) year = int(parts[3]) hour, min, sec = map(int, parts[4].split(':')) return int(timegm(year, month, day, hour, min, sec))class HttpRequest: http_version = (1, 1) http_version_string = ("HTTP/%d.%d" % http_version) max_content_length = 10000 max_headers = 500 request_line = None request_method = None request_uri = None request_path = None request_query = None request_version = None content_length = 0 content = None etag = None close_connection = True response_code = 200 response_status = "OK" response_sent = False cached = False last_modified = None forceSSL = False def __init__(self, host, rin, out): self.host = host self.rin = rin self.out = out self.request_args = {} self.args = self.request_args self.request_headers = {} self.request_cookies = {} self.response_headers = {} self.response_cookies = {} self.output = StringIO() self.parseRequest() def isSecure(self): return self.forceSSL def getRequestMethod(self): return self.request_method def trim(self, str, ends): for end in ends: if str.endswith(end): str = str[ : -len(end) ] break return str def requestError(self, code, msg=None): self.sendError(code, msg) raise ValueError(self.response_status) def sendError(self, code, msg=None): self.setResponseCode(code, msg=msg) self.sendResponse() def parseRequestVersion(self, version): try: if not version.startswith('HTTP/'): raise ValueError version_string = version.split('/', 1)[1] version_codes = version_string.split('.') if len(version_codes) != 2: raise ValueError request_version = (int(version_codes[0]), int(version_codes[1])) except (ValueError, IndexError): self.requestError(400, "Bad request version (%s)" % `version`) def parseRequestLine(self): line = self.trim(self.request_line, ['\r\n', '\n']) line_fields = line.split() n = len(line_fields) if n == 3: [method, uri, version] = line_fields elif n == 2: [method, uri] = line_fields version = 'HTTP/0.9' else: self.requestError(BAD_REQUEST, "Bad request (%s)" % `line`) request_version = self.parseRequestVersion(version) if request_version > (2, 0): self.requestError(VERSION_NOT_SUPPORTED, "HTTP version not supported (%s)" % `version`) #if request_version >= (1, 1) and self.http_version >= (1, 1): # self.close_connection = False #else: # self.close_connection = True self.request_method = method self.method = method
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -