authomatic/core.py
def backend(self, adapter):
        """
        Converts a *request handler* to a JSON backend which you can use with
        :ref:`authomatic.js <js>`.

        Just call it inside a *request handler* like this:

        ::

            class JSONHandler(webapp2.RequestHandler):
                def get(self):
                    authomatic.backend(Webapp2Adapter(self))

        :param adapter:
            The only argument is an :doc:`adapter <adapters>`.

        The *request handler* will now accept these request parameters:

        :param str type:
            Type of the request. Either ``auto``, ``fetch`` or ``elements``.
            Default is ``auto``.

        :param str credentials:
            Serialized :class:`.Credentials`.

        :param str url:
            URL of the **protected resource** request.

        :param str method:
            HTTP method of the **protected resource** request.

        :param str body:
            HTTP body of the **protected resource** request.

        :param JSON params:
            HTTP params of the **protected resource** request as a JSON object.

        :param JSON headers:
            HTTP headers of the **protected resource** request as a
            JSON object.

        :param JSON json:
            You can pass all of the aforementioned params except ``type``
            in a JSON object.

            .. code-block:: javascript

                {
                    "credentials": "######",
                    "url": "https://example.com",
                    "method": "POST",
                    "params": {"foo": "bar"},
                    "headers": {"baz": "bing"},
                    "body": "the body of the request"
                }

        Depending on the ``type`` param, the handler will either write
        a JSON object with *request elements* to the response,
        and add an ``Authomatic-Response-To: elements`` response header, ...

        .. code-block:: javascript

            {
                "url": "https://example.com/api",
                "method": "POST",
                "params": {
                    "access_token": "###",
                    "foo": "bar"
                },
                "headers": {
                    "baz": "bing",
                    "Authorization": "Bearer ###"
                }
            }

        ... or make a fetch to the **protected resource** and forward
        it's response content, status and headers with an additional
        ``Authomatic-Response-To: fetch`` header to the response.

        .. warning::

            The backend will not work if you write anything to the
            response in the handler!

        """

        AUTHOMATIC_HEADER = 'Authomatic-Response-To'

        # Collect request params
        request_type = adapter.params.get('type', 'auto')
        json_input = adapter.params.get('json')
        credentials = adapter.params.get('credentials')
        url = adapter.params.get('url')
        method = adapter.params.get('method', 'GET')
        body = adapter.params.get('body', '')

        params = adapter.params.get('params')
        params = json.loads(params) if params else {}

        headers = adapter.params.get('headers')
        headers = json.loads(headers) if headers else {}

        ProviderClass = Credentials.deserialize(
            self.config, credentials).provider_class

        if request_type == 'auto':
            # If there is a "callback" param, it's a JSONP request.
            jsonp = params.get('callback')

            # JSONP is possible only with GET method.
            if ProviderClass.supports_jsonp and method is 'GET':
                request_type = 'elements'
            else:
                # Remove the JSONP callback
                if jsonp:
                    params.pop('callback')
                request_type = 'fetch'

        if request_type == 'fetch':
            # Access protected resource
            response = self.access(
                credentials, url, params, method, headers, body)
            result = response.content

            # Forward status
            adapter.status = str(response.status) + ' ' + str(response.reason)

            # Forward headers
            for k, v in response.getheaders():
                logging.info('    {0}: {1}'.format(k, v))
                adapter.set_header(k, v)

        elif request_type == 'elements':
            # Create request elements
            if json_input:
                result = self.request_elements(
                    json_input=json_input, return_json=True)
            else:
                result = self.request_elements(credentials=credentials,
                                               url=url,
                                               method=method,
                                               params=params,
                                               headers=headers,
                                               body=body,
                                               return_json=True)

            adapter.set_header('Content-Type', 'application/json')
        else:
            result = '{"error": "Bad Request!"}'

        # Add the authomatic header
        adapter.set_header(AUTHOMATIC_HEADER, request_type)

        # Write result to response
        adapter.write(result)
