示例#1
0
 def Search(self, request, context):
   query = request.query
   query = urllib.urlencode({'q': query})
   response = urllib.urlopen(
       'http://ajax.googleapis.com/ajax/services/search/web?v=1.0&' + query)
   .read()
   _json = json.loads(response)
   results = _json['responseData']['results']
   for result in results:
     yield result
示例#2
0
    def get_static_google_map_image_url(self):
        """
        https://developers.google.com/maps/documentation/staticmaps/

        Example URL:
        http://maps.googleapis.com/maps/api/staticmap?center=Brooklyn+Bridge,New+York,NY&zoom=13&size=600x300&maptype=roadmap&markers=color:blue%7Clabel:S%7C40.702147,-74.015794&markers=color:green%7Clabel:G%7C40.711614,-74.012318&markers=color:red%7Clabel:C%7C40.718217,-73.998284&sensor=false
        """
        width = 301
        height = 234
        str_value = self.__str__()
        base_url = 'http://maps.googleapis.com/maps/api/staticmap?'
        query = urllib.urlencode({
            'center': str_value,
            'markers': 'color:green|%s' % str_value,
            'zoom': 13,
            'size': '%dx%d' % (
                width,
                height,
            ),
            'maptype': 'roadmap',
            'sensor': 'false',
        })
        url = base_url + query
        return url
示例#3
0
    def onAuthenticate(self, signature, extra):
        """
        Callback fired when a client responds to an authentication challenge.
        """
        print("onAuthenticate: {} {}".format(signature, extra))

        # if there is a pending auth, check the challenge response. The specifics
        # of how to check depend on the authentication method
        #
        if self._pending_auth:

            # WAMP-CRA
            #
            if isinstance(self._pending_auth, PendingAuthWampCra):

                if signature == self._pending_auth.signature:
                    # WAMP-CRA authentication signature was valid: accept the client
                    #
                    return types.Accept(authid=self._pending_auth.authid,
                                        authrole=self._pending_auth.authrole,
                                        authmethod=self._pending_auth.authmethod,
                                        authprovider=self._pending_auth.authprovider)
                else:
                    # WAMP-CRA authentication signature was invalid: deny client
                    #
                    return types.Deny(message=u"signature is invalid")

            # WAMP-Ticket
            #
            elif isinstance(self._pending_auth, PendingAuthTicket):

                # when doing WAMP-Ticket from static configuration, the ticket we
                # expect was store on the pending authentication object and we just compare ..
                #
                if self._pending_auth.authprovider == 'static':
                    if signature == self._pending_auth.ticket:
                        # WAMP-Ticket authentication ticket was valid: accept the client
                        #
                        return types.Accept(authid=self._pending_auth.authid,
                                            authrole=self._pending_auth.authrole,
                                            authmethod=self._pending_auth.authmethod,
                                            authprovider=self._pending_auth.authprovider)
                    else:
                        # WAMP-Ticket authentication ticket was invalid: deny client
                        #
                        return types.Deny(message=u"ticket is invalid")

                # WAMP-Ticket dynamic ..
                #
                else:
                    # call the configured dynamic authenticator procedure
                    # via the router's service session
                    #
                    service_session = self._router_factory.get(self._pending_auth.realm)._realm.session

                    d = service_session.call(self._pending_auth.authprovider,
                                             self._pending_auth.realm,
                                             self._pending_auth.authid,
                                             signature)

                    def on_authenticate_ok(principal):

                        if isinstance(principal, dict):
                            # dynamic ticket authenticator returned a dictionary (new)
                            authid = principal.get("authid", self._pending_auth.authid)
                            authrole = principal["role"]
                        else:
                            # backwards compatibility: dynamic ticket authenticator
                            # was expected to return a role directly
                            authid = self._pending_auth.authid
                            authrole = principal

                        return types.Accept(authid=authid,
                                            authrole=authrole,
                                            authmethod=self._pending_auth.authmethod,
                                            authprovider=self._pending_auth.authprovider)

                    def on_authenticate_error(err):
                        error = None
                        message = "dynamic WAMP-Ticket credential getter failed: {}".format(err)

                        if isinstance(err.value, ApplicationError):
                            error = err.value.error
                            if err.value.args and len(err.value.args):
                                message = err.value.args[0]

                        return types.Deny(error, message)

                    d.addCallbacks(on_authenticate_ok, on_authenticate_error)

                    return d

            elif isinstance(self._pending_auth, PendingAuthPersona):

                dres = Deferred()

                # The client did it's Mozilla Persona authentication thing
                # and now wants to verify the authentication and login.
                assertion = signature
                audience = str(self._pending_auth.audience)  # eg "http://192.168.1.130:8080/"
                provider = str(self._pending_auth.provider)  # eg "https://verifier.login.persona.org/verify"

                # To verify the authentication, we need to send a HTTP/POST
                # to Mozilla Persona. When successful, Persona will send us
                # back something like:

                # {
                #    "audience": "http://192.168.1.130:8080/",
                #    "expires": 1393681951257,
                #    "issuer": "gmail.login.persona.org",
                #    "email": "*****@*****.**",
                #    "status": "okay"
                # }

                headers = {'Content-Type': 'application/x-www-form-urlencoded'}
                body = urllib.urlencode({'audience': audience, 'assertion': assertion})

                from twisted.web.client import getPage
                d = getPage(url=provider,
                            method='POST',
                            postdata=body,
                            headers=headers)

                log.msg("Authentication request sent.")

                def done(res):
                    res = json.loads(res)
                    try:
                        if res['status'] == 'okay':

                            # awesome: Mozilla Persona successfully authenticated the user
                            self._transport._authid = res['email']
                            self._transport._authrole = self._pending_auth.role
                            self._transport._authmethod = 'mozilla_persona'

                            log.msg("Authenticated user {} with role {}".format(self._transport._authid, self._transport._authrole))
                            dres.callback(types.Accept(authid=self._transport._authid, authrole=self._transport._authrole, authmethod=self._transport._authmethod))

                            # remember the user's auth info (this marks the cookie as authenticated)
                            if self._transport._cbtid and self._transport.factory._cookiestore:
                                cs = self._transport.factory._cookiestore
                                cs.setAuth(self._transport._cbtid, self._transport._authid, self._transport._authrole, self._transport._authmethod)

                                # kick all sessions using same cookie (but not _this_ connection)
                                if True:
                                    for proto in cs.getProtos(self._transport._cbtid):
                                        if proto and proto != self._transport:
                                            try:
                                                proto.close()
                                            except Exception as e:
                                                pass
                        else:
                            log.msg("Authentication failed!")
                            log.msg(res)
                            dres.callback(types.Deny(reason="wamp.error.authorization_failed", message=res.get("reason", None)))
                    except Exception as e:
                        log.msg("internal error during authentication verification: {}".format(e))
                        dres.callback(types.Deny(reason="wamp.error.internal_error", message=str(e)))

                def error(err):
                    log.msg("Authentication request failed: {}".format(err.value))
                    dres.callback(types.Deny(reason="wamp.error.authorization_request_failed", message=str(err.value)))

                d.addCallbacks(done, error)

                return dres

            else:

                log.msg("don't know how to authenticate")

                return types.Deny()

        else:

            # deny client
            return types.Deny(message=u"no pending authentication")
