def _handle_request(self, environ, start_response, inst=None,
                      request_type=instance.NORMAL_REQUEST):
    if inst:
      try:
        environ['SERVER_PORT'] = str(self.get_instance_port(inst.instance_id))
      except request_info.NotSupportedWithAutoScalingError:
        environ['SERVER_PORT'] = str(self.balanced_port)
    else:
      environ['SERVER_PORT'] = str(self.balanced_port)
    if 'HTTP_HOST' in environ:
      environ['SERVER_NAME'] = environ['HTTP_HOST'].split(':', 1)[0]
    environ['DEFAULT_VERSION_HOSTNAME'] = '%s:%s' % (
        environ['SERVER_NAME'], self._default_version_port)

    runtime_config = self._get_runtime_config()
    # Python monkey-patches out os.environ because some environment variables
    # are set per-request (REQUEST_ID_HASE and REQUEST_LOG_ID for example).
    # This means that although these environment variables could be set once
    # at startup, they must be passed in during each request.
    if (runtime_config.vm and
        self._module_configuration.effective_runtime == 'python27'):
      environ.update(http_runtime.get_vm_environment_variables(
          self._module_configuration, runtime_config))

    with self._request_data.request(
        environ,
        self._module_configuration) as request_id:
      should_log_request = not _REQUEST_LOGGING_BLACKLIST_RE.match(
          environ['PATH_INFO'])
      environ['REQUEST_ID_HASH'] = self.generate_request_id_hash()
      if should_log_request:
        environ['REQUEST_LOG_ID'] = self.generate_request_log_id()
        if 'HTTP_HOST' in environ:
          hostname = environ['HTTP_HOST']
        elif environ['SERVER_PORT'] == '80':
          hostname = environ['SERVER_NAME']
        else:
          hostname = '%s:%s' % (environ['SERVER_NAME'], environ['SERVER_PORT'])

        if environ.get('QUERY_STRING'):
          resource = '%s?%s' % (urllib.quote(environ['PATH_INFO']),
                                environ['QUERY_STRING'])
        else:
          resource = urllib.quote(environ['PATH_INFO'])
        email, _, _ = login.get_user_info(environ.get('HTTP_COOKIE', ''))
        method = environ.get('REQUEST_METHOD', 'GET')
        http_version = environ.get('SERVER_PROTOCOL', 'HTTP/1.0')

        logservice = apiproxy_stub_map.apiproxy.GetStub('logservice')
        logservice.start_request(
            request_id=request_id,
            user_request_id=environ['REQUEST_LOG_ID'],
            ip=environ.get('REMOTE_ADDR', ''),
            app_id=self._module_configuration.application,
            version_id=self._module_configuration.major_version,
            nickname=email.split('@', 1)[0],
            user_agent=environ.get('HTTP_USER_AGENT', ''),
            host=hostname,
            method=method,
            resource=resource,
            http_version=http_version,
            module=self._module_configuration.module_name)

      def wrapped_start_response(status, response_headers, exc_info=None):
        response_headers.append(('Server',
                                 http_runtime_constants.SERVER_SOFTWARE))
        if should_log_request:
          headers = wsgiref.headers.Headers(response_headers)
          status_code = int(status.split(' ', 1)[0])
          content_length = int(headers.get('Content-Length', 0))
          # TODO: Remove after the Files API is really gone.
          if (self._filesapi_warning_message is not None
              and self._request_data.was_filesapi_used(request_id)):
            logging.warning(self._filesapi_warning_message)
            self._insert_log_message(self._filesapi_warning_message,
                                     2, request_id)
          logservice.end_request(request_id, status_code, content_length)
          if any(resource.startswith(prefix) for prefix in _QUIETER_RESOURCES):
            level = logging.DEBUG
          else:
            level = logging.INFO
          logging.log(level, '%(module_name)s: '
                      '"%(method)s %(resource)s %(http_version)s" '
                      '%(status)d %(content_length)s',
                      {'module_name': self.name,
                       'method': method,
                       'resource': resource,
                       'http_version': http_version,
                       'status': status_code,
                       'content_length': content_length or '-'})
        return start_response(status, response_headers, exc_info)

      content_length = int(environ.get('CONTENT_LENGTH', '0'))

      if (environ['REQUEST_METHOD'] in ('GET', 'HEAD', 'DELETE', 'TRACE') and
          content_length != 0):
        # CONTENT_LENGTH may be empty or absent.
        wrapped_start_response('400 Bad Request', [])
        return ['"%s" requests may not contain bodies.' %
                environ['REQUEST_METHOD']]

      # Do not apply request limits to internal _ah handlers (known to break
      # blob uploads).
      # TODO: research if _ah handlers need limits.
      if (not environ.get('REQUEST_URI', '/').startswith('/_ah/') and
          content_length > _MAX_UPLOAD_BYTES):
        # As allowed by the RFC, cherrypy closes the connection for 413 errors.
        # Most clients do not handle this correctly and treat the page as
        # unavailable if the connection is closed before the client can send
        # all the data. To match the behavior of production, for large files
        # < 64M read the data to prevent the client bug from being triggered.







        if content_length <= _MAX_UPLOAD_NO_TRIGGER_BAD_CLIENT_BYTES:
          environ['wsgi.input'].read(content_length)
        status = '%d %s' % (httplib.REQUEST_ENTITY_TOO_LARGE,
                            httplib.responses[httplib.REQUEST_ENTITY_TOO_LARGE])
        wrapped_start_response(status, [])
        return ['Upload limited to %d megabytes.' % _MAX_UPLOAD_MEGABYTES]

      with self._handler_lock:
        handlers = self._handlers

      try:
        path_info = environ['PATH_INFO']
        path_info_normal = self._normpath(path_info)
        if path_info_normal != path_info:
          # While a 301 Moved Permanently makes more sense for non-normal
          # paths, prod issues a 302 so we do the same.
          return self._redirect_302_path_info(path_info_normal,
                                              environ,
                                              wrapped_start_response)
        if request_type in (instance.BACKGROUND_REQUEST,
                            instance.INTERACTIVE_REQUEST,
                            instance.SHUTDOWN_REQUEST):
          app = functools.partial(self._handle_script_request,
                                  url_map=_DUMMY_URLMAP,
                                  match=_EMPTY_MATCH,
                                  request_id=request_id,
                                  inst=inst,
                                  request_type=request_type)
          return request_rewriter.frontend_rewriter_middleware(app)(
              environ, wrapped_start_response)
        for handler in handlers:
          match = handler.match(path_info)
          if match:
            auth_failure = handler.handle_authorization(environ,
                                                        wrapped_start_response)
            if auth_failure is not None:
              return auth_failure

            if isinstance(handler, _ScriptHandler):
              app = functools.partial(self._handle_script_request,
                                      url_map=handler.url_map,
                                      match=match,
                                      request_id=request_id,
                                      inst=inst,
                                      request_type=request_type)
              return request_rewriter.frontend_rewriter_middleware(app)(
                  environ, wrapped_start_response)
            else:
              ret = handler.handle(match, environ, wrapped_start_response)
              if ret is not None:
                return ret
        return self._no_handler_for_request(environ, wrapped_start_response,
                                            request_id)
      except StandardError, e:
        if logging.getLogger('').isEnabledFor(logging.DEBUG):
          logging.exception('Request to %r failed', path_info)
        else:
          logging.error('Request to %r failed', path_info)
        wrapped_start_response('500 Internal Server Error', [], e)
        return []
supports dict-like items() access
dataset/ETHPy150Open GoogleCloudPlatform/python-compat-runtime/appengine-compat/exported_appengine_sdk/google/appengine/tools/devappserver2/module.py/Module._handle_request--crossover with--dataset/ETHPy150Open geopython/OWSLib/owslib/feature/wfs110.py/WebFeatureService_1_1_0.items