def CreateRequestHandler(root_path,
                         login_url,
                         static_caching=True,
                         default_partition=None,
                         interactive_console=True,
                         secret_hash='xxx'):
  """Creates a new BaseHTTPRequestHandler sub-class.

  This class will be used with the Python BaseHTTPServer module's HTTP server.

  Python's built-in HTTP server does not support passing context information
  along to instances of its request handlers. This function gets around that
  by creating a sub-class of the handler in a closure that has access to
  this context information.

  Args:
    root_path: Path to the root of the application running on the server.
    login_url: Relative URL which should be used for handling user logins.
    static_caching: True if browser caching of static files should be allowed.
    default_partition: Default partition to use in the application id.
    interactive_console: Whether to add the interactive console.

  Returns:
    Sub-class of BaseHTTPRequestHandler.
  """




















  application_module_dict = SetupSharedModules(sys.modules)


  application_config_cache = AppConfigCache()

  class DevAppServerRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
    """Dispatches URLs using patterns from a URLMatcher.

    The URLMatcher is created by loading an application's configuration file.
    Executes CGI scripts in the local process so the scripts can use mock
    versions of APIs.

    HTTP requests that correctly specify a user info cookie
    (dev_appserver_login.COOKIE_NAME) will have the 'USER_EMAIL' environment
    variable set accordingly. If the user is also an admin, the
    'USER_IS_ADMIN' variable will exist and be set to '1'. If the user is not
    logged in, 'USER_EMAIL' will be set to the empty string.

    On each request, raises an InvalidAppConfigError exception if the
    application configuration file in the directory specified by the root_path
    argument is invalid.
    """
    server_version = 'AppScaleServer/1.10'




    module_dict = application_module_dict
    module_manager = ModuleManager(application_module_dict)


    config_cache = application_config_cache

    rewriter_chain = CreateResponseRewritersChain()

    def __init__(self, *args, **kwargs):
      """Initializer.

      Args:
        args: Positional arguments passed to the superclass constructor.
        kwargs: Keyword arguments passed to the superclass constructor.
      """
      self._log_record_writer = logservice_stub.RequestLogWriter()
      BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kwargs)

    def version_string(self):
      """Returns server's version string used for Server HTTP header."""

      return self.server_version

    def do_GET(self):
      """Handle GET requests."""
      if self._HasNoBody('GET'):
        self._HandleRequest()

    def do_POST(self):
      """Handles POST requests."""
      self._HandleRequest()

    def do_PUT(self):
      """Handle PUT requests."""
      self._HandleRequest()

    def do_HEAD(self):
      """Handle HEAD requests."""
      if self._HasNoBody('HEAD'):
        self._HandleRequest()

    def do_OPTIONS(self):
      """Handles OPTIONS requests."""
      self._HandleRequest()

    def do_DELETE(self):
      """Handle DELETE requests."""
      self._HandleRequest()

    def do_TRACE(self):
      """Handles TRACE requests."""
      if self._HasNoBody('TRACE'):
        self._HandleRequest()

    def _HasNoBody(self, method):
      """Check for request body in HTTP methods where no body is permitted.

      If a request body is present a 400 (Invalid request) response is sent.

      Args:
        method: The request method.

      Returns:
        True if no request body is present, False otherwise.
      """


      content_length = int(self.headers.get('content-length', 0))
      if content_length:
        body = self.rfile.read(content_length)
        logging.warning('Request body in %s is not permitted: %s', method, body)
        self.send_response(httplib.BAD_REQUEST)
        return False
      return True

    def _Dispatch(self, dispatcher, socket_infile, outfile, env_dict):
      """Copy request data from socket and dispatch.

      Args:
        dispatcher: Dispatcher to handle request (MatcherDispatcher).
        socket_infile: Original request file stream.
        outfile: Output file to write response to.
        env_dict: Environment dictionary.
      """


      request_descriptor, request_file_name = tempfile.mkstemp('.tmp',
                                                               'request.')

      try:
        request_file = open(request_file_name, 'wb')
        try:
          CopyStreamPart(self.rfile,
                         request_file,
                         int(self.headers.get('content-length', 0)))
        finally:
          request_file.close()

        request_file = open(request_file_name, 'rb')
        try:
          app_server_request = AppServerRequest(self.path,
                                                None,
                                                self.headers,
                                                request_file,
                                                secret_hash)
          dispatcher.Dispatch(app_server_request,
                              outfile,
                              base_env_dict=env_dict)
        finally:
          request_file.close()
      finally:
        try:
          os.close(request_descriptor)



          try:
            os.remove(request_file_name)
          except __HOLE__, err:
            if getattr(err, 'winerror', 0) == os_compat.ERROR_SHARING_VIOLATION:
              logging.warning('Failed removing %s', request_file_name)
            else:
              raise
        except OSError, err:
          if err.errno != errno.ENOENT:
            raise

    def _HandleRequest(self):
      """Handles any type of request and prints exceptions if they occur."""



      host_name = self.headers.get('host') or self.server.server_name
      server_name = host_name.split(':', 1)[0]

      env_dict = {
          'REQUEST_METHOD': self.command,
          'REMOTE_ADDR': self.headers.get("X-Real-IP", self.client_address[0]),
          'SERVER_SOFTWARE': self.server_version,
          'SERVER_NAME': server_name,
          'SERVER_PROTOCOL': self.protocol_version,
          'SERVER_PORT': str(self.server.server_port),
      }

      full_url = GetFullURL(server_name, self.server.server_port, self.path)
      if len(full_url) > MAX_URL_LENGTH:
        msg = 'Requested URI too long: %s' % full_url
        logging.error(msg)
        self.send_response(httplib.REQUEST_URI_TOO_LONG, msg)
        return

      tbhandler = cgitb.Hook(file=self.wfile).handle
      try:

        config, explicit_matcher, from_cache = LoadAppConfig(
          root_path, self.module_dict, cache=self.config_cache,
          static_caching=static_caching, default_partition=default_partition)


        if not from_cache:
          self.module_manager.ResetModules()



        implicit_matcher = CreateImplicitMatcher(config,
                                                 self.module_dict,
                                                 root_path,
                                                 login_url)

        if self.path.startswith('/_ah/admin'):


          if any((handler.url == '/_ah/datastore_admin.*'
                  for handler in config.handlers)):
            self.headers['X-AppEngine-Datastore-Admin-Enabled'] = 'True'
          self.headers['X-AppEngine-Interactive-Console-Enabled'] = str(
              interactive_console)

        if config.api_version != API_VERSION:
          logging.error(
              "API versions cannot be switched dynamically: %r != %r",
              config.api_version, API_VERSION)
          sys.exit(1)

        (exclude, service_match) = ReservedPathFilter(
            config.inbound_services).ExcludePath(self.path)
        if exclude:
          logging.warning(
              'Request to %s excluded because %s is not enabled '
              'in inbound_services in app.yaml' % (self.path, service_match))
          self.send_response(httplib.NOT_FOUND)
          return

        if config.runtime == 'go':

          from google.appengine.ext import go
          go.APP_CONFIG = config

        version = GetVersionObject()
        env_dict['SDK_VERSION'] = version['release']
        env_dict['CURRENT_VERSION_ID'] = config.version + ".1"
        env_dict['APPLICATION_ID'] = config.application
        env_dict['DEFAULT_VERSION_HOSTNAME'] = self.server.frontend_hostport
        env_dict['APPENGINE_RUNTIME'] = config.runtime
        if config.runtime == 'python27' and config.threadsafe:
          env_dict['_AH_THREADSAFE'] = '1'



        global _request_time
        global _request_id
        _request_time = time.time()
        _request_id += 1

        request_id_hash = _generate_request_id_hash()
        env_dict['REQUEST_ID_HASH'] = request_id_hash
        os.environ['REQUEST_ID_HASH'] = request_id_hash



        cookies = ', '.join(self.headers.getheaders('cookie'))
        email_addr, user_id, admin, valid_cookie = \
                dev_appserver_login.GetUserInfo(cookies)

        self._log_record_writer.write_request_info(
            ip=env_dict['REMOTE_ADDR'],
            app_id=env_dict['APPLICATION_ID'],
            version_id=env_dict['CURRENT_VERSION_ID'],
            nickname=email_addr.split('@')[0],
            user_agent=self.headers.get('user-agent'),
            host=host_name)

        dispatcher = MatcherDispatcher(config, login_url, self.module_manager,
                                       [implicit_matcher, explicit_matcher])





        outfile = cStringIO.StringIO()
        try:
          self._Dispatch(dispatcher, self.rfile, outfile, env_dict)
        finally:
          self.module_manager.UpdateModuleFileModificationTimes()

        outfile.flush()
        outfile.seek(0)

        response = RewriteResponse(outfile, self.rewriter_chain, self.headers,
                                   env_dict)

        runtime_response_size = _RemainingDataSize(response.body)
        if self.command == 'HEAD' and runtime_response_size > 0:
          logging.warning('Dropping unexpected body in response to HEAD '
                          'request')
          response.body = cStringIO.StringIO('')
        elif (not response.large_response and
              runtime_response_size > MAX_RUNTIME_RESPONSE_SIZE):
          logging.error('Response too large: %d, max is %d',
                        runtime_response_size, MAX_RUNTIME_RESPONSE_SIZE)


          response.status_code = 500
          response.status_message = 'Forbidden'

          new_response = ('HTTP response was too large: %d.  '
                          'The limit is: %d.'
                          % (runtime_response_size,
                             MAX_RUNTIME_RESPONSE_SIZE))
          response.headers['Content-Length'] = str(len(new_response))
          response.body = cStringIO.StringIO(new_response)



      except yaml_errors.EventListenerError, e:
        title = 'Fatal error when loading application configuration'
        msg = '%s:\n%s' % (title, str(e))
        logging.error(msg)
        self.send_response(httplib.INTERNAL_SERVER_ERROR, title)
        self.wfile.write('Content-Type: text/html\r\n\r\n')
        self.wfile.write('<pre>%s</pre>' % cgi.escape(msg))
      except KeyboardInterrupt, e:



        logging.info('Server interrupted by user, terminating')
        self.server.stop_serving_forever()
      except CompileError, e:
        msg = 'Compile error:\n' + e.text + '\n'
        logging.error(msg)
        self.send_response(httplib.INTERNAL_SERVER_ERROR, 'Compile error')
        self.wfile.write('Content-Type: text/plain; charset=utf-8\r\n\r\n')
        self.wfile.write(msg)
      except ExecuteError, e:
        logging.error(e.text)
        self.send_response(httplib.INTERNAL_SERVER_ERROR, 'Execute error')
        self.wfile.write('Content-Type: text/html; charset=utf-8\r\n\r\n')
        self.wfile.write('<title>App failure</title>\n')
        self.wfile.write(e.text + '\n<pre>\n')
        for l in e.log:
          self.wfile.write(cgi.escape(l))
        self.wfile.write('</pre>\n')
      except:
        msg = 'Exception encountered handling request'
        logging.exception(msg)
        self.send_response(httplib.INTERNAL_SERVER_ERROR, msg)
        tbhandler()
      else:
        try:
          self.send_response(response.status_code, response.status_message)
          self.wfile.write(response.header_data)
          self.wfile.write('\r\n')

          shutil.copyfileobj(response.body, self.wfile, COPY_BLOCK_SIZE)
        except (IOError, OSError), e:
          if e.errno not in [errno.EPIPE, os_compat.WSAECONNABORTED]:
            raise e
        except socket.error, e:
          logging.error("Socket exception: %s" % str(e))
          self.server.stop_serving_forever()

    def log_error(self, format, *args):
      """Redirect error messages through the logging module."""
      logging.error(format, *args)

    def log_message(self, format, *args):
      """Redirect log messages through the logging module."""


      if hasattr(self, 'path'):
        logging.debug(format, *args)
      else:
        logging.info(format, *args)


    def log_request(self, code='-', size='-'):
      """Indicate that this request has completed."""
      BaseHTTPServer.BaseHTTPRequestHandler.log_request(self, code, size)
      if code == '-':
        code = 0
      if size == '-':
        size = 0

      logservice.logs_buffer().flush()

      self._log_record_writer.write(self.command, self.path, code, size,
                                    self.request_version)

  return DevAppServerRequestHandler
dataset/ETHPy150Open AppScale/appscale/AppServer/google/appengine/tools/dev_appserver.py/CreateRequestHandler