示例#4
0
    def onAuthenticate(self, signature, extra):
        """
        Callback fired when a client responds to an authentication challenge.
        """
        print("onAuthenticate: {} {}".format(signature, extra))

        # if there is a pending auth, check the challenge response. The specifics
        # of how to check depend on the authentication method
        #
        if self._pending_auth:

            # WAMP-CRA
            #
            if isinstance(self._pending_auth, PendingAuthWampCra):

                if signature == self._pending_auth.signature:
                    # WAMP-CRA authentication signature was valid: accept the client
                    #
                    return types.Accept(
                        authid=self._pending_auth.authid,
                        authrole=self._pending_auth.authrole,
                        authmethod=self._pending_auth.authmethod,
                        authprovider=self._pending_auth.authprovider)
                else:
                    # WAMP-CRA authentication signature was invalid: deny client
                    #
                    return types.Deny(message=u"signature is invalid")

            # WAMP-Ticket
            #
            elif isinstance(self._pending_auth, PendingAuthTicket):

                # when doing WAMP-Ticket from static configuration, the ticket we
                # expect was store on the pending authentication object and we just compare ..
                #
                if self._pending_auth.authprovider == 'static':
                    if signature == self._pending_auth.ticket:
                        # WAMP-Ticket authentication ticket was valid: accept the client
                        #
                        return types.Accept(
                            authid=self._pending_auth.authid,
                            authrole=self._pending_auth.authrole,
                            authmethod=self._pending_auth.authmethod,
                            authprovider=self._pending_auth.authprovider)
                    else:
                        # WAMP-Ticket authentication ticket was invalid: deny client
                        #
                        return types.Deny(message=u"ticket is invalid")

                # WAMP-Ticket dynamic ..
                #
                else:
                    # call the configured dynamic authenticator procedure
                    # via the router's service session
                    #
                    service_session = self._router_factory.get(
                        self._pending_auth.realm)._realm.session

                    d = service_session.call(self._pending_auth.authprovider,
                                             self._pending_auth.realm,
                                             self._pending_auth.authid,
                                             signature)

                    def on_authenticate_ok(principal):

                        if isinstance(principal, dict):
                            # dynamic ticket authenticator returned a dictionary (new)
                            authid = principal.get("authid",
                                                   self._pending_auth.authid)
                            authrole = principal["role"]
                        else:
                            # backwards compatibility: dynamic ticket authenticator
                            # was expected to return a role directly
                            authid = self._pending_auth.authid
                            authrole = principal

                        return types.Accept(
                            authid=authid,
                            authrole=authrole,
                            authmethod=self._pending_auth.authmethod,
                            authprovider=self._pending_auth.authprovider)

                    def on_authenticate_error(err):
                        error = None
                        message = "dynamic WAMP-Ticket credential getter failed: {}".format(
                            err)

                        if isinstance(err.value, ApplicationError):
                            error = err.value.error
                            if err.value.args and len(err.value.args):
                                message = err.value.args[0]

                        return types.Deny(error, message)

                    d.addCallbacks(on_authenticate_ok, on_authenticate_error)

                    return d

            elif isinstance(self._pending_auth, PendingAuthPersona):

                dres = Deferred()

                # The client did it's Mozilla Persona authentication thing
                # and now wants to verify the authentication and login.
                assertion = signature
                audience = str(self._pending_auth.audience
                               )  # eg "http://192.168.1.130:8080/"
                provider = str(
                    self._pending_auth.provider
                )  # eg "https://verifier.login.persona.org/verify"

                # To verify the authentication, we need to send a HTTP/POST
                # to Mozilla Persona. When successful, Persona will send us
                # back something like:

                # {
                #    "audience": "http://192.168.1.130:8080/",
                #    "expires": 1393681951257,
                #    "issuer": "gmail.login.persona.org",
                #    "email": "*****@*****.**",
                #    "status": "okay"
                # }

                headers = {'Content-Type': 'application/x-www-form-urlencoded'}
                body = urllib.urlencode({
                    'audience': audience,
                    'assertion': assertion
                })

                from twisted.web.client import getPage
                d = getPage(url=provider,
                            method='POST',
                            postdata=body,
                            headers=headers)

                self.log.info("Authentication request sent.")

                def done(res):
                    res = json.loads(res)
                    try:
                        if res['status'] == 'okay':

                            # awesome: Mozilla Persona successfully authenticated the user
                            self._transport._authid = res['email']
                            self._transport._authrole = self._pending_auth.role
                            self._transport._authmethod = 'mozilla_persona'

                            self.log.info(
                                "Authenticated user {} with role {}".format(
                                    self._transport._authid,
                                    self._transport._authrole))
                            dres.callback(
                                types.Accept(
                                    authid=self._transport._authid,
                                    authrole=self._transport._authrole,
                                    authmethod=self._transport._authmethod))

                            # remember the user's auth info (this marks the cookie as authenticated)
                            if self._transport._cbtid and self._transport.factory._cookiestore:
                                cs = self._transport.factory._cookiestore
                                cs.setAuth(self._transport._cbtid,
                                           self._transport._authid,
                                           self._transport._authrole,
                                           self._transport._authmethod)

                                # kick all sessions using same cookie (but not _this_ connection)
                                if True:
                                    for proto in cs.getProtos(
                                            self._transport._cbtid):
                                        if proto and proto != self._transport:
                                            try:
                                                proto.close()
                                            except Exception as e:
                                                pass
                        else:
                            self.log.info("Authentication failed!")
                            self.log.info(res)
                            dres.callback(
                                types.Deny(
                                    reason="wamp.error.authorization_failed",
                                    message=res.get("reason", None)))
                    except Exception as e:
                        self.log.info(
                            "internal error during authentication verification: {}"
                            .format(e))
                        dres.callback(
                            types.Deny(reason="wamp.error.internal_error",
                                       message=str(e)))

                def error(err):
                    self.log.info("Authentication request failed: {}".format(
                        err.value))
                    dres.callback(
                        types.Deny(
                            reason="wamp.error.authorization_request_failed",
                            message=str(err.value)))

                d.addCallbacks(done, error)

                return dres

            else:

                self.log.info("don't know how to authenticate")

                return types.Deny()

        else:

            # deny client
            return types.Deny(message=u"no pending authentication")
