Пример #1
0
  def make_php_cgi_environ(self, environ):
    """Returns a dict of environ for php-cgi based off the wsgi environ."""

    user_environ = self.environ_template.copy()

    environ_utils.propagate_environs(environ, user_environ)
    user_environ['REQUEST_METHOD'] = environ.get('REQUEST_METHOD', 'GET')
    user_environ['PATH_INFO'] = environ['PATH_INFO']
    user_environ['QUERY_STRING'] = environ['QUERY_STRING']

    # Construct the partial URL that PHP expects for REQUEST_URI
    # (http://php.net/manual/en/reserved.variables.server.php) using part of
    # the process described in PEP-333
    # (http://www.python.org/dev/peps/pep-0333/#url-reconstruction).
    user_environ['REQUEST_URI'] = urllib.quote(user_environ['PATH_INFO'])
    if user_environ['QUERY_STRING']:
      user_environ['REQUEST_URI'] += '?' + user_environ['QUERY_STRING']

    # Modify the SCRIPT_FILENAME to specify the setup script that readies the
    # PHP environment. Put the user script in REAL_SCRIPT_FILENAME.
    user_environ['REAL_SCRIPT_FILENAME'] = os.path.normpath(
        os.path.join(self.config.application_root,
                     environ[http_runtime_constants.SCRIPT_HEADER].lstrip('/')))
    user_environ['SCRIPT_FILENAME'] = SETUP_PHP_PATH
    user_environ['REMOTE_REQUEST_ID'] = environ[
        http_runtime_constants.REQUEST_ID_ENVIRON]

    # Pass the APPLICATION_ROOT so we can use it in the setup script. We will
    # remove it from the environment before we execute the user script.
    user_environ['APPLICATION_ROOT'] = self.config.application_root

    if 'CONTENT_TYPE' in environ:
      user_environ['CONTENT_TYPE'] = environ['CONTENT_TYPE']
      user_environ['HTTP_CONTENT_TYPE'] = environ['CONTENT_TYPE']

    if 'CONTENT_LENGTH' in environ:
      user_environ['CONTENT_LENGTH'] = environ['CONTENT_LENGTH']
      user_environ['HTTP_CONTENT_LENGTH'] = environ['CONTENT_LENGTH']

    # On Windows, in order to run a side-by-side assembly the specified env
    # must include a valid SystemRoot.
    if 'SYSTEMROOT' in os.environ:
      user_environ['SYSTEMROOT'] = os.environ['SYSTEMROOT']

    if 'LD_LIBRARY_PATH' in os.environ:
      user_environ['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']

    # On Windows, TMP & TEMP environmental variables are used by GetTempPath
    # http://msdn.microsoft.com/library/windows/desktop/aa364992(v=vs.85).aspx
    if 'TMP' in os.environ:
      user_environ['TMP'] = os.environ['TMP']
    if 'TEMP' in os.environ:
      user_environ['TEMP'] = os.environ['TEMP']

    if self.config.php_config.enable_debugger:
      user_environ['XDEBUG_CONFIG'] = environ.get('XDEBUG_CONFIG', '')

    return user_environ
