def _modify_request_before_signing(self, request): # This is our chance to add additional query params we need # before we go about calculating the signature. request.headers = {} request.method = 'GET' # Note that we're not including X-Amz-Signature. # From the docs: "The Canonical Query String must include all the query # parameters from the preceding table except for X-Amz-Signature. auth_params = { 'X-Amz-Algorithm': 'AWS4-HMAC-SHA256', 'X-Amz-Credential': self.scope(request), 'X-Amz-Date': self.timestamp, 'X-Amz-Expires': self._expires, 'X-Amz-SignedHeaders': 'host', } if self.credentials.token is not None: auth_params['X-Amz-Security-Token'] = self.credentials.token # Now parse the original query string to a dict, inject our new query # params, and serialize back to a query string. url_parts = urlsplit(request.url) # parse_qs makes each value a list, but in our case we know we won't # have repeated keys so we know we have single element lists which we # can convert back to scalar values. query_dict = dict([(k, v[0]) for k, v in parse_qs(url_parts.query).items()]) # The spec is particular about this. It *has* to be: # https://<endpoint>?<operation params>&<auth params> # You can't mix the two types of params together, i.e just keep doing # new_query_params.update(op_params) # new_query_params.update(auth_params) # urlencode(new_query_params) operation_params = '' if request.data: # We also need to move the body params into the query string. # request.data will be populated, for example, with query services # which normally form encode the params into the body. # This means that request.data is a dict() of the operation params. query_dict.update(request.data) request.data = '' if query_dict: operation_params = urlencode(query_dict) + '&' new_query_string = operation_params + urlencode(auth_params) # url_parts is a tuple (and therefore immutable) so we need to create # a new url_parts with the new query string. # <part> - <index> # scheme - 0 # netloc - 1 # path - 2 # query - 3 <-- we're replacing this. # fragment - 4 p = url_parts new_url_parts = (p[0], p[1], p[2], new_query_string, p[4]) request.url = urlunsplit(new_url_parts)
def _serialize_request_description(request_dict): if isinstance(request_dict.get('body'), dict): # urlencode the request body. encoded = urlencode(request_dict['body']).encode('utf-8') request_dict['body'] = encoded if isinstance(request_dict.get('query_string'), dict): encoded = urlencode(request_dict.pop('query_string')) if encoded: # 'requests' automatically handle this, but we in the # test runner we need to handle the case where the url_path # already has query params. if '?' not in request_dict['url_path']: request_dict['url_path'] += '?%s' % encoded else: request_dict['url_path'] += '&%s' % encoded
def prepare_body(self, data): """Prepares the given HTTP body data.""" self.body = data if self.body == b'': self.body = None if not self.body and self.method == 'GET': return if self.body is None: self.headers['Content-Length'] = '0' if isinstance(self.body, dict): params = list(self.body.items()) self.body = urlencode(params, doseq=True) try: length = len(self.body) self.headers['Content-Length'] = str(length) except (AttributeError, TypeError) as e: pass if 'Content-Length' not in self.headers: if hasattr(data, 'seek') and hasattr(data, 'tell'): orig_pos = data.tell() data.seek(0, 2) end_file_pos = data.tell() self.headers['Content-Length'] = str(end_file_pos - orig_pos) data.seek(orig_pos) if self.body and 'Content-Length' not in self.headers: # NOTE: This should probably never happen, we don't use chunked self.headers['Transfer-Encoding'] = 'chunked'
def _prepare_url(self, original): url = original.url if original.params: url_parts = urlparse(url) delim = '&' if url_parts.query else '?' params = urlencode(list(original.params.items()), doseq=True) url = delim.join((url, params)) return url
def _prepare_body(self, original): """Prepares the given HTTP body data.""" body = original.data if body == b'': body = None if isinstance(body, dict): params = [self._to_utf8(item) for item in body.items()] body = urlencode(params, doseq=True) return body
def prepare_url(self, url, params): if params: params = urlencode(list(params.items()), doseq=True) self.url = '%s?%s' % (url, params) else: self.url = url
def _prepare_url(self, original): url = original.url if original.params: params = urlencode(list(original.params.items()), doseq=True) url = '%s?%s' % (url, params) return url