def test_adds_query_params_properly(self): params1 = { b("a2"): b("r b"), b("b5"): b("=%3D"), b("a3"): [b("a")], b("c2"): [b("")], } params2 = { b("a3"): [b("2 q")], b("c@"): b(""), } params3 = b("""oauth_nonce=7d8f3e4a\ &oauth_timestamp=137131201\ &oauth_signature_method=HMAC-SHA1\ &oauth_consumer_key=9djdj82h48djs9d2\ &oauth_token=kkk9d7dh3k39sjv7\ """) resulting_query_string = b("""\ a2=r%20b\ &a3=2%20q\ &a3=a\ &b5=%3D%253D\ &c%40=\ &c2=\ &oauth_consumer_key=9djdj82h48djs9d2\ &oauth_nonce=7d8f3e4a\ &oauth_signature_method=HMAC-SHA1\ &oauth_timestamp=137131201\ &oauth_token=kkk9d7dh3k39sjv7""") self.assertEqual(urlencode_s(query_add(params1, params2, params3)), resulting_query_string)
def test_adds_query_params_properly(self): params1 = { "a2": "r b", "b5": "=%3D", "a3": ["a"], "c2": [""], } params2 = { "a3": ["2 q"], "c@": "", } params3 = """oauth_nonce=7d8f3e4a\ &oauth_timestamp=137131201\ &oauth_signature_method=HMAC-SHA1\ &oauth_consumer_key=9djdj82h48djs9d2\ &oauth_token=kkk9d7dh3k39sjv7\ """ resulting_query_string = "a2=r%20b&a3=2%20q&a3=a&b5=%3D%253D&c%40=&c2=&oauth_consumer_key=9djdj82h48djs9d2&oauth_nonce=7d8f3e4a&oauth_signature_method=HMAC-SHA1&oauth_timestamp=137131201&oauth_token=kkk9d7dh3k39sjv7" assert_equal(urlencode_s(query_add(params1, params2, params3)), resulting_query_string)
def _generate_signature(cls, method, url, params, body, headers, oauth_consumer_secret, oauth_token_secret, oauth_params): """ Given the base string parameters, secrets, and protocol parameters, calculates a signature for the request. :param method: HTTP method. :param url: Request URL. :param params: Additional query/payload parameters. :param body: Payload if any. :param headers: HTTP headers as a dictionary. :param oauth_consumer_secret: OAuth client shared secret (consumer secret). :param oauth_token_secret: OAuth token/temporary shared secret if obtained from the OAuth server. :param oauth_params: OAuth parameters generated by :func:`OAuthClient._generate_oauth_params`. :returns: Request signature. """ # Take parameters from the body if the Content-Type is specified # as ``application/x-www-form-urlencoded``. # http://tools.ietf.org/html/rfc5849#section-3.4.1.3.1 if body: try: try: content_type = headers[HEADER_CONTENT_TYPE] except KeyError: content_type = headers[HEADER_CONTENT_TYPE_CAPS] if content_type == CONTENT_TYPE_FORM_URLENCODED: # These parameters must also be included in the signature. # Ignore OAuth-specific parameters. They must be specified # separately. body_params = query_remove_oauth(parse_qs(body)) params = query_add(params, body_params) else: logging.info( "Entity-body specified but `content-type` header " \ "value is not %r: entity-body parameters if " \ "present will not be signed: got body %r" % \ (CONTENT_TYPE_FORM_URLENCODED, body) ) except KeyError: logging.warning( "Entity-body specified but `content-type` is missing " ) # Make oauth params and sign the request. signature_url = url_add_query(url, query_remove_oauth(params)) # NOTE: We're not explicitly cleaning up because this method # expects oauth params generated by _generate_oauth_params. base_string = generate_base_string(method, signature_url, oauth_params) signature_method = oauth_params[OAUTH_PARAM_SIGNATURE_METHOD] cls.check_signature_method(signature_method) try: sign_func = SIGNATURE_METHOD_MAP[signature_method] return sign_func(base_string, oauth_consumer_secret, oauth_token_secret) except KeyError: raise InvalidSignatureMethodError( "unsupported signature method: %r" % signature_method )