Skip to content

Commit

Permalink
Merge pull request #139 from varju/url-encode-query-string
Browse files Browse the repository at this point in the history
URL encode non-alpha querystring parameters
  • Loading branch information
okigan committed Dec 5, 2021
2 parents 6d4b7bb + ad8d75a commit 230eed7
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 3 deletions.
16 changes: 15 additions & 1 deletion awscurl/awscurl.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import configargparse
import requests
from requests.structures import CaseInsensitiveDict
from urllib.parse import quote


from .utils import sha256_hash, sha256_hash_for_binary_data, sign
Expand Down Expand Up @@ -315,11 +316,24 @@ def __normalize_query_string(query):
for s in query.split('&')
if len(s) > 0)

normalized = '&'.join('%s=%s' % (p[0], p[1] if len(p) > 1 else '')
normalized = '&'.join('%s=%s' % (aws_url_encode(p[0]), aws_url_encode(p[1]) if len(p) > 1 else '')
for p in sorted(parameter_pairs))
return normalized


def aws_url_encode(text):
"""
URI-encode each parameter name and value according to the following rules:
- Do not URI-encode any of the unreserved characters that RFC 3986 defines: A-Z, a-z, 0-9, hyphen (-),
underscore (_), period (.), and tilde (~).
- Percent-encode all other characters with %XY, where X and Y are hexadecimal characters (0-9 and uppercase A-F).
For example, the space character must be encoded as %20 (not using '+', as some encoding schemes do) and
extended UTF-8 characters must be in the form %XY%ZA%BC.
- Double-encode any equals (=) characters in parameter values.
"""
return quote(text, safe='~=').replace('=', '==')


def __now():
return datetime.datetime.utcnow()

Expand Down
27 changes: 27 additions & 0 deletions tests/stages_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,33 @@ def test_task_1_create_a_canonical_request(self):
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
self.assertEqual(signed_headers, "host;x-amz-date")

def test_task_1_create_a_canonical_request_url_encode_querystring(self):
"""
Test that canonical requests correctly sort and url encode querystring parameters.
"""
canonical_request, payload_hash, signed_headers = task_1_create_a_canonical_request(
query="arg1=true&arg3=c,b,a&arg2=false&noEncoding=ABC-abc_1.23~tilde/slash",
headers="{'Content-Type': 'application/json', 'Accept': 'application/xml'}",
port=None,
host="my-gateway-id.execute-api.us-east-1.amazonaws.com",
amzdate="20190921T022008Z",
method="GET",
data="",
security_token=None,
data_binary=False,
canonical_uri="/stage/my-path")
self.assertEqual(canonical_request, "GET\n"
"/stage/my-path\n"
"arg1=true&arg2=false&arg3=c%2Cb%2Ca&noEncoding=ABC-abc_1.23~tilde%2Fslash\n"
"host:my-gateway-id.execute-api.us-east-1.amazonaws.com\n"
"x-amz-date:20190921T022008Z\n"
"\n"
"host;x-amz-date\n"
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
self.assertEqual(payload_hash,
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
self.assertEqual(signed_headers, "host;x-amz-date")

def test_task_2_create_the_string_to_sign(self):
"""
Test the next function that is creating a string in exactly the same way as AWS is on the
Expand Down
13 changes: 11 additions & 2 deletions tests/unit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
# -*- coding: UTF-8 -*-

import datetime
import logging
import sys

from unittest import TestCase

from mock import patch

from awscurl.awscurl import make_request
from awscurl.awscurl import aws_url_encode, make_request

from requests.exceptions import SSLError
from requests import Response
Expand Down Expand Up @@ -318,3 +317,13 @@ def test_make_request(self, mocked_resp):
self.assertFalse(expected in str(r.text.encode('utf-8')))

pass

class TestAwsUrlEncode(TestCase):
def test_aws_url_encode(self):
self.assertEqual(aws_url_encode(""), "")
self.assertEqual(aws_url_encode("AZaz09-_.~"), "AZaz09-_.~")
self.assertEqual(aws_url_encode(" /:@[`{"), "%20%2F%3A%40%5B%60%7B")
self.assertEqual(aws_url_encode("a=,=b"), "a==%2C==b")
self.assertEqual(aws_url_encode("\u0394-\u30a1"), "%CE%94-%E3%82%A1")

pass

0 comments on commit 230eed7

Please sign in to comment.