# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
"""
Middleware to make internal requests and forward requests internally.

When applied, several keys are added to the environment that will allow
you to trigger recursive redirects and forwards.

  paste.recursive.include:
      When you call
      ``environ['paste.recursive.include'](new_path_info)`` a response
      will be returned.  The response has a ``body`` attribute, a
      ``status`` attribute, and a ``headers`` attribute.

  paste.recursive.script_name:
      The ``SCRIPT_NAME`` at the point that recursive lives.  Only
      paths underneath this path can be redirected to.

  paste.recursive.old_path_info:
      A list of previous ``PATH_INFO`` values from previous redirects.

Raise ``ForwardRequestException(new_path_info)`` to do a forward
(aborting the current request).
"""

import six
import warnings
from six.moves import cStringIO as StringIO

__all__ = ['RecursiveMiddleware']
__pudge_all__ =  ['RecursiveMiddleware', 'ForwardRequestException']

class RecursionLoop(AssertionError):
    # Subclasses AssertionError for legacy reasons
    """Raised when a recursion enters into a loop"""

class CheckForRecursionMiddleware(object):
    def __init__(self, app, env):
        self.app = app
        self.env = env

    def __call__(self, environ, start_response):
        path_info = environ.get('PATH_INFO','')
        if path_info in self.env.get(
            'paste.recursive.old_path_info', []):
            raise RecursionLoop(
                "Forwarding loop detected; %r visited twice (internal "
                "redirect path: %s)"
                % (path_info, self.env['paste.recursive.old_path_info']))
        old_path_info = self.env.setdefault('paste.recursive.old_path_info', [])
        old_path_info.append(self.env.get('PATH_INFO', ''))
        return self.app(environ, start_response)

class RecursiveMiddleware(object):

    """
    A WSGI middleware that allows for recursive and forwarded calls.
    All these calls go to the same 'application', but presumably that
    application acts differently with different URLs.  The forwarded
    URLs must be relative to this container.

    Interface is entirely through the ``paste.recursive.forward`` and
    ``paste.recursive.include`` environmental keys.
    """

    def __init__(self, application, global_conf=None):
        self.application = application

    def __call__(self, environ, start_response):
        environ['paste.recursive.forward'] = Forwarder(
            self.application,
            environ,
            start_response)
        environ['paste.recursive.include'] = Includer(
            self.application,
            environ,
            start_response)
        environ['paste.recursive.include_app_iter'] = IncluderAppIter(
            self.application,
            environ,
            start_response)
        my_script_name = environ.get('SCRIPT_NAME', '')
        environ['paste.recursive.script_name'] = my_script_name
        try:
            return self.application(environ, start_response)
        except ForwardRequestException as e:
            middleware = CheckForRecursionMiddleware(
                e.factory(self), environ)
            return middleware(environ, start_response)