示例#5
0
    def onAuthenticate(self, signature, extra):

        if isinstance(self._pending_auth, PendingAuthPersona):

            dres = Deferred()

            ## The client did it's Mozilla Persona authentication thing
            ## and now wants to verify the authentication and login.
            assertion = signature
            audience = str(
                self._pending_auth.audience)  # eg "http://192.168.1.130:8080/"
            provider = str(self._pending_auth.provider
                           )  # eg "https://verifier.login.persona.org/verify"

            ## To verify the authentication, we need to send a HTTP/POST
            ## to Mozilla Persona. When successful, Persona will send us
            ## back something like:

            # {
            #    "audience": "http://192.168.1.130:8080/",
            #    "expires": 1393681951257,
            #    "issuer": "gmail.login.persona.org",
            #    "email": "*****@*****.**",
            #    "status": "okay"
            # }

            headers = {'Content-Type': 'application/x-www-form-urlencoded'}
            body = urllib.urlencode({
                'audience': audience,
                'assertion': assertion
            })

            from twisted.web.client import getPage
            d = getPage(url=provider,
                        method='POST',
                        postdata=body,
                        headers=headers)

            log.msg("Authentication request sent.")

            def done(res):
                res = json.loads(res)
                try:
                    if res['status'] == 'okay':

                        ## awesome: Mozilla Persona successfully authenticated the user
                        self._transport._authid = res['email']
                        self._transport._authrole = self._pending_auth.role
                        self._transport._authmethod = 'mozilla_persona'

                        log.msg("Authenticated user {} with role {}".format(
                            self._transport._authid,
                            self._transport._authrole))
                        dres.callback(
                            types.Accept(
                                authid=self._transport._authid,
                                authrole=self._transport._authrole,
                                authmethod=self._transport._authmethod))

                        ## remember the user's auth info (this marks the cookie as authenticated)
                        if self._transport._cbtid and self._transport.factory._cookiestore:
                            cs = self._transport.factory._cookiestore
                            cs.setAuth(self._transport._cbtid,
                                       self._transport._authid,
                                       self._transport._authrole,
                                       self._transport._authmethod)

                            ## kick all sessions using same cookie (but not _this_ connection)
                            if True:
                                for proto in cs.getProtos(
                                        self._transport._cbtid):
                                    if proto and proto != self._transport:
                                        try:
                                            proto.close()
                                        except Exception as e:
                                            pass
                    else:
                        log.msg("Authentication failed!")
                        log.msg(res)
                        dres.callback(
                            types.Deny(
                                reason="wamp.error.authorization_failed",
                                message=res.get("reason", None)))
                except Exception as e:
                    log.msg(
                        "internal error during authentication verification: {}"
                        .format(e))
                    dres.callback(
                        types.Deny(reason="wamp.error.internal_error",
                                   message=str(e)))

            def error(err):
                log.msg("Authentication request failed: {}".format(err.value))
                dres.callback(
                    types.Deny(
                        reason="wamp.error.authorization_request_failed",
                        message=str(err.value)))

            d.addCallbacks(done, error)

            return dres

        else:

            log.msg("don't know how to authenticate")

            return types.Deny()
