# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Module for Google Connection and Authentication classes.

Information about setting up your Google OAUTH2 credentials:

For libcloud, there are two basic methods for authenticating to Google using
OAUTH2: Service Accounts and Client IDs for Installed Applications.

Both are initially set up from the Cloud Console Console -
https://cloud.google.com/console

Setting up Service Account authentication (note that you need the PyCrypto
package installed to use this):

- Go to the Console
- Go to your project and then to "APIs & auth" on the left
- Click on "Credentials"
- Click on "Create New Client ID..."
- Select "Service account" and click on "Create Client ID"
- Download the Private Key (should happen automatically).  The key you download
  is in JSON format.
- Move the .json file to a safe location.
- Optionally, you may choose to Generate a PKCS12 key from the Console.
  It needs to be converted to the PEM format.  Please note, the PKCS12 format
  is deprecated and may be removed in a future release.
  - Convert the key using OpenSSL (the default password is 'notasecret').
  - Move the .pem file to a safe location.
- To Authenticate, you will need to pass the Service Account's "Email
  address" in as the user_id and the path to the .pem file as the key.

Setting up Installed Application authentication:

- Go to the Console
- Go to your project and then to "APIs & auth" on the left
- Click on "Credentials"
- Select "Installed application" and "Other" then click on
  "Create Client ID"
- To Authenticate, pass in the "Client ID" as the user_id and the "Client
  secret" as the key
- The first time that you do this, the libcloud will give you a URL to
  visit.  Copy and paste the URL into a browser.
