|
|
|
@ -114,19 +114,23 @@ class SimpleHttpClient(object): |
|
|
|
|
raise e |
|
|
|
|
|
|
|
|
|
@defer.inlineCallbacks |
|
|
|
|
def post_urlencoded_get_json(self, uri, args={}): |
|
|
|
|
def post_urlencoded_get_json(self, uri, args={}, headers=None): |
|
|
|
|
# TODO: Do we ever want to log message contents? |
|
|
|
|
logger.debug("post_urlencoded_get_json args: %s", args) |
|
|
|
|
|
|
|
|
|
query_bytes = urllib.urlencode(encode_urlencode_args(args), True) |
|
|
|
|
|
|
|
|
|
actual_headers = { |
|
|
|
|
b"Content-Type": [b"application/x-www-form-urlencoded"], |
|
|
|
|
b"User-Agent": [self.user_agent], |
|
|
|
|
} |
|
|
|
|
if headers: |
|
|
|
|
actual_headers.update(headers) |
|
|
|
|
|
|
|
|
|
response = yield self.request( |
|
|
|
|
"POST", |
|
|
|
|
uri.encode("ascii"), |
|
|
|
|
headers=Headers({ |
|
|
|
|
b"Content-Type": [b"application/x-www-form-urlencoded"], |
|
|
|
|
b"User-Agent": [self.user_agent], |
|
|
|
|
}), |
|
|
|
|
headers=Headers(actual_headers), |
|
|
|
|
bodyProducer=FileBodyProducer(StringIO(query_bytes)) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
@ -135,18 +139,33 @@ class SimpleHttpClient(object): |
|
|
|
|
defer.returnValue(json.loads(body)) |
|
|
|
|
|
|
|
|
|
@defer.inlineCallbacks |
|
|
|
|
def post_json_get_json(self, uri, post_json): |
|
|
|
|
def post_json_get_json(self, uri, post_json, headers=None): |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
|
uri (str): |
|
|
|
|
post_json (object): |
|
|
|
|
headers (dict[str, List[str]]|None): If not None, a map from |
|
|
|
|
header name to a list of values for that header |
|
|
|
|
|
|
|
|
|
Returns: |
|
|
|
|
Deferred[object]: parsed json |
|
|
|
|
""" |
|
|
|
|
json_str = encode_canonical_json(post_json) |
|
|
|
|
|
|
|
|
|
logger.debug("HTTP POST %s -> %s", json_str, uri) |
|
|
|
|
|
|
|
|
|
actual_headers = { |
|
|
|
|
b"Content-Type": [b"application/json"], |
|
|
|
|
b"User-Agent": [self.user_agent], |
|
|
|
|
} |
|
|
|
|
if headers: |
|
|
|
|
actual_headers.update(headers) |
|
|
|
|
|
|
|
|
|
response = yield self.request( |
|
|
|
|
"POST", |
|
|
|
|
uri.encode("ascii"), |
|
|
|
|
headers=Headers({ |
|
|
|
|
b"Content-Type": [b"application/json"], |
|
|
|
|
b"User-Agent": [self.user_agent], |
|
|
|
|
}), |
|
|
|
|
headers=Headers(actual_headers), |
|
|
|
|
bodyProducer=FileBodyProducer(StringIO(json_str)) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
@ -160,7 +179,7 @@ class SimpleHttpClient(object): |
|
|
|
|
defer.returnValue(json.loads(body)) |
|
|
|
|
|
|
|
|
|
@defer.inlineCallbacks |
|
|
|
|
def get_json(self, uri, args={}): |
|
|
|
|
def get_json(self, uri, args={}, headers=None): |
|
|
|
|
""" Gets some json from the given URI. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
@ -169,6 +188,8 @@ class SimpleHttpClient(object): |
|
|
|
|
None. |
|
|
|
|
**Note**: The value of each key is assumed to be an iterable |
|
|
|
|
and *not* a string. |
|
|
|
|
headers (dict[str, List[str]]|None): If not None, a map from |
|
|
|
|
header name to a list of values for that header |
|
|
|
|
Returns: |
|
|
|
|
Deferred: Succeeds when we get *any* 2xx HTTP response, with the |
|
|
|
|
HTTP body as JSON. |
|
|
|
@ -177,13 +198,13 @@ class SimpleHttpClient(object): |
|
|
|
|
error message. |
|
|
|
|
""" |
|
|
|
|
try: |
|
|
|
|
body = yield self.get_raw(uri, args) |
|
|
|
|
body = yield self.get_raw(uri, args, headers=headers) |
|
|
|
|
defer.returnValue(json.loads(body)) |
|
|
|
|
except CodeMessageException as e: |
|
|
|
|
raise self._exceptionFromFailedRequest(e.code, e.msg) |
|
|
|
|
|
|
|
|
|
@defer.inlineCallbacks |
|
|
|
|
def put_json(self, uri, json_body, args={}): |
|
|
|
|
def put_json(self, uri, json_body, args={}, headers=None): |
|
|
|
|
""" Puts some json to the given URI. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
@ -193,6 +214,8 @@ class SimpleHttpClient(object): |
|
|
|
|
None. |
|
|
|
|
**Note**: The value of each key is assumed to be an iterable |
|
|
|
|
and *not* a string. |
|
|
|
|
headers (dict[str, List[str]]|None): If not None, a map from |
|
|
|
|
header name to a list of values for that header |
|
|
|
|
Returns: |
|
|
|
|
Deferred: Succeeds when we get *any* 2xx HTTP response, with the |
|
|
|
|
HTTP body as JSON. |
|
|
|
@ -205,13 +228,17 @@ class SimpleHttpClient(object): |
|
|
|
|
|
|
|
|
|
json_str = encode_canonical_json(json_body) |
|
|
|
|
|
|
|
|
|
actual_headers = { |
|
|
|
|
b"Content-Type": [b"application/json"], |
|
|
|
|
b"User-Agent": [self.user_agent], |
|
|
|
|
} |
|
|
|
|
if headers: |
|
|
|
|
actual_headers.update(headers) |
|
|
|
|
|
|
|
|
|
response = yield self.request( |
|
|
|
|
"PUT", |
|
|
|
|
uri.encode("ascii"), |
|
|
|
|
headers=Headers({ |
|
|
|
|
b"User-Agent": [self.user_agent], |
|
|
|
|
"Content-Type": ["application/json"] |
|
|
|
|
}), |
|
|
|
|
headers=Headers(actual_headers), |
|
|
|
|
bodyProducer=FileBodyProducer(StringIO(json_str)) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
@ -226,7 +253,7 @@ class SimpleHttpClient(object): |
|
|
|
|
raise CodeMessageException(response.code, body) |
|
|
|
|
|
|
|
|
|
@defer.inlineCallbacks |
|
|
|
|
def get_raw(self, uri, args={}): |
|
|
|
|
def get_raw(self, uri, args={}, headers=None): |
|
|
|
|
""" Gets raw text from the given URI. |
|
|
|
|
|
|
|
|
|
Args: |
|
|
|
@ -235,6 +262,8 @@ class SimpleHttpClient(object): |
|
|
|
|
None. |
|
|
|
|
**Note**: The value of each key is assumed to be an iterable |
|
|
|
|
and *not* a string. |
|
|
|
|
headers (dict[str, List[str]]|None): If not None, a map from |
|
|
|
|
header name to a list of values for that header |
|
|
|
|
Returns: |
|
|
|
|
Deferred: Succeeds when we get *any* 2xx HTTP response, with the |
|
|
|
|
HTTP body at text. |
|
|
|
@ -246,12 +275,16 @@ class SimpleHttpClient(object): |
|
|
|
|
query_bytes = urllib.urlencode(args, True) |
|
|
|
|
uri = "%s?%s" % (uri, query_bytes) |
|
|
|
|
|
|
|
|
|
actual_headers = { |
|
|
|
|
b"User-Agent": [self.user_agent], |
|
|
|
|
} |
|
|
|
|
if headers: |
|
|
|
|
actual_headers.update(headers) |
|
|
|
|
|
|
|
|
|
response = yield self.request( |
|
|
|
|
"GET", |
|
|
|
|
uri.encode("ascii"), |
|
|
|
|
headers=Headers({ |
|
|
|
|
b"User-Agent": [self.user_agent], |
|
|
|
|
}) |
|
|
|
|
headers=Headers(actual_headers), |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
body = yield preserve_context_over_fn(readBody, response) |
|
|
|
@ -274,27 +307,33 @@ class SimpleHttpClient(object): |
|
|
|
|
# The two should be factored out. |
|
|
|
|
|
|
|
|
|
@defer.inlineCallbacks |
|
|
|
|
def get_file(self, url, output_stream, max_size=None): |
|
|
|
|
def get_file(self, url, output_stream, max_size=None, headers=None): |
|
|
|
|
"""GETs a file from a given URL |
|
|
|
|
Args: |
|
|
|
|
url (str): The URL to GET |
|
|
|
|
output_stream (file): File to write the response body to. |
|
|
|
|
headers (dict[str, List[str]]|None): If not None, a map from |
|
|
|
|
header name to a list of values for that header |
|
|
|
|
Returns: |
|
|
|
|
A (int,dict,string,int) tuple of the file length, dict of the response |
|
|
|
|
headers, absolute URI of the response and HTTP response code. |
|
|
|
|
""" |
|
|
|
|
|
|
|
|
|
actual_headers = { |
|
|
|
|
b"User-Agent": [self.user_agent], |
|
|
|
|
} |
|
|
|
|
if headers: |
|
|
|
|
actual_headers.update(headers) |
|
|
|
|
|
|
|
|
|
response = yield self.request( |
|
|
|
|
"GET", |
|
|
|
|
url.encode("ascii"), |
|
|
|
|
headers=Headers({ |
|
|
|
|
b"User-Agent": [self.user_agent], |
|
|
|
|
}) |
|
|
|
|
headers=Headers(actual_headers), |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
headers = dict(response.headers.getAllRawHeaders()) |
|
|
|
|
resp_headers = dict(response.headers.getAllRawHeaders()) |
|
|
|
|
|
|
|
|
|
if 'Content-Length' in headers and headers['Content-Length'] > max_size: |
|
|
|
|
if 'Content-Length' in resp_headers and resp_headers['Content-Length'] > max_size: |
|
|
|
|
logger.warn("Requested URL is too large > %r bytes" % (self.max_size,)) |
|
|
|
|
raise SynapseError( |
|
|
|
|
502, |
|
|
|
@ -327,7 +366,9 @@ class SimpleHttpClient(object): |
|
|
|
|
Codes.UNKNOWN, |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
defer.returnValue((length, headers, response.request.absoluteURI, response.code)) |
|
|
|
|
defer.returnValue( |
|
|
|
|
(length, resp_headers, response.request.absoluteURI, response.code), |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# XXX: FIXME: This is horribly copy-pasted from matrixfederationclient. |
|
|
|
|