def send_body(self,DATA,code,msg,desc,ctype='application/octet-stream',headers={}): """ send a body in one part """ self.send_response(code,message=msg) self.send_header("Accept-Ranges", "bytes") ctype_set = False for a,v in headers.items(): if a.lower() == "content-type": ctype_set = True for a,v in headers.items(): self.send_header(a,v) if (type(DATA) is type("")) or DATA is None: if DATA: self.send_header("Content-Length", str(len(DATA))) else: self.send_header("Content-Length", "0") DATA = "" self.end_headers() self.data.append(DATA) else: # data is an s3server.file_iter self.send_header("Content-Length", str(DATA.size)) self.end_headers() self.data = DATA
def get_headers(self, **headers): headers = wsgiref.headers.Headers([(k.replace('_', '-'), v) for k,v in headers.items() if v]) if not headers['accept']: headers.add_header('Accept', self.accept) if self.account and self.password: encoded = base64.b64encode("%s:%s" % (self.account, self.password)) headers.add_header('Authorization', "Basic %s" % encoded) return dict(headers.items())
def encode_request(headers, **kwargs): if hasattr(headers, "items"): headers = headers.items() data = "".join("%s: %s\r\n" % (k, v) for k, v in headers) + "".join( "X-Goa-%s: %s\r\n" % (k.title(), v) for k, v in kwargs.iteritems() ) return base64.b64encode(zlib.compress(data)).rstrip()
def __init__( self, uri, method, headers=None, body="", scheme="http", host="", port=80, content_length=0, request_protocol="HTTP/1.0", cookies=None, ): self.raw_uri = uri self.method = method.upper() self.body = body self.scheme = scheme self.host = host self.port = int(port) self.content_length = int(content_length) self.request_protocol = request_protocol self._cookies = cookies or http.cookies.SimpleCookie() self.COOKIES = {} # For caching. self._GET, self._POST, self._PUT = None, None, None if not headers: headers = {} # `Headers` is specific about wanting a list of tuples, so just doing # `headers.items()` isn't good enough here. self.headers = wsgiref.headers.Headers([(k, v) for k, v in headers.items()]) for key, morsel in self._cookies.items(): self.COOKIES[key] = morsel.value uri_bits = self.split_uri(self.raw_uri) domain_bits = uri_bits.get("netloc", ":").split(":", 1) self.path = uri_bits["path"] self.query = uri_bits.get("query", {}) self.fragment = uri_bits.get("fragment", "") if not self.host: self.host = domain_bits[0] if len(domain_bits) > 1 and domain_bits[1]: self.port = int(domain_bits[1])
def _normalize_headers(headers): """Normalize a headers set to a list with lowercased names. Args: headers: A sequence of pairs, a dict or a wsgiref.headers.Headers object. Returns: headers, converted to a sequence of pairs (if it was not already), with all of the header names lowercased. """ if (isinstance(headers, dict) or isinstance(headers, wsgiref.headers.Headers)): headers = list(headers.items()) return [(name.lower(), value) for name, value in headers]
def encode_request(headers, **kwargs): if hasattr(headers, 'items'): headers = headers.items() data = ''.join('%s: %s\r\n' % (k, v) for k, v in headers) + ''.join('X-Goa-%s: %s\r\n' % (k.title(), v) for k, v in kwargs.iteritems()) return base64.b64encode(zlib.compress(data)).rstrip()
def handle(self, environ, start_response, url_map, match, request_id, request_type): """Serves this request by forwarding it to the runtime process. Args: environ: An environ dict for the request as defined in PEP-333. start_response: A function with semantics defined in PEP-333. url_map: An appinfo.URLMap instance containing the configuration for the handler matching this request. match: A re.MatchObject containing the result of the matched URL pattern. request_id: A unique string id associated with the request. request_type: The type of the request. See instance.*_REQUEST module constants. Yields: A sequence of strings containing the body of the HTTP response. """ if self._prior_error: yield self._handle_error(self._prior_error, start_response) return environ[http_runtime_constants.SCRIPT_HEADER] = match.expand( url_map.script) if request_type == instance.BACKGROUND_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'background' elif request_type == instance.SHUTDOWN_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'shutdown' elif request_type == instance.INTERACTIVE_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'interactive' for name in http_runtime_constants.ENVIRONS_TO_PROPAGATE: if http_runtime_constants.INTERNAL_ENVIRON_PREFIX + name not in environ: value = environ.get(name, None) if value is not None: environ[http_runtime_constants.INTERNAL_ENVIRON_PREFIX + name] = value headers = util.get_headers_from_environ(environ) if environ.get('QUERY_STRING'): url = '%s?%s' % (urllib.quote( environ['PATH_INFO']), environ['QUERY_STRING']) else: url = urllib.quote(environ['PATH_INFO']) if 'CONTENT_LENGTH' in environ: headers['CONTENT-LENGTH'] = environ['CONTENT_LENGTH'] data = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])) else: data = '' cookies = environ.get('HTTP_COOKIE') user_email, admin, user_id = login.get_user_info(cookies) if user_email: nickname, organization = user_email.split('@', 1) else: nickname = '' organization = '' headers[http_runtime_constants.REQUEST_ID_HEADER] = request_id headers[http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Id'] = (user_id) headers[http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Email'] = (user_email) headers[http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Is-Admin'] = (str(int(admin))) headers[http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Nickname'] = (nickname) headers[http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Organization'] = (organization) headers['X-AppEngine-Country'] = 'ZZ' connection = httplib.HTTPConnection(self._host, self._port) with contextlib.closing(connection): try: connection.connect() connection.request(environ.get('REQUEST_METHOD', 'GET'), url, data, dict(headers.items())) try: response = connection.getresponse() except httplib.HTTPException as e: # The runtime process has written a bad HTTP response. For example, # a Go runtime process may have crashed in app-specific code. yield self._handle_error( 'the runtime process gave a bad HTTP response: %s' % e, start_response) return # Ensures that we avoid merging repeat headers into a single header, # allowing use of multiple Set-Cookie headers. headers = [] for name in response.msg: for value in response.msg.getheaders(name): headers.append((name, value)) response_headers = wsgiref.headers.Headers(headers) error_file = self._get_error_file() if (error_file and http_runtime_constants.ERROR_CODE_HEADER in response_headers): try: with open(error_file) as f: content = f.read() except IOError: content = 'Failed to load error handler' logging.exception('failed to load error file: %s', error_file) start_response('500 Internal Server Error', [('Content-Type', 'text/html'), ('Content-Length', str(len(content)))]) yield content return del response_headers[http_runtime_constants.ERROR_CODE_HEADER] start_response('%s %s' % (response.status, response.reason), response_headers.items()) # Yield the response body in small blocks. while True: try: block = response.read(512) if not block: break yield block except httplib.HTTPException: # The runtime process has encountered a problem, but has not # necessarily crashed. For example, a Go runtime process' HTTP # handler may have panicked in app-specific code (which the http # package will recover from, so the process as a whole doesn't # crash). At this point, we have already proxied onwards the HTTP # header, so we cannot retroactively serve a 500 Internal Server # Error. We silently break here; the runtime process has presumably # already written to stderr (via the Tee). break except Exception: with self._process_lock: if self._process and self._process.poll() is not None: # The development server is in a bad state. Log and return an error # message. self._prior_error = ( 'the runtime process for the instance running ' 'on port %d has unexpectedly quit' % (self._port)) yield self._handle_error(self._prior_error, start_response) else: raise
def handle(self, environ, start_response, url_map, match, request_id, request_type): """Serves this request by forwarding it to the runtime process. Args: environ: An environ dict for the request as defined in PEP-333. start_response: A function with semantics defined in PEP-333. url_map: An appinfo.URLMap instance containing the configuration for the handler matching this request. match: A re.MatchObject containing the result of the matched URL pattern. request_id: A unique string id associated with the request. request_type: The type of the request. See instance.*_REQUEST module constants. Yields: A sequence of strings containing the body of the HTTP response. """ environ[http_runtime_constants.SCRIPT_HEADER] = match.expand(url_map.script) if request_type == instance.BACKGROUND_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'background' elif request_type == instance.SHUTDOWN_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'shutdown' elif request_type == instance.INTERACTIVE_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'interactive' for name in http_runtime_constants.ENVIRONS_TO_PROPAGATE: if http_runtime_constants.INTERNAL_ENVIRON_PREFIX + name not in environ: value = environ.get(name, None) if value is not None: environ[ http_runtime_constants.INTERNAL_ENVIRON_PREFIX + name] = value headers = util.get_headers_from_environ(environ) if environ.get('QUERY_STRING'): url = '%s?%s' % (urllib.quote(environ['PATH_INFO']), environ['QUERY_STRING']) else: url = urllib.quote(environ['PATH_INFO']) if 'CONTENT_LENGTH' in environ: headers['CONTENT-LENGTH'] = environ['CONTENT_LENGTH'] data = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])) else: data = '' cookies = environ.get('HTTP_COOKIE') user_email, admin, user_id = login.get_user_info(cookies) if user_email: nickname, organization = user_email.split('@', 1) else: nickname = '' organization = '' headers[http_runtime_constants.REQUEST_ID_HEADER] = request_id headers[http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Id'] = ( user_id) headers[http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Email'] = ( user_email) headers[ http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Is-Admin'] = ( str(int(admin))) headers[ http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Nickname'] = ( nickname) headers[ http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Organization'] = ( organization) headers['X-AppEngine-Country'] = 'ZZ' connection = httplib.HTTPConnection(self._host, self._port) with contextlib.closing(connection): try: connection.connect() connection.request(environ.get('REQUEST_METHOD', 'GET'), url, data, dict(headers.items())) response = connection.getresponse() # Ensures that we avoid merging repeat headers into a single header, # allowing use of multiple Set-Cookie headers. headers = [] for name in response.msg: for value in response.msg.getheaders(name): headers.append((name, value)) response_headers = wsgiref.headers.Headers(headers) error_file = self._get_error_file() if (error_file and http_runtime_constants.ERROR_CODE_HEADER in response_headers): try: with open(error_file) as f: content = f.read() except IOError: content = 'Failed to load error handler' logging.exception('failed to load error file: %s', error_file) start_response('500 Internal Server Error', [('Content-Type', 'text/html'), ('Content-Length', str(len(content)))]) yield content return del response_headers[http_runtime_constants.ERROR_CODE_HEADER] start_response('%s %s' % (response.status, response.reason), response_headers.items()) # Yield the response body in small blocks. block = response.read(512) while block: yield block block = response.read(512) except Exception: with self._process_lock: if self._process and self._process.poll() is not None: # The development server is in a bad state. Log and return an error # message and quit. message = ('the runtime process for the instance running on port ' '%d has unexpectedly quit; exiting the development ' 'server' % ( self._port)) logging.error(message) start_response('500 Internal Server Error', [('Content-Type', 'text/plain'), ('Content-Length', str(len(message)))]) shutdown.async_quit() yield message else: raise
def handle(self, environ, start_response, url_map, match, request_id, request_type): """Serves this request by forwarding it to the runtime process. Args: environ: An environ dict for the request as defined in PEP-333. start_response: A function with semantics defined in PEP-333. url_map: An appinfo.URLMap instance containing the configuration for the handler matching this request. match: A re.MatchObject containing the result of the matched URL pattern. request_id: A unique string id associated with the request. request_type: The type of the request. See instance.*_REQUEST module constants. Yields: A sequence of strings containing the body of the HTTP response. """ if self._prior_error: logging.error(self._prior_error) yield self._respond_with_error(self._prior_error, start_response) return environ[http_runtime_constants.SCRIPT_HEADER] = match.expand(url_map.script) if request_type == instance.BACKGROUND_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'background' elif request_type == instance.SHUTDOWN_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'shutdown' elif request_type == instance.INTERACTIVE_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'interactive' for name in http_runtime_constants.ENVIRONS_TO_PROPAGATE: if http_runtime_constants.APPENGINE_ENVIRON_PREFIX + name not in environ: value = environ.get(name, None) if value is not None: environ[ http_runtime_constants.APPENGINE_ENVIRON_PREFIX + name] = value headers = util.get_headers_from_environ(environ) if environ.get('QUERY_STRING'): url = '%s?%s' % (urllib.quote(environ['PATH_INFO']), environ['QUERY_STRING']) else: url = urllib.quote(environ['PATH_INFO']) if 'CONTENT_LENGTH' in environ: headers['CONTENT-LENGTH'] = environ['CONTENT_LENGTH'] data = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])) else: data = None cookies = environ.get('HTTP_COOKIE') user_email, admin, user_id = login.get_user_info(cookies) if user_email: nickname, organization = user_email.split('@', 1) else: nickname = '' organization = '' headers[self.request_id_header_name] = request_id headers[http_runtime_constants.APPENGINE_HEADER_PREFIX + 'User-Id'] = ( user_id) headers[http_runtime_constants.APPENGINE_HEADER_PREFIX + 'User-Email'] = ( user_email) headers[ http_runtime_constants.APPENGINE_HEADER_PREFIX + 'User-Is-Admin'] = ( str(int(admin))) headers[ http_runtime_constants.APPENGINE_HEADER_PREFIX + 'User-Nickname'] = ( nickname) headers[http_runtime_constants.APPENGINE_HEADER_PREFIX + 'User-Organization'] = organization headers['X-AppEngine-Country'] = 'ZZ' connection = httplib.HTTPConnection(self._host, self._port) with contextlib.closing(connection): try: connection.connect() connection.request(environ.get('REQUEST_METHOD', 'GET'), url, data, dict(headers.items())) try: response = connection.getresponse() except httplib.HTTPException as e: # The runtime process has written a bad HTTP response. For example, # a Go runtime process may have crashed in app-specific code. yield self._respond_with_error( 'the runtime process gave a bad HTTP response: %s' % e, start_response) return # Ensures that we avoid merging repeat headers into a single header, # allowing use of multiple Set-Cookie headers. headers = [] for name in response.msg: for value in response.msg.getheaders(name): headers.append((name, value)) response_headers = wsgiref.headers.Headers(headers) if self._error_handler_file and ( http_runtime_constants.ERROR_CODE_HEADER in response_headers): try: with open(self._error_handler_file) as f: content = f.read() except IOError: content = 'Failed to load error handler' logging.exception('failed to load error file: %s', self._error_handler_file) start_response('500 Internal Server Error', [('Content-Type', 'text/html'), ('Content-Length', str(len(content)))]) yield content return del response_headers[http_runtime_constants.ERROR_CODE_HEADER] start_response('%s %s' % (response.status, response.reason), response_headers.items()) # Yield the response body in small blocks. while True: try: block = response.read(512) if not block: break yield block except httplib.HTTPException: # The runtime process has encountered a problem, but has not # necessarily crashed. For example, a Go runtime process' HTTP # handler may have panicked in app-specific code (which the http # package will recover from, so the process as a whole doesn't # crash). At this point, we have already proxied onwards the HTTP # header, so we cannot retroactively serve a 500 Internal Server # Error. We silently break here; the runtime process has presumably # already written to stderr (via the Tee). break except Exception: if self._instance_died_unexpectedly(): yield self._respond_with_error( 'the runtime process for the instance running on port %d has ' 'unexpectedly quit' % self._port, start_response) else: raise
def handle(self, environ, start_response, url_map, match, request_id, request_type): """Serves this request by forwarding it to the runtime process. Args: environ: An environ dict for the request as defined in PEP-333. start_response: A function with semantics defined in PEP-333. url_map: An appinfo.URLMap instance containing the configuration for the handler matching this request. match: A re.MatchObject containing the result of the matched URL pattern. request_id: A unique string id associated with the request. request_type: The type of the request. See instance.*_REQUEST module constants. Yields: A sequence of strings containing the body of the HTTP response. """ environ[http_runtime_constants.SCRIPT_HEADER] = match.expand(url_map.script) if request_type == instance.BACKGROUND_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'background' elif request_type == instance.SHUTDOWN_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'shutdown' elif request_type == instance.INTERACTIVE_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'interactive' for name in http_runtime_constants.ENVIRONS_TO_PROPAGATE: if http_runtime_constants.INTERNAL_ENVIRON_PREFIX + name not in environ: value = environ.get(name, None) if value is not None: environ[ http_runtime_constants.INTERNAL_ENVIRON_PREFIX + name] = value headers = wsgiref.headers.Headers([]) for header, value in environ.iteritems(): if header.startswith('HTTP_'): headers[header[5:].replace('_', '-')] = value # Content-Type is special; it does not start with 'HTTP_'. if 'CONTENT_TYPE' in environ: headers['CONTENT-TYPE'] = environ['CONTENT_TYPE'] if environ.get('QUERY_STRING'): url = '%s?%s' % (urllib.quote(environ['PATH_INFO']), environ['QUERY_STRING']) else: url = urllib.quote(environ['PATH_INFO']) if 'CONTENT_LENGTH' in environ: headers['CONTENT-LENGTH'] = environ['CONTENT_LENGTH'] data = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])) else: data = '' cookies = environ.get('HTTP_COOKIE') user_email, admin, user_id = login.get_user_info(cookies) if user_email: nickname, organization = user_email.split('@', 1) else: nickname = '' organization = '' headers[http_runtime_constants.REQUEST_ID_HEADER] = request_id headers[ http_runtime_constants.INTERNAL_HEADER_PREFIX + 'Datacenter'] = 'us1' headers[http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Id'] = ( user_id) headers[http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Email'] = ( user_email) headers[ http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Is-Admin'] = ( str(int(admin))) headers[ http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Nickname'] = ( nickname) headers[ http_runtime_constants.INTERNAL_HEADER_PREFIX + 'User-Organization'] = ( organization) headers['X-AppEngine-Country'] = 'ZZ' connection = httplib.HTTPConnection(self._host, self._port) with contextlib.closing(connection): connection.connect() connection.request(environ.get('REQUEST_METHOD', 'GET'), url, data, dict(headers.items())) response = connection.getresponse() response_headers = wsgiref.headers.Headers(response.getheaders()) error_file = self._get_error_file() if (error_file and http_runtime_constants.ERROR_CODE_HEADER in response_headers): try: with open(error_file) as f: content = f.read() except IOError: content = 'Failed to load error handler' logging.exception('failed to load error file: %s', error_file) start_response('500 Internal Server Error', [('Content-Type', 'text/html'), ('Content-Length', str(len(content)))]) yield content return del response_headers[http_runtime_constants.ERROR_CODE_HEADER] start_response('%s %s' % (response.status, response.reason), response_headers.items()) # Yield the response body in small blocks. block = response.read(512) while block: yield block block = response.read(512)
def handle(self, environ, start_response, url_map, match, request_id, request_type): """Serves this request by forwarding it to the runtime process. Args: environ: An environ dict for the request as defined in PEP-333. start_response: A function with semantics defined in PEP-333. url_map: An appinfo.URLMap instance containing the configuration for the handler matching this request. match: A re.MatchObject containing the result of the matched URL pattern. request_id: A unique string id associated with the request. request_type: The type of the request. See instance.*_REQUEST module constants. Yields: A sequence of strings containing the body of the HTTP response. """ environ[http_runtime_constants.SCRIPT_HEADER] = match.expand( url_map.script) if request_type == instance.BACKGROUND_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'background' elif request_type == instance.SHUTDOWN_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'shutdown' elif request_type == instance.INTERACTIVE_REQUEST: environ[http_runtime_constants.REQUEST_TYPE_HEADER] = 'interactive' for name in http_runtime_constants.ENVIRONS_TO_PROPAGATE: if http_runtime_constants.INTERNAL_ENVIRON_PREFIX + name not in environ: value = environ.get(name, None) if value is not None: environ[http_runtime_constants.INTERNAL_ENVIRON_PREFIX + name] = value headers = util.get_headers_from_environ(environ) if environ.get('QUERY_STRING'): url = '%s?%s' % (urllib.quote( environ['PATH_INFO']), environ['QUERY_STRING']) else: url = urllib.quote(environ['PATH_INFO']) if 'CONTENT_LENGTH' in environ: headers['CONTENT-LENGTH'] = environ['CONTENT_LENGTH'] data = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH'])) else: data = '' cookies = environ.get('HTTP_COOKIE') user_email, admin, user_id = login.get_user_info(cookies) if user_email: nickname, organization = user_email.split('@', 1) else: nickname = '' organization = '' headers[http_runtime_constants.REQUEST_ID_HEADER] = request_id prefix = http_runtime_constants.INTERNAL_HEADER_PREFIX # The Go runtime from the 1.9.48 SDK looks for different headers. if self._module_configuration.runtime == 'go': headers['X-Appengine-Dev-Request-Id'] = request_id prefix = 'X-Appengine-' headers[prefix + 'User-Id'] = (user_id) headers[prefix + 'User-Email'] = (user_email) headers[prefix + 'User-Is-Admin'] = (str(int(admin))) headers[prefix + 'User-Nickname'] = (nickname) headers[prefix + 'User-Organization'] = (organization) headers['X-AppEngine-Country'] = 'ZZ' connection = httplib.HTTPConnection(self._host, self._port) with contextlib.closing(connection): try: connection.connect() connection.request(environ.get('REQUEST_METHOD', 'GET'), url, data, dict(headers.items())) response = connection.getresponse() # Ensures that we avoid merging repeat headers into a single header, # allowing use of multiple Set-Cookie headers. headers = [] for name in response.msg: for value in response.msg.getheaders(name): headers.append((name, value)) response_headers = wsgiref.headers.Headers(headers) error_file = self._get_error_file() if (error_file and http_runtime_constants.ERROR_CODE_HEADER in response_headers): try: with open(error_file) as f: content = f.read() except IOError: content = 'Failed to load error handler' logging.exception('failed to load error file: %s', error_file) start_response('500 Internal Server Error', [('Content-Type', 'text/html'), ('Content-Length', str(len(content)))]) yield content return del response_headers[http_runtime_constants.ERROR_CODE_HEADER] start_response('%s %s' % (response.status, response.reason), response_headers.items()) # Yield the response body in small blocks. block = response.read(512) while block: yield block block = response.read(512) except Exception: with self._process_lock: if self._process and self._process.poll() is not None: # The development server is in a bad state. Log and return an error # message and quit. message = ( 'the runtime process for the instance running on port ' '%d has unexpectedly quit; exiting the development ' 'server' % (self._port)) logging.error(message) start_response('500 Internal Server Error', [('Content-Type', 'text/plain'), ('Content-Length', str(len(message)))]) shutdown.async_quit() yield message else: raise