def backend(self, adapter):
        """
        Converts a *request handler* to a JSON backend which you can use with
        :ref:`authomatic.js <js>`.

        Just call it inside a *request handler* like this:

        ::

            class JSONHandler(webapp2.RequestHandler):
                def get(self):
                    authomatic.backend(Webapp2Adapter(self))

        :param adapter:
            The only argument is an :doc:`adapter <adapters>`.

        The *request handler* will now accept these request parameters:

        :param str type:
            Type of the request. Either ``auto``, ``fetch`` or ``elements``.
            Default is ``auto``.

        :param str credentials:
            Serialized :class:`.Credentials`.

        :param str url:
            URL of the **protected resource** request.

        :param str method:
            HTTP method of the **protected resource** request.

        :param str body:
            HTTP body of the **protected resource** request.

        :param JSON params:
            HTTP params of the **protected resource** request as a JSON object.

        :param JSON headers:
            HTTP headers of the **protected resource** request as a
            JSON object.

        :param JSON json:
            You can pass all of the aforementioned params except ``type``
            in a JSON object.

            .. code-block:: javascript

                {
                    "credentials": "######",
                    "url": "https://example.com",
                    "method": "POST",
                    "params": {"foo": "bar"},
                    "headers": {"baz": "bing"},
                    "body": "the body of the request"
                }

        Depending on the ``type`` param, the handler will either write
        a JSON object with *request elements* to the response,
        and add an ``Authomatic-Response-To: elements`` response header, ...

        .. code-block:: javascript

            {
                "url": "https://example.com/api",
                "method": "POST",
                "params": {
                    "access_token": "###",
                    "foo": "bar"
                },
                "headers": {
                    "baz": "bing",
                    "Authorization": "Bearer ###"
                }
            }

        ... or make a fetch to the **protected resource** and forward
        it's response content, status and headers with an additional
        ``Authomatic-Response-To: fetch`` header to the response.

        .. warning::

            The backend will not work if you write anything to the
            response in the handler!

        """

        AUTHOMATIC_HEADER = 'Authomatic-Response-To'

        # Collect request params
        request_type = adapter.params.get('type', 'auto')
        json_input = adapter.params.get('json')
        credentials = adapter.params.get('credentials')
        url = adapter.params.get('url')
        method = adapter.params.get('method', 'GET')
        body = adapter.params.get('body', '')

        params = adapter.params.get('params')
        params = json.loads(params) if params else {}

        headers = adapter.params.get('headers')
        headers = json.loads(headers) if headers else {}

        ProviderClass = Credentials.deserialize(
            self.config, credentials).provider_class

        if request_type == 'auto':
            # If there is a "callback" param, it's a JSONP request.
            jsonp = params.get('callback')

            # JSONP is possible only with GET method.
            if ProviderClass.supports_jsonp and method is 'GET':
                request_type = 'elements'
            else:
                # Remove the JSONP callback
                if jsonp:
                    params.pop('callback')
                request_type = 'fetch'

        if request_type == 'fetch':
            # Access protected resource
            response = self.access(
                credentials, url, params, method, headers, body)
            result = response.content

            # Forward status
            adapter.status = str(response.status) + ' ' + str(response.reason)

            # Forward headers
            for k, v in response.getheaders():
                logging.info('    {0}: {1}'.format(k, v))
                adapter.set_header(k, v)

        elif request_type == 'elements':
            # Create request elements
            if json_input:
                result = self.request_elements(
                    json_input=json_input, return_json=True)
            else:
                result = self.request_elements(credentials=credentials,
                                               url=url,
                                               method=method,
                                               params=params,
                                               headers=headers,
                                               body=body,
                                               return_json=True)

            adapter.set_header('Content-Type', 'application/json')
        else:
            result = '{"error": "Bad Request!"}'

        # Add the authomatic header
        adapter.set_header(AUTHOMATIC_HEADER, request_type)

        # Write result to response
        adapter.write(result)
Converts a *request handler* to a JSON backend which you can use with
        :ref:`authomatic.js <js>`.

        Just call it inside a *request handler* like this:

        ::

            class JSONHandler(webapp2.RequestHandler):
                def get(self):
                    authomatic.backend(Webapp2Adapter(self))

        :param adapter:
            The only argument is an :doc:`adapter <adapters>`.

        The *request handler* will now accept these request parameters:

        :param str type:
            Type of the request. Either ``auto``, ``fetch`` or ``elements``.
            Default is ``auto``.

        :param str credentials:
            Serialized :class:`.Credentials`.

        :param str url:
            URL of the **protected resource** request.

        :param str method:
            HTTP method of the **protected resource** request.

        :param str body:
            HTTP body of the **protected resource** request.

        :param JSON params:
            HTTP params of the **protected resource** request as a JSON object.

        :param JSON headers:
            HTTP headers of the **protected resource** request as a
            JSON object.

        :param JSON json:
            You can pass all of the aforementioned params except ``type``
            in a JSON object.

            .. code-block:: javascript

                {
                    "credentials": "######",
                    "url": "https://example.com",
                    "method": "POST",
                    "params": {"foo": "bar"},
                    "headers": {"baz": "bing"},
                    "body": "the body of the request"
                }

        Depending on the ``type`` param, the handler will either write
        a JSON object with *request elements* to the response,
        and add an ``Authomatic-Response-To: elements`` response header, ...

        .. code-block:: javascript

            {
                "url": "https://example.com/api",
                "method": "POST",
                "params": {
                    "access_token": "###",
                    "foo": "bar"
                },
                "headers": {
                    "baz": "bing",
                    "Authorization": "Bearer ###"
                }
            }

        ... or make a fetch to the **protected resource** and forward
        it's response content, status and headers with an additional
        ``Authomatic-Response-To: fetch`` header to the response.

        .. warning::

            The backend will not work if you write anything to the
            response in the handler!