- When you go to the URL it will ask you to log in (if you aren't already)
  and ask you if you want to allow the project access to your account.
- Click on Accept and you will be given a code.
- Paste that code at the prompt given to you by the Google libcloud
  connection.
- At that point, a token & refresh token will be stored in your home
  directory and will be used for authentication.

Please remember to secure your keys and access tokens.
"""

from __future__ import with_statement

try:
    import simplejson as json
except ImportError:
    import json

import base64
import errno
import time
import datetime
import os
import socket
import sys

from libcloud.utils.connection import get_response_object
from libcloud.utils.py3 import b, httplib, urlencode, urlparse, PY3
from libcloud.common.base import (ConnectionUserAndKey, JsonResponse,
                                  PollingConnection)
from libcloud.common.types import (ProviderError,
                                   LibcloudError)

try:
    from Crypto.Hash import SHA256
    from Crypto.PublicKey import RSA
    from Crypto.Signature import PKCS1_v1_5
    import Crypto.Random
    Crypto.Random.atfork()
except ImportError:
    # The pycrypto library is unavailable
    SHA256 = None
    RSA = None
    PKCS1_v1_5 = None

UTC_TIMESTAMP_FORMAT = '%Y-%m-%dT%H:%M:%SZ'


def _utcnow():
    """
    Mocked in libcloud.test.common.google.GoogleTestCase.
    """
    return datetime.datetime.utcnow()


def _utc_timestamp(datetime_obj):
    return datetime_obj.strftime(UTC_TIMESTAMP_FORMAT)


def _from_utc_timestamp(timestamp):
    return datetime.datetime.strptime(timestamp, UTC_TIMESTAMP_FORMAT)


def _get_gce_metadata(path=''):
    try:
        url = 'http://metadata/computeMetadata/v1/' + path.lstrip('/')
        headers = {'Metadata-Flavor': 'Google'}
        response = get_response_object(url, headers=headers)
        return response.status, '', response.body
    except Exception as e:
        return -1, str(e), None


class GoogleAuthError(LibcloudError):
    """Generic Error class for various authentication errors."""
    def __init__(self, value):
        self.value = value

    def __repr__(self):
        return repr(self.value)


class GoogleBaseError(ProviderError):
    def __init__(self, value, http_code, code, driver=None):
        self.code = code
        super(GoogleBaseError, self).__init__(value, http_code, driver)


class InvalidRequestError(GoogleBaseError):
    pass


class JsonParseError(GoogleBaseError):
    pass


class ResourceNotFoundError(GoogleBaseError):
    def __init__(self, value, http_code, code, driver=None):
        self.code = code
        if isinstance(value, dict) and 'message' in value and \
                value['message'].count('/') == 1 and \
                value['message'].count('projects/') == 1:
            value['message'] = value['message'] + ". A missing project " \
                "error may be an authentication issue. " \
                "Please  ensure your auth credentials match " \
                "your project. "
        super(ResourceNotFoundError, self).__init__(value, http_code, driver)


class QuotaExceededError(GoogleBaseError):
    pass


class ResourceExistsError(GoogleBaseError):
    pass


class ResourceInUseError(GoogleBaseError):
    pass


class GoogleResponse(JsonResponse):
    """
    Google Base Response class.
    """
    def success(self):
        """
        Determine if the request was successful.

        For the Google response class, tag all responses as successful and
        raise appropriate Exceptions from parse_body.

        :return: C{True}
        """
        return True

    def _get_error(self, body):
        """
        Get the error code and message from a JSON response.

        Return just the first error if there are multiple errors.

        :param  body: The body of the JSON response dictionary
        :type   body: ``dict``

        :return:  Tuple containing error code and message
        :rtype:   ``tuple`` of ``str`` or ``int``
        """
        if 'errors' in body['error']:
            err = body['error']['errors'][0]
        else:
            err = body['error']

        if 'code' in err:
            code = err.get('code')
            message = err.get('message')
        else:
            code = err.get('reason', None)
            message = body.get('error_description', err)

        return (code, message)

    def parse_body(self):
        """
        Parse the JSON response body, or raise exceptions as appropriate.

        :return:  JSON dictionary
        :rtype:   ``dict``
        """
        if len(self.body) == 0 and not self.parse_zero_length_body:
            return self.body

        json_error = False
        try:
            body = json.loads(self.body)
        except:
            # If there is both a JSON parsing error and an unsuccessful http
            # response (like a 404), we want to raise the http error and not
            # the JSON one, so don't raise JsonParseError here.
            body = self.body
            json_error = True

        valid_http_codes = [
            httplib.OK,
            httplib.CREATED,
            httplib.ACCEPTED,
            httplib.CONFLICT,
        ]
        if self.status in valid_http_codes:
            if json_error:
                raise JsonParseError(body, self.status, None)
            elif 'error' in body:
                (code, message) = self._get_error(body)
                if code == 'QUOTA_EXCEEDED':
                    raise QuotaExceededError(message, self.status, code)
                elif code == 'RESOURCE_ALREADY_EXISTS':
                    raise ResourceExistsError(message, self.status, code)
                elif code == 'alreadyExists':
                    raise ResourceExistsError(message, self.status, code)
                elif code.startswith('RESOURCE_IN_USE'):
                    raise ResourceInUseError(message, self.status, code)
                else:
                    raise GoogleBaseError(message, self.status, code)
            else:
                return body

        elif self.status == httplib.NOT_FOUND:
            if (not json_error) and ('error' in body):
                (code, message) = self._get_error(body)
            else:
                message = body
                code = None
            raise ResourceNotFoundError(message, self.status, code)

        elif self.status == httplib.BAD_REQUEST:
            if (not json_error) and ('error' in body):
                (code, message) = self._get_error(body)
            else:
                message = body
                code = None
            raise InvalidRequestError(message, self.status, code)

        else:
            if (not json_error) and ('error' in body):
                (code, message) = self._get_error(body)
            else:
                message = body
                code = None
            raise GoogleBaseError(message, self.status, code)


class GoogleBaseDriver(object):
    name = "Google API"


class GoogleBaseAuthConnection(ConnectionUserAndKey):
    """
    Base class for Google Authentication.  Should be subclassed for specific
    types of authentication.
    """
    driver = GoogleBaseDriver
    responseCls = GoogleResponse
    name = 'Google Auth'
    host = 'accounts.google.com'
    auth_path = '/o/oauth2/auth'

    def __init__(self, user_id, key=None, scopes=None,
                 redirect_uri='urn:ietf:wg:oauth:2.0:oob',
                 login_hint=None, **kwargs):
        """
        :param  user_id: The email address (for service accounts) or Client ID
                         (for installed apps) to be used for authentication.
        :type   user_id: ``str``

        :param  key: The RSA Key (for service accounts) or file path containing
                     key or Client Secret (for installed apps) to be used for
                     authentication.
        :type   key: ``str``

        :param  scopes: A list of urls defining the scope of authentication
                       to grant.
        :type   scopes: ``list``

        :keyword  redirect_uri: The Redirect URI for the authentication
                                request.  See Google OAUTH2 documentation for
                                more info.
        :type     redirect_uri: ``str``

        :keyword  login_hint: Login hint for authentication request.  Useful
                              for Installed Application authentication.
        :type     login_hint: ``str``
        """
        scopes = scopes or []

        self.scopes = " ".join(scopes)
        self.redirect_uri = redirect_uri
        self.login_hint = login_hint

        super(GoogleBaseAuthConnection, self).__init__(user_id, key, **kwargs)

    def add_default_headers(self, headers):
        headers['Content-Type'] = "application/x-www-form-urlencoded"
        headers['Host'] = self.host
        return headers

    def _token_request(self, request_body):
        """
        Return an updated token from a token request body.

        :param  request_body: A dictionary of values to send in the body of the
                              token request.
        :type   request_body: ``dict``

        :return:  A dictionary with updated token information
        :rtype:   ``dict``
        """
        data = urlencode(request_body)
        try:
            response = self.request('/o/oauth2/token', method='POST',
                                    data=data)
        except AttributeError:
            raise GoogleAuthError('Invalid authorization response, please '
                                  'check your credentials and time drift.')
        token_info = response.object
        if 'expires_in' in token_info:
            expire_time = _utcnow() + datetime.timedelta(
                seconds=token_info['expires_in'])
            token_info['expire_time'] = _utc_timestamp(expire_time)
        return token_info

    def refresh_token(self, token_info):
        """
        Refresh the current token.

        Fetch an updated refresh token from internal metadata service.

        :param  token_info: Dictionary containing token information.
                            (Not used, but here for compatibility)
        :type   token_info: ``dict``

        :return:  A dictionary containing updated token information.
        :rtype:   ``dict``
        """
        # pylint: disable=no-member
        return self.get_new_token()


class GoogleInstalledAppAuthConnection(GoogleBaseAuthConnection):
    """Authentication connection for "Installed Application" authentication."""
    def get_code(self):
        """
        Give the user a URL that they can visit to authenticate and obtain a
        code.  This method will ask for that code that the user can paste in.

        Mocked in libcloud.test.common.google.GoogleTestCase.

        :return:  Code supplied by the user after authenticating
        :rtype:   ``str``
        """
        auth_params = {'response_type': 'code',
                       'client_id': self.user_id,
                       'redirect_uri': self.redirect_uri,
                       'scope': self.scopes,
                       'state': 'Libcloud Request'}
        if self.login_hint:
            auth_params['login_hint'] = self.login_hint

        data = urlencode(auth_params)

        url = 'https://%s%s?%s' % (self.host, self.auth_path, data)
        print('\nPlease Go to the following URL and sign in:')
        print(url)
        if PY3:
            code = input('Enter Code: ')
        else:
            code = raw_input('Enter Code: ')
        return code

    def get_new_token(self):
        """
        Get a new token. Generally used when no previous token exists or there
        is no refresh token

        :return:  Dictionary containing token information
        :rtype:   ``dict``
        """
        # Ask the user for a code
        code = self.get_code()

        token_request = {'code': code,
                         'client_id': self.user_id,
                         'client_secret': self.key,
                         'redirect_uri': self.redirect_uri,
                         'grant_type': 'authorization_code'}

        return self._token_request(token_request)

    def refresh_token(self, token_info):
        """
        Use the refresh token supplied in the token info to get a new token.

        :param  token_info: Dictionary containing current token information
        :type   token_info: ``dict``

        :return:  A dictionary containing updated token information.
        :rtype:   ``dict``
        """
        if 'refresh_token' not in token_info:
            return self.get_new_token()
        refresh_request = {'refresh_token': token_info['refresh_token'],
                           'client_id': self.user_id,
                           'client_secret': self.key,
                           'grant_type': 'refresh_token'}

        new_token = self._token_request(refresh_request)
        if 'refresh_token' not in new_token:
            new_token['refresh_token'] = token_info['refresh_token']
        return new_token


class GoogleServiceAcctAuthConnection(GoogleBaseAuthConnection):
    """Authentication class for "Service Account" authentication."""
    def __init__(self, user_id, key, *args, **kwargs):
        """
        Check to see if PyCrypto is available, and convert key file path into a
        key string if the key is in a file.

        :param  user_id: Email address to be used for Service Account
                authentication.
        :type   user_id: ``str``

        :param  key: The RSA Key or path to file containing the key.
        :type   key: ``str``
        """
        if SHA256 is None:
            raise GoogleAuthError('PyCrypto library required for '
                                  'Service Account Authentication.')
        # Check to see if 'key' is a file and read the file if it is.
        if key.find("PRIVATE KEY---") == -1:
            # key is a file
            keypath = os.path.expanduser(key)
            is_file_path = os.path.exists(keypath) and os.path.isfile(keypath)
            if not is_file_path:
                raise ValueError("Missing (or not readable) key "
                                 "file: '%s'" % key)
            with open(keypath, 'r') as f:
                contents = f.read()
            try:
                key = json.loads(contents)
                key = key['private_key']
            except ValueError:
                key = contents

        super(GoogleServiceAcctAuthConnection, self).__init__(
            user_id, key, *args, **kwargs)

    def get_new_token(self):
        """
        Get a new token using the email address and RSA Key.

        :return:  Dictionary containing token information
        :rtype:   ``dict``
        """
        # The header is always the same
        header = {'alg': 'RS256', 'typ': 'JWT'}
        header_enc = base64.urlsafe_b64encode(b(json.dumps(header)))

        # Construct a claim set
        claim_set = {'iss': self.user_id,
                     'scope': self.scopes,
                     'aud': 'https://accounts.google.com/o/oauth2/token',
                     'exp': int(time.time()) + 3600,
                     'iat': int(time.time())}
        claim_set_enc = base64.urlsafe_b64encode(b(json.dumps(claim_set)))

        # The message contains both the header and claim set
        message = b'.'.join((header_enc, claim_set_enc))
        # Then the message is signed using the key supplied
        key = RSA.importKey(self.key)
        hash_func = SHA256.new(message)
        signer = PKCS1_v1_5.new(key)
        signature = base64.urlsafe_b64encode(signer.sign(hash_func))

        # Finally the message and signature are sent to get a token
        jwt = b'.'.join((message, signature))
        request = {'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
                   'assertion': jwt}

        return self._token_request(request)


class GoogleGCEServiceAcctAuthConnection(GoogleBaseAuthConnection):
    """Authentication class for self-authentication when used with a GCE
    instance that supports serviceAccounts.
    """
    def get_new_token(self):
        """
        Get a new token from the internal metadata service.

        :return:  Dictionary containing token information
        :rtype:   ``dict``
        """
        path = '/instance/service-accounts/default/token'
        http_code, http_reason, token_info = _get_gce_metadata(path)
        if http_code == httplib.NOT_FOUND:
            raise ValueError("Service Accounts are not enabled for this "
                             "GCE instance.")
        if http_code != httplib.OK:
            raise ValueError("Internal GCE Authorization failed: "
                             "'%s'" % str(http_reason))
        token_info = json.loads(token_info)
        if 'expires_in' in token_info:
            expire_time = _utcnow() + datetime.timedelta(
                seconds=token_info['expires_in'])
            token_info['expire_time'] = _utc_timestamp(expire_time)
        return token_info


class GoogleAuthType(object):
    """
    SA (Service Account),
    IA (Installed Application),
    GCE (Auth from a GCE instance with service account enabled)
    GCS_S3 (Cloud Storage S3 interoperability authentication)
    """
    SA = 'SA'
    IA = 'IA'
    GCE = 'GCE'
    GCS_S3 = 'GCS_S3'

    ALL_TYPES = [SA, IA, GCE, GCS_S3]
    OAUTH2_TYPES = [SA, IA, GCE]

    @classmethod
    def guess_type(cls, user_id):
        if cls._is_sa(user_id):
            return cls.SA
        elif cls._is_gce():
            return cls.GCE
        elif cls._is_gcs_s3(user_id):
            return cls.GCS_S3
        else:
            return cls.IA

    @classmethod
    def is_oauth2(cls, auth_type):
        return auth_type in cls.OAUTH2_TYPES

    @staticmethod
    def _is_gce():
        """
        Checks if we can access the GCE metadata server.
        Mocked in libcloud.test.common.google.GoogleTestCase.
        """
        http_code, http_reason, body = _get_gce_metadata()
        if http_code == httplib.OK and body:
            return True
        return False

    @staticmethod
    def _is_gcs_s3(user_id):
        """
        Checks S3 key format: 20 alphanumeric chars starting with GOOG.
        """
        return len(user_id) == 20 and user_id.startswith('GOOG')

    @staticmethod
    def _is_sa(user_id):
        return user_id.endswith('.gserviceaccount.com')


class GoogleOAuth2Credential(object):
    default_credential_file = '~/.google_libcloud_auth'

    def __init__(self, user_id, key, auth_type=None, credential_file=None,
                 scopes=None, **kwargs):
        self.auth_type = auth_type or GoogleAuthType.guess_type(user_id)
        if self.auth_type not in GoogleAuthType.ALL_TYPES:
            raise GoogleAuthError('Invalid auth type: %s' % self.auth_type)
        if not GoogleAuthType.is_oauth2(self.auth_type):
            raise GoogleAuthError(('Auth type %s cannot be used with OAuth2' %
                                   self.auth_type))
        self.user_id = user_id
        self.key = key

        default_credential_file = '.'.join([self.default_credential_file,
                                            user_id])
        self.credential_file = credential_file or default_credential_file
        # Default scopes to read/write for compute, storage, and dns.
        self.scopes = scopes or [
            'https://www.googleapis.com/auth/compute',
            'https://www.googleapis.com/auth/devstorage.full_control',
            'https://www.googleapis.com/auth/ndev.clouddns.readwrite',
        ]

        self.token = self._get_token_from_file()

        if self.auth_type == GoogleAuthType.GCE:
            self.oauth2_conn = GoogleGCEServiceAcctAuthConnection(
                self.user_id, self.scopes, **kwargs)
        elif self.auth_type == GoogleAuthType.SA:
            self.oauth2_conn = GoogleServiceAcctAuthConnection(
                self.user_id, self.key, self.scopes, **kwargs)
        elif self.auth_type == GoogleAuthType.IA:
            self.oauth2_conn = GoogleInstalledAppAuthConnection(
                self.user_id, self.key, self.scopes, **kwargs)
        else:
            raise GoogleAuthError('Invalid auth_type: %s' %
                                  str(self.auth_type))

        if self.token is None:
            self.token = self.oauth2_conn.get_new_token()
            self._write_token_to_file()

    @property
    def access_token(self):
        if self.token_expire_utc_datetime < _utcnow():
            self._refresh_token()
        return self.token['access_token']

    @property
    def token_expire_utc_datetime(self):
        return _from_utc_timestamp(self.token['expire_time'])

    def _refresh_token(self):
        self.token = self.oauth2_conn.refresh_token(self.token)
        self._write_token_to_file()

    def _get_token_from_file(self):
        """
        Read credential file and return token information.
        Mocked in libcloud.test.common.google.GoogleTestCase.

        :return:  Token information dictionary, or None
        :rtype:   ``dict`` or ``None``
        """
        token = None
        filename = os.path.realpath(os.path.expanduser(self.credential_file))

        try:
            with open(filename, 'r') as f:
                data = f.read()
            token = json.loads(data)
        except (IOError, ValueError):
            # Note: File related errors (IOError) and errors related to json
            # parsing of the data (ValueError) are not fatal.
            pass
        return token

    def _write_token_to_file(self):
        """
        Write token to credential file.
        Mocked in libcloud.test.common.google.GoogleTestCase.
        """
        try:
            filename = os.path.expanduser(self.credential_file)
            filename = os.path.realpath(filename)
            data = json.dumps(self.token)
            write_flags = os.O_CREAT | os.O_WRONLY | os.O_TRUNC
            with os.fdopen(os.open(filename, write_flags,
                                   int('600', 8)), 'w') as f:
                f.write(data)
        except:
            # Note: Failed to write (cache) token in a file is not fatal. It
            # simply means degraded performance since we will need to acquire a
            # new token each time script runs.
            pass


class GoogleBaseConnection(ConnectionUserAndKey, PollingConnection):
    """Base connection class for interacting with Google APIs."""
    driver = GoogleBaseDriver
    responseCls = GoogleResponse
    host = 'www.googleapis.com'
    poll_interval = 2.0
    timeout = 180

    def __init__(self, user_id, key=None, auth_type=None,
                 credential_file=None, scopes=None, **kwargs):
        """
        Determine authentication type, set up appropriate authentication
        connection and get initial authentication information.

        :param  user_id: The email address (for service accounts) or Client ID
                         (for installed apps) to be used for authentication.
        :type   user_id: ``str``

        :param  key: The RSA Key (for service accounts) or file path containing
                     key or Client Secret (for installed apps) to be used for
                     authentication.
        :type   key: ``str``

        :keyword  auth_type: See GoogleAuthType class for list and description
                             of accepted values.
                             If not supplied, auth_type will be guessed based
                             on value of user_id or if the code is running
                             on a GCE instance.
        :type     auth_type: ``str``

        :keyword  credential_file: Path to file for caching authentication
                                   information.
        :type     credential_file: ``str``

        :keyword  scopes: List of OAuth2 scope URLs. The empty default sets
                          read/write access to Compute, Storage, and DNS.
        :type     scopes: ``list``
        """
        super(GoogleBaseConnection, self).__init__(user_id, key, **kwargs)

        self.oauth2_credential = GoogleOAuth2Credential(
            user_id, key, auth_type, credential_file, scopes, **kwargs)

        python_ver = '%s.%s.%s' % (sys.version_info[0], sys.version_info[1],
                                   sys.version_info[2])
        ver_platform = 'Python %s/%s' % (python_ver, sys.platform)
        self.user_agent_append(ver_platform)

    def add_default_headers(self, headers):
        """
        @inherits: :class:`Connection.add_default_headers`
        """
        headers['Content-Type'] = 'application/json'
        headers['Host'] = self.host
        return headers

    def pre_connect_hook(self, params, headers):
        """
        Check to make sure that token hasn't expired.  If it has, get an
        updated token.  Also, add the token to the headers.

        @inherits: :class:`Connection.pre_connect_hook`
        """
        headers['Authorization'] = ('Bearer ' +
                                    self.oauth2_credential.access_token)
        return params, headers

    def encode_data(self, data):
        """Encode data to JSON"""
        return json.dumps(data)

    def request(self, *args, **kwargs):
        """
        @inherits: :class:`Connection.request`
        """
        # Adds some retry logic for the occasional
        # "Connection Reset by peer" error.
        retries = 4
        tries = 0
        while tries < (retries - 1):
            try:
                return super(GoogleBaseConnection, self).request(
                    *args, **kwargs)
            except socket.error:
                e = sys.exc_info()[1]
                if e.errno == errno.ECONNRESET:
                    tries = tries + 1
                else:
                    raise e
        # One more time, then give up.
        return super(GoogleBaseConnection, self).request(*args, **kwargs)

    def has_completed(self, response):
        """
        Determine if operation has completed based on response.

        :param  response: JSON response
        :type   response: I{responseCls}

        :return:  True if complete, False otherwise
        :rtype:   ``bool``
        """
        if response.object['status'] == 'DONE':
            return True
        else:
            return False

    def get_poll_request_kwargs(self, response, context, request_kwargs):
        """
        @inherits: :class:`PollingConnection.get_poll_request_kwargs`
        """
        return {'action': response.object['selfLink']}

    def morph_action_hook(self, action):
        """
        Update action to correct request path.

        In many places, the Google API returns a full URL to a resource.
        This will strip the scheme and host off of the path and just return
        the request.  Otherwise, it will prepend the base request_path to
        the action.

        :param  action: The action to be called in the http request
        :type   action: ``str``

        :return:  The modified request based on the action
        :rtype:   ``str``
        """
        if action.startswith('https://'):
            u = urlparse.urlsplit(action)
            request = urlparse.urlunsplit(('', '', u[2], u[3], u[4]))
        else:
            request = self.request_path + action
        return request