示例#6
0
def shuffle_qs(qs):
    qs_parts = urllib.parse.parse_qsl(qs)
    random.shuffle(qs_parts)
    return urllib.urlencode(qs_parts)
示例#7
0
def sorted_qs(qs):
    # we use parse_qsl to avoid getting multiple values as list and to preserve
    # the order of the qs_params
    qs_parts = urllib.parse.parse_qsl(qs)
    qs_parts_sorted = sorted(qs_parts)
    return urllib.urlencode(qs_parts_sorted)
示例#8
0
def run():
    sess = requests.session()
    sess.auth = ('vagrant', 'vagrant')

    API_URL = 'http://localhost:8000/api/v1/'

    # Make an app record, if vr_node_example isn't already there.
    app_name = 'vr_node_example'
    app_url = API_URL + 'apps/%s/' % app_name

    r = sess.get(app_url)

    if r.status_code == 404:
        # App not found.  Make it!
        app_data = json.dumps({
            "name":
            app_name,
            "repo_type":
            "hg",
            "repo_url":
            "https://bitbucket.org/btubbs/vr_node_example"
        })
        r = sess.post(API_URL + 'apps/', data=app_data)

        # Throw exception and bail out if this fails
        r.raise_for_status()

    # Make a buildpack record, if necessary.  Buildpacks
    # don't have nice natural
    # keys like apps do, so we'll search.
    node_buildpack_url = (
        'https://github.com/heroku/heroku-buildpack-nodejs.git')
    buildpack_search_url = API_URL + 'buildpacks/?' + urllib.urlencode(
        {'repo_url': node_buildpack_url})
    r = sess.get(buildpack_search_url)
    results = r.json()['objects']
    if not len(results):
        # Not buildpack record found with that URL.  Make one.
        buildpack_data = json.dumps({
            'repo_url': node_buildpack_url,
            'repo_type': 'git',
            'order': 0,
        })
        r = sess.post(API_URL + 'buildpacks/', data=buildpack_data)
        assert r.status_code == 201

    # Make a build record
    build_data = json.dumps({
        'app': urllib.parse.urlparse(app_url).path,
        'tag': 'v4',
    })
    r = sess.post(API_URL + 'builds/', data=build_data)
    assert r.status_code == 201
    build_url = r.headers['location']

    # Tell VR to build it
    r = sess.post(build_url + 'build/')

    # Watch the output
    stream_url = 'http://localhost:8000/api/streams/events/'
    for message in sseclient.SSEClient(stream_url, auth=sess.auth):
        print(message.id, message)