class ForwardRequestException(Exception):
    """
    Used to signal that a request should be forwarded to a different location.

    ``url``
        The URL to forward to starting with a ``/`` and relative to
        ``RecursiveMiddleware``. URL fragments can also contain query strings
        so ``/error?code=404`` would be a valid URL fragment.

    ``environ``
        An altertative WSGI environment dictionary to use for the forwarded
        request. If specified is used *instead* of the ``url_fragment``

    ``factory``
        If specifed ``factory`` is used instead of ``url`` or ``environ``.
        ``factory`` is a callable that takes a WSGI application object
        as the first argument and returns an initialised WSGI middleware
        which can alter the forwarded response.

    Basic usage (must have ``RecursiveMiddleware`` present) :

    .. code-block:: python

        from paste.recursive import ForwardRequestException
        def app(environ, start_response):
            if environ['PATH_INFO'] == '/hello':
                start_response("200 OK", [('Content-type', 'text/plain')])
                return [b'Hello World!']
            elif environ['PATH_INFO'] == '/error':
                start_response("404 Not Found", [('Content-type', 'text/plain')])
                return [b'Page not found']
            else:
                raise ForwardRequestException('/error')

        from paste.recursive import RecursiveMiddleware
        app = RecursiveMiddleware(app)

    If you ran this application and visited ``/hello`` you would get a
    ``Hello World!`` message. If you ran the application and visited
    ``/not_found`` a ``ForwardRequestException`` would be raised and the caught
    by the ``RecursiveMiddleware``. The ``RecursiveMiddleware`` would then
    return the headers and response from the ``/error`` URL but would display
    a ``404 Not found`` status message.

    You could also specify an ``environ`` dictionary instead of a url. Using
    the same example as before:

    .. code-block:: python

        def app(environ, start_response):
            ... same as previous example ...
            else:
                new_environ = environ.copy()
                new_environ['PATH_INFO'] = '/error'
                raise ForwardRequestException(environ=new_environ)

    Finally, if you want complete control over every aspect of the forward you
    can specify a middleware factory. For example to keep the old status code
    but use the headers and resposne body from the forwarded response you might
    do this:

    .. code-block:: python

        from paste.recursive import ForwardRequestException
        from paste.recursive import RecursiveMiddleware
        from paste.errordocument import StatusKeeper

        def app(environ, start_response):
            if environ['PATH_INFO'] == '/hello':
                start_response("200 OK", [('Content-type', 'text/plain')])
                return [b'Hello World!']
            elif environ['PATH_INFO'] == '/error':
                start_response("404 Not Found", [('Content-type', 'text/plain')])
                return [b'Page not found']
            else:
                def factory(app):
                    return StatusKeeper(app, status='404 Not Found', url='/error')
                raise ForwardRequestException(factory=factory)

        app = RecursiveMiddleware(app)
    """

    def __init__(
        self,
        url=None,
        environ={},
        factory=None,
        path_info=None):
        # Check no incompatible options have been chosen
        if factory and url:
            raise TypeError(
                'You cannot specify factory and a url in '
                'ForwardRequestException')
        elif factory and environ:
            raise TypeError(
                'You cannot specify factory and environ in '
                'ForwardRequestException')
        if url and environ:
            raise TypeError(
                'You cannot specify environ and url in '
                'ForwardRequestException')

        # set the path_info or warn about its use.
        if path_info:
            if not url:
                warnings.warn(
                    "ForwardRequestException(path_info=...) has been deprecated; please "
                    "use ForwardRequestException(url=...)",
                    DeprecationWarning, 2)
            else:
                raise TypeError('You cannot use url and path_info in ForwardRequestException')
            self.path_info = path_info

        # If the url can be treated as a path_info do that
        if url and not '?' in str(url):
            self.path_info = url

        # Base middleware
        class ForwardRequestExceptionMiddleware(object):
            def __init__(self, app):
                self.app = app

        # Otherwise construct the appropriate middleware factory
        if hasattr(self, 'path_info'):
            p = self.path_info
            def factory_(app):
                class PathInfoForward(ForwardRequestExceptionMiddleware):
                    def __call__(self, environ, start_response):
                        environ['PATH_INFO'] = p
                        return self.app(environ, start_response)
                return PathInfoForward(app)
            self.factory = factory_
        elif url:
            def factory_(app):
                class URLForward(ForwardRequestExceptionMiddleware):
                    def __call__(self, environ, start_response):
                        environ['PATH_INFO'] = url.split('?')[0]
                        environ['QUERY_STRING'] = url.split('?')[1]
                        return self.app(environ, start_response)
                return URLForward(app)
            self.factory = factory_
        elif environ:
            def factory_(app):
                class EnvironForward(ForwardRequestExceptionMiddleware):
                    def __call__(self, environ_, start_response):
                        return self.app(environ, start_response)
                return EnvironForward(app)
            self.factory = factory_
        else:
            self.factory = factory