Пример #2
0
  def make_php_cgi_environ(self, environ):
    """Returns a dict of environ for php-cgi based off the wsgi environ."""

    user_environ = self.environ_template.copy()

    environ_utils.propagate_environs(environ, user_environ)
    user_environ['REQUEST_METHOD'] = environ.get('REQUEST_METHOD', 'GET')
    user_environ['PATH_INFO'] = environ['PATH_INFO']
    user_environ['QUERY_STRING'] = environ['QUERY_STRING']

    # Construct the partial URL that PHP expects for REQUEST_URI
    # (http://php.net/manual/en/reserved.variables.server.php) using part of
    # the process described in PEP-333
    # (http://www.python.org/dev/peps/pep-0333/#url-reconstruction).
    user_environ['REQUEST_URI'] = urllib.quote(user_environ['PATH_INFO'])
    if user_environ['QUERY_STRING']:
      user_environ['REQUEST_URI'] += '?' + user_environ['QUERY_STRING']

    # Modify the SCRIPT_FILENAME to specify the setup script that readies the
    # PHP environment. Put the user script in REAL_SCRIPT_FILENAME.
    user_environ['REAL_SCRIPT_FILENAME'] = os.path.normpath(
        os.path.join(self.config.application_root,
                     environ[http_runtime_constants.SCRIPT_HEADER].lstrip('/')))
    user_environ['SCRIPT_FILENAME'] = SETUP_PHP_PATH
    user_environ['REMOTE_REQUEST_ID'] = environ[
        http_runtime_constants.REQUEST_ID_ENVIRON]

    # Pass the APPLICATION_ROOT so we can use it in the setup script. We will
    # remove it from the environment before we execute the user script.
    user_environ['APPLICATION_ROOT'] = self.config.application_root

    if 'CONTENT_TYPE' in environ:
      user_environ['CONTENT_TYPE'] = environ['CONTENT_TYPE']
      user_environ['HTTP_CONTENT_TYPE'] = environ['CONTENT_TYPE']

    if 'CONTENT_LENGTH' in environ:
      user_environ['CONTENT_LENGTH'] = environ['CONTENT_LENGTH']
      user_environ['HTTP_CONTENT_LENGTH'] = environ['CONTENT_LENGTH']

    # On Windows, in order to run a side-by-side assembly the specified env
    # must include a valid SystemRoot.
    if 'SYSTEMROOT' in os.environ:
      user_environ['SYSTEMROOT'] = os.environ['SYSTEMROOT']

    # On Windows, TMP & TEMP environmental variables are used by GetTempPath
    # http://msdn.microsoft.com/library/windows/desktop/aa364992(v=vs.85).aspx
    if 'TMP' in os.environ:
      user_environ['TMP'] = os.environ['TMP']
    if 'TEMP' in os.environ:
      user_environ['TEMP'] = os.environ['TEMP']

    if self.config.php_config.enable_debugger:
      user_environ['XDEBUG_CONFIG'] = environ.get('XDEBUG_CONFIG', '')

    return user_environ
Пример #3
0
  def test_propagate_environs(self):
    src = {
        'LALA': 'will not propagate',
        'HTTP_LALA': 'will propagate',
        'HTTP_X_APPENGINE_USER_ID': '12345',
        'HTTP_X_APPENGINE_DEV_MYENV': 'will not propagate either'
    }

    dst = {}
    environ_utils.propagate_environs(src, dst)
    self.assertEqual(dst, {'HTTP_LALA': 'will propagate',
                           'USER_ID': '12345'})
Пример #4
0
    def test_propagate_environs(self):
        src = {
            'LALA': 'will not propagate',
            'HTTP_LALA': 'will propagate',
            'HTTP_X_APPENGINE_USER_ID': '12345',
            'HTTP_X_APPENGINE_DEV_MYENV': 'will not propagate either'
        }

        dst = {}
        environ_utils.propagate_environs(src, dst)
        self.assertEqual(dst, {
            'HTTP_LALA': 'will propagate',
            'USER_ID': '12345'
        })
Пример #5
0
    def get_user_environ(self, environ):
        """Returns a dict containing the environ to pass to the user's application.

    Args:
      environ: A dict containing the request WSGI environ.

    Returns:
      A dict containing the environ representing an HTTP request.
    """
        user_environ = self.environ_template.copy()
        environ_utils.propagate_environs(environ, user_environ)
        user_environ['REQUEST_METHOD'] = environ.get('REQUEST_METHOD', 'GET')
        content_type = environ.get('CONTENT_TYPE')
        if content_type:
            user_environ['HTTP_CONTENT_TYPE'] = content_type
        content_length = environ.get('CONTENT_LENGTH')
        if content_length:
            user_environ['HTTP_CONTENT_LENGTH'] = content_length
        return user_environ