示例#9
0
   def onAuthenticate(self, signature, extra):
      """
      Callback fired when a client responds to an authentication challenge.
      """
      print("onAuthenticate: {} {}".format(signature, extra))

      ## if there is a pending auth, and the signature provided by client matches ..
      if self._pending_auth:

         if isinstance(self._pending_auth, PendingAuthWampCra):

            if signature == self._pending_auth.signature:

               ## accept the client
               return types.Accept(authid = self._pending_auth.authid,
                  authrole = self._pending_auth.authrole,
                  authmethod = self._pending_auth.authmethod,
                  authprovider = self._pending_auth.authprovider)
            else:

               ## deny client
               return types.Deny(message = u"signature is invalid")

         elif isinstance(self._pending_auth, PendingAuthPersona):

            dres = Deferred()

            ## The client did it's Mozilla Persona authentication thing
            ## and now wants to verify the authentication and login.
            assertion = signature
            audience = str(self._pending_auth.audience) # eg "http://192.168.1.130:8080/"
            provider = str(self._pending_auth.provider) # eg "https://verifier.login.persona.org/verify"

            ## To verify the authentication, we need to send a HTTP/POST
            ## to Mozilla Persona. When successful, Persona will send us
            ## back something like:

            # {
            #    "audience": "http://192.168.1.130:8080/",
            #    "expires": 1393681951257,
            #    "issuer": "gmail.login.persona.org",
            #    "email": "*****@*****.**",
            #    "status": "okay"
            # }

            headers = {'Content-Type': 'application/x-www-form-urlencoded'}
            body = urllib.urlencode({'audience': audience, 'assertion': assertion})

            from twisted.web.client import getPage
            d = getPage(url = provider,
                        method = 'POST',
                        postdata = body,
                        headers = headers)

            log.msg("Authentication request sent.")

            def done(res):
               res = json.loads(res)
               try:
                  if res['status'] == 'okay':

                     ## awesome: Mozilla Persona successfully authenticated the user
                     self._transport._authid = res['email']
                     self._transport._authrole = self._pending_auth.role
                     self._transport._authmethod = 'mozilla_persona'

                     log.msg("Authenticated user {} with role {}".format(self._transport._authid, self._transport._authrole))
                     dres.callback(types.Accept(authid = self._transport._authid, authrole = self._transport._authrole, authmethod = self._transport._authmethod))

                     ## remember the user's auth info (this marks the cookie as authenticated)
                     if self._transport._cbtid and self._transport.factory._cookiestore:
                        cs = self._transport.factory._cookiestore
                        cs.setAuth(self._transport._cbtid, self._transport._authid, self._transport._authrole, self._transport._authmethod)

                        ## kick all sessions using same cookie (but not _this_ connection)
                        if True:
                           for proto in cs.getProtos(self._transport._cbtid):
                              if proto and proto != self._transport:
                                 try:
                                    proto.close()
                                 except Exception as e:
                                    pass
                  else:
                     log.msg("Authentication failed!")
                     log.msg(res)
                     dres.callback(types.Deny(reason = "wamp.error.authorization_failed", message = res.get("reason", None)))
               except Exception as e:
                  log.msg("internal error during authentication verification: {}".format(e))
                  dres.callback(types.Deny(reason = "wamp.error.internal_error", message = str(e)))

            def error(err):
               log.msg("Authentication request failed: {}".format(err.value))
               dres.callback(types.Deny(reason = "wamp.error.authorization_request_failed", message = str(err.value)))

            d.addCallbacks(done, error)

            return dres

         else:

            log.msg("don't know how to authenticate")

            return types.Deny()

      else:

         ## deny client
         return types.Deny(message = u"no pending authentication")