class Recursive(object):

    def __init__(self, application, environ, start_response):
        self.application = application
        self.original_environ = environ.copy()
        self.previous_environ = environ
        self.start_response = start_response

    def __call__(self, path, extra_environ=None):
        """
        `extra_environ` is an optional dictionary that is also added
        to the forwarded request.  E.g., ``{'HTTP_HOST': 'new.host'}``
        could be used to forward to a different virtual host.
        """
        environ = self.original_environ.copy()
        if extra_environ:
            environ.update(extra_environ)
        environ['paste.recursive.previous_environ'] = self.previous_environ
        base_path = self.original_environ.get('SCRIPT_NAME')
        if path.startswith('/'):
            assert path.startswith(base_path), (
                "You can only forward requests to resources under the "
                "path %r (not %r)" % (base_path, path))
            path = path[len(base_path)+1:]
        assert not path.startswith('/')
        path_info = '/' + path
        environ['PATH_INFO'] = path_info
        environ['REQUEST_METHOD'] = 'GET'
        environ['CONTENT_LENGTH'] = '0'
        environ['CONTENT_TYPE'] = ''
        environ['wsgi.input'] = StringIO('')
        return self.activate(environ)

    def activate(self, environ):
        raise NotImplementedError

    def __repr__(self):
        return '<%s.%s from %s>' % (
            self.__class__.__module__,
            self.__class__.__name__,
            self.original_environ.get('SCRIPT_NAME') or '/')

class Forwarder(Recursive):

    """
    The forwarder will try to restart the request, except with
    the new `path` (replacing ``PATH_INFO`` in the request).

    It must not be called after and headers have been returned.
    It returns an iterator that must be returned back up the call
    stack, so it must be used like:

    .. code-block:: python

        return environ['paste.recursive.forward'](path)

    Meaningful transformations cannot be done, since headers are
    sent directly to the server and cannot be inspected or
    rewritten.
    """

    def activate(self, environ):
        warnings.warn(
            "recursive.Forwarder has been deprecated; please use "
            "ForwardRequestException",
            DeprecationWarning, 2)
        return self.application(environ, self.start_response)


class Includer(Recursive):

    """
    Starts another request with the given path and adding or
    overwriting any values in the `extra_environ` dictionary.
    Returns an IncludeResponse object.
    """

    def activate(self, environ):
        response = IncludedResponse()
        def start_response(status, headers, exc_info=None):
            if exc_info:
                six.reraise(exc_info[0], exc_info[1], exc_info[2])
            response.status = status
            response.headers = headers
            return response.write
        app_iter = self.application(environ, start_response)
        try:
            for s in app_iter:
                response.write(s)
        finally:
            if hasattr(app_iter, 'close'):
                app_iter.close()
        response.close()
        return response

class IncludedResponse(object):

    def __init__(self):
        self.headers = None
        self.status = None
        self.output = StringIO()
        self.str = None

    def close(self):
        self.str = self.output.getvalue()
        self.output.close()
        self.output = None

    def write(self, s):
        assert self.output is not None, (
            "This response has already been closed and no further data "
            "can be written.")
        self.output.write(s)

    def __str__(self):
        return self.body

    def body__get(self):
        if self.str is None:
            return self.output.getvalue()
        else:
            return self.str
    body = property(body__get)


class IncluderAppIter(Recursive):
    """
    Like Includer, but just stores the app_iter response
    (be sure to call close on the response!)
    """

    def activate(self, environ):
        response = IncludedAppIterResponse()
        def start_response(status, headers, exc_info=None):
            if exc_info:
                six.reraise(exc_info[0], exc_info[1], exc_info[2])
            response.status = status
            response.headers = headers
            return response.write
        app_iter = self.application(environ, start_response)
        response.app_iter = app_iter
        return response

class IncludedAppIterResponse(object):

    def __init__(self):
        self.status = None
        self.headers = None
        self.accumulated = []
        self.app_iter = None
        self._closed = False

    def close(self):
        assert not self._closed, (
            "Tried to close twice")
        if hasattr(self.app_iter, 'close'):
            self.app_iter.close()

    def write(self, s):
        self.accumulated.append

def make_recursive_middleware(app, global_conf):
    return RecursiveMiddleware(app)

make_recursive_middleware.__doc__ = __doc__