Пример #6
0
  def get_user_environ(self, environ):
    """Returns a dict containing the environ to pass to the user's application.

    Args:
      environ: A dict containing the request WSGI environ.

    Returns:
      A dict containing the environ representing an HTTP request.
    """
    user_environ = self.environ_template.copy()
    environ_utils.propagate_environs(environ, user_environ)
    user_environ['REQUEST_METHOD'] = environ.get('REQUEST_METHOD', 'GET')
    content_type = environ.get('CONTENT_TYPE')
    if content_type:
      user_environ['HTTP_CONTENT_TYPE'] = content_type
    content_length = environ.get('CONTENT_LENGTH')
    if content_length:
      user_environ['HTTP_CONTENT_LENGTH'] = content_length
    return user_environ
Пример #7
0
    def __call__(self, environ, start_response):
        """Handles an HTTP request for the runtime using a PHP executable.

    Args:
      environ: An environ dict for the request as defined in PEP-333.
      start_response: A function with semantics defined in PEP-333.

    Returns:
      An iterable over strings containing the body of the HTTP response.
    """
        user_environ = self.environ_template.copy()

        environ_utils.propagate_environs(environ, user_environ)
        user_environ['REQUEST_METHOD'] = environ.get('REQUEST_METHOD', 'GET')
        user_environ['PATH_INFO'] = environ['PATH_INFO']
        user_environ['QUERY_STRING'] = environ['QUERY_STRING']

        # Construct the partial URL that PHP expects for REQUEST_URI
        # (http://php.net/manual/en/reserved.variables.server.php) using part of
        # the process described in PEP-333
        # (http://www.python.org/dev/peps/pep-0333/#url-reconstruction).
        user_environ['REQUEST_URI'] = urllib.quote(user_environ['PATH_INFO'])
        if user_environ['QUERY_STRING']:
            user_environ['REQUEST_URI'] += '?' + user_environ['QUERY_STRING']

        # Modify the SCRIPT_FILENAME to specify the setup script that readies the
        # PHP environment. Put the user script in REAL_SCRIPT_FILENAME.
        user_environ['REAL_SCRIPT_FILENAME'] = os.path.normpath(
            os.path.join(
                self.config.application_root,
                environ[http_runtime_constants.SCRIPT_HEADER].lstrip('/')))
        user_environ['SCRIPT_FILENAME'] = SETUP_PHP_PATH
        user_environ['REMOTE_REQUEST_ID'] = environ[
            http_runtime_constants.REQUEST_ID_ENVIRON]

        # Pass the APPLICATION_ROOT so we can use it in the setup script. We will
        # remove it from the environment before we execute the user script.
        user_environ['APPLICATION_ROOT'] = self.config.application_root

        if 'CONTENT_TYPE' in environ:
            user_environ['CONTENT_TYPE'] = environ['CONTENT_TYPE']
            user_environ['HTTP_CONTENT_TYPE'] = environ['CONTENT_TYPE']

        if 'CONTENT_LENGTH' in environ:
            user_environ['CONTENT_LENGTH'] = environ['CONTENT_LENGTH']
            user_environ['HTTP_CONTENT_LENGTH'] = environ['CONTENT_LENGTH']
            content = environ['wsgi.input'].read(int(
                environ['CONTENT_LENGTH']))
        else:
            content = ''

        # On Windows, in order to run a side-by-side assembly the specified env
        # must include a valid SystemRoot.
        if 'SYSTEMROOT' in os.environ:
            user_environ['SYSTEMROOT'] = os.environ['SYSTEMROOT']

        # See http://www.php.net/manual/en/ini.core.php#ini.include-path.
        include_paths = [self.config.application_root, SDK_PATH]
        if sys.platform == 'win32':
            # See https://bugs.php.net/bug.php?id=46034 for quoting requirements.
            include_path = 'include_path="%s"' % ';'.join(include_paths)
        else:
            include_path = 'include_path=%s' % ':'.join(include_paths)

        args = [self.config.php_config.php_executable_path, '-d', include_path]

        # Load php.ini from application's root.
        args.extend(['-c', self.config.application_root])

        if self.config.php_config.enable_debugger:
            args.extend(['-d', 'xdebug.remote_enable="1"'])
            user_environ['XDEBUG_CONFIG'] = os.environ.get('XDEBUG_CONFIG', '')

        request_type = environ.pop(http_runtime_constants.REQUEST_TYPE_HEADER,
                                   None)
        if request_type == 'interactive':
            args.extend(['-d', 'html_errors="0"'])
            user_environ[
                http_runtime_constants.REQUEST_TYPE_HEADER] = request_type

        try:
            p = safe_subprocess.start_process(args,
                                              input_string=content,
                                              env=user_environ,
                                              cwd=self.config.application_root,
                                              stdout=subprocess.PIPE,
                                              stderr=subprocess.PIPE)
            stdout, stderr = p.communicate()
        except Exception as e:
            logging.exception('Failure to start PHP with: %s', args)
            start_response('500 Internal Server Error',
                           [(http_runtime_constants.ERROR_CODE_HEADER, '1')])
            return [
                'Failure to start the PHP subprocess with %r:\n%s' % (args, e)
            ]

        if p.returncode:
            if request_type == 'interactive':
                start_response('200 OK', [('Content-Type', 'text/plain')])
                message = httplib.HTTPMessage(cStringIO.StringIO(stdout))
                return [message.fp.read()]
            else:
                logging.error('php failure (%r) with:\nstdout:\n%sstderr:\n%s',
                              p.returncode, stdout, stderr)
                start_response(
                    '500 Internal Server Error',
                    [(http_runtime_constants.ERROR_CODE_HEADER, '1')])
                message = httplib.HTTPMessage(cStringIO.StringIO(stdout))
                return [message.fp.read()]

        message = httplib.HTTPMessage(cStringIO.StringIO(stdout))

        if 'Status' in message:
            status = message['Status']
            del message['Status']
        else:
            status = '200 OK'

        # Ensures that we avoid merging repeat headers into a single header,
        # allowing use of multiple Set-Cookie headers.
        headers = []
        for name in message:
            for value in message.getheaders(name):
                headers.append((name, value))

        start_response(status, headers)
        return [message.fp.read()]