示例#10
0
def shuffle_qs(qs):
    qs_parts = urllib.parse.parse_qsl(qs)
    random.shuffle(qs_parts)
    return urllib.urlencode(qs_parts)
示例#11
0
def sorted_qs(qs):
    # we use parse_qsl to avoid getting multiple values as list and to preserve
    # the order of the qs_params
    qs_parts = urllib.parse.parse_qsl(qs)
    qs_parts_sorted = sorted(qs_parts)
    return urllib.urlencode(qs_parts_sorted)
def request(method,
            url,
            params=None,
            data=None,
            headers=None,
            cookies=None,
            files=None,
            auth=None,
            timeout=60,
            allow_redirects=False,
            stream=False):
    """Initiate an HTTP(S) request. Returns :class:`Response` object.

    :param method: 'GET' or 'POST'
    :type method: unicode
    :param url: URL to open
    :type url: unicode
    :param params: mapping of URL parameters
    :type params: dict
    :param data: mapping of form data ``{'field_name': 'value'}`` or
        :class:`str`
    :type data: dict or str
    :param headers: HTTP headers
    :type headers: dict
    :param cookies: cookies to send to server
    :type cookies: dict
    :param files: files to upload (see below).
    :type files: dict
    :param auth: username, password
    :type auth: tuple
    :param timeout: connection timeout limit in seconds
    :type timeout: int
    :param allow_redirects: follow redirections
    :type allow_redirects: bool
    :param stream: Stream content instead of fetching it all at once.
    :type stream: bool
    :returns: Response object
    :rtype: :class:`Response`


    The ``files`` argument is a dictionary::

        {'fieldname' : { 'filename': 'blah.txt',
                         'content': '<binary data>',
                         'mimetype': 'text/plain'}
        }

    * ``fieldname`` is the name of the field in the HTML form.
    * ``mimetype`` is optional. If not provided, :mod:`mimetypes` will
      be used to guess the mimetype, or ``application/octet-stream``
      will be used.

    """
    # TODO: cookies
    socket.setdefaulttimeout(timeout)

    # Default handlers
    openers = [urllib2.ProxyHandler(urllib2.getproxies())]

    if not allow_redirects:
        openers.append(NoRedirectHandler())

    if auth is not None:  # Add authorisation handler
        username, password = auth
        password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
        password_manager.add_password(None, url, username, password)
        auth_manager = urllib2.HTTPBasicAuthHandler(password_manager)
        openers.append(auth_manager)

    # Install our custom chain of openers
    opener = urllib2.build_opener(*openers)
    urllib2.install_opener(opener)

    if not headers:
        headers = CaseInsensitiveDictionary()
    else:
        headers = CaseInsensitiveDictionary(headers)

    if 'user-agent' not in headers:
        headers['user-agent'] = USER_AGENT

    # Accept gzip-encoded content
    encodings = [
        s.strip() for s in headers.get('accept-encoding', '').split(',')
    ]
    if 'gzip' not in encodings:
        encodings.append('gzip')

    headers['accept-encoding'] = ', '.join(encodings)

    if files:
        if not data:
            data = {}
        new_headers, data = encode_multipart_formdata(data, files)
        headers.update(new_headers)
    elif data and isinstance(data, dict):
        data = urllib.urlencode(str_dict(data))

    # Make sure everything is encoded text
    headers = str_dict(headers)

    if isinstance(url, unicode):
        url = url.encode('utf-8')

    if params:  # GET args (POST args are handled in encode_multipart_formdata)

        scheme, netloc, path, query, fragment = urlparse.urlsplit(url)

        if query:  # Combine query string and `params`
            url_params = urlparse.parse_qs(query)
            # `params` take precedence over URL query string
            url_params.update(params)
            params = url_params

        query = urllib.urlencode(str_dict(params), doseq=True)
        url = urlparse.urlunsplit((scheme, netloc, path, query, fragment))

    req = Request(url, data, headers, method=method)
    return Response(req, stream)