Example #1
0
    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
Example #2
0
 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())
Example #3
0
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()
Example #4
0
    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 _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]
Example #7
0
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()
Example #8
0
    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
Example #9
0
  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
Example #10
0
  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
Example #11
0
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()
Example #12
0
  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)
Example #13
0
    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