Пример #8
0
  def __call__(self, environ, start_response):
    """Handles an HTTP request for the runtime using a PHP executable.

    Args:
      environ: An environ dict for the request as defined in PEP-333.
      start_response: A function with semantics defined in PEP-333.

    Returns:
      An iterable over strings containing the body of the HTTP response.
    """
    user_environ = self.environ_template.copy()

    environ_utils.propagate_environs(environ, user_environ)
    user_environ['REQUEST_METHOD'] = environ.get('REQUEST_METHOD', 'GET')
    user_environ['PATH_INFO'] = environ['PATH_INFO']
    user_environ['QUERY_STRING'] = environ['QUERY_STRING']

    # Construct the partial URL that PHP expects for REQUEST_URI
    # (http://php.net/manual/en/reserved.variables.server.php) using part of
    # the process described in PEP-333
    # (http://www.python.org/dev/peps/pep-0333/#url-reconstruction).
    user_environ['REQUEST_URI'] = urllib.quote(user_environ['PATH_INFO'])
    if user_environ['QUERY_STRING']:
      user_environ['REQUEST_URI'] += '?' + user_environ['QUERY_STRING']

    # Modify the SCRIPT_FILENAME to specify the setup script that readies the
    # PHP environment. Put the user script in REAL_SCRIPT_FILENAME.
    user_environ['REAL_SCRIPT_FILENAME'] = os.path.normpath(
        os.path.join(self.config.application_root,
                     environ[http_runtime_constants.SCRIPT_HEADER]))
    user_environ['SCRIPT_FILENAME'] = SETUP_PHP_PATH
    user_environ['REMOTE_REQUEST_ID'] = environ[
        http_runtime_constants.REQUEST_ID_ENVIRON]

    # Pass the APPLICATION_ROOT so we can use it in the setup script. We will
    # remove it from the environment before we execute the user script.
    user_environ['APPLICATION_ROOT'] = self.config.application_root

    if 'CONTENT_TYPE' in environ:
      user_environ['CONTENT_TYPE'] = environ['CONTENT_TYPE']
      user_environ['HTTP_CONTENT_TYPE'] = environ['CONTENT_TYPE']

    if 'CONTENT_LENGTH' in environ:
      user_environ['CONTENT_LENGTH'] = environ['CONTENT_LENGTH']
      user_environ['HTTP_CONTENT_LENGTH'] = environ['CONTENT_LENGTH']
      content = environ['wsgi.input'].read(int(environ['CONTENT_LENGTH']))
    else:
      content = ''

    # On Windows, in order to run a side-by-side assembly the specified env
    # must include a valid SystemRoot.
    if 'SYSTEMROOT' in os.environ:
      user_environ['SYSTEMROOT'] = os.environ['SYSTEMROOT']

    # See http://www.php.net/manual/en/ini.core.php#ini.include-path.
    include_paths = [self.config.application_root, SDK_PATH]
    if sys.platform == 'win32':
      # See https://bugs.php.net/bug.php?id=46034 for quoting requirements.
      include_path = 'include_path="%s"' % ';'.join(include_paths)
    else:
      include_path = 'include_path=%s' % ':'.join(include_paths)

    args = [self.config.php_config.php_executable_path, '-d', include_path]

    if self.config.php_config.enable_debugger:
      args.extend(['-d', 'xdebug.remote_enable="1"'])
      user_environ['XDEBUG_CONFIG'] = os.environ.get('XDEBUG_CONFIG', '')

    request_type = environ.pop(http_runtime_constants.REQUEST_TYPE_HEADER, None)
    if request_type == 'interactive':
      args.extend(['-d', 'html_errors="0"'])
      user_environ[http_runtime_constants.REQUEST_TYPE_HEADER] = request_type

    try:
      p = safe_subprocess.start_process(args,
                                        input_string=content,
                                        env=user_environ,
                                        cwd=self.config.application_root,
                                        stdout=subprocess.PIPE,
                                        stderr=subprocess.PIPE)
      stdout, stderr = p.communicate()
    except Exception as e:
      logging.exception('Failure to start PHP with: %s', args)
      start_response('500 Internal Server Error',
                     [(http_runtime_constants.ERROR_CODE_HEADER, '1')])
      return ['Failure to start the PHP subprocess with %r:\n%s' % (args, e)]

    if p.returncode:
      if request_type == 'interactive':
        start_response('200 OK', [('Content-Type', 'text/plain')])
        message = httplib.HTTPMessage(cStringIO.StringIO(stdout))
        return [message.fp.read()]
      else:
        logging.error('php failure (%r) with:\nstdout:\n%sstderr:\n%s',
                      p.returncode, stdout, stderr)
        start_response('500 Internal Server Error',
                       [(http_runtime_constants.ERROR_CODE_HEADER, '1')])
        message = httplib.HTTPMessage(cStringIO.StringIO(stdout))
        return [message.fp.read()]

    message = httplib.HTTPMessage(cStringIO.StringIO(stdout))

    if 'Status' in message:
      status = message['Status']
      del message['Status']
    else:
      status = '200 OK'

    # Ensures that we avoid merging repeat headers into a single header,
    # allowing use of multiple Set-Cookie headers.
    headers = []
    for name in message:
      for value in message.getheaders(name):
        headers.append((name, value))

    start_response(status, headers)
    return [message.fp.read()]