Use Cases
Handling Streaming Responses
In addition to receiving responses
with IResponse.deliverBody(), treq provides a helper function
treq.collect() which takes a
response and a single argument function which will be called with all new
data available from the response. Much like IProtocol.dataReceived(),
treq.collect() knows nothing about the framing of your data and will
simply call your collector function with any data that is currently available.
By default, treq buffers the full response in memory.
Pass unbufferred=True to disable this behavior.
Here is an example which simply a file object’s write method to
treq.collect() to save the response body to a file.
async def download_file(reactor, url, destination_filename):
with open(destination_filename, "wb") as destination:
response = await treq.get(url, unbuffered=True)
await treq.collect(response, destination.write)
Full example: download_file.py
URLs, URIs, and Hyperlinks
The url argument to HTTPClient.request() accepts three URL representations:
High-level:
hyperlink.DecodedURLMid-level
str(unicodeon Python 2)Low-level: ASCII
bytesorhyperlink.URL
The high-level DecodedURL form is useful when programatically generating URLs.
Here is an example that builds a URL that contains a & character, which is automatically escaped properly.
async def basic_url(reactor):
url = (
DecodedURL.from_text("https://httpbin.org")
.child("get") # add path /get
.add("foo", "&") # add query ?foo=%26
)
print(url.to_text())
await print_response(await treq.get(url))
Full example: basic_url.py
Query Parameters
treq.HTTPClient.request() supports a params keyword argument which will
be URL-encoded and added to the url argument in addition to any query
parameters that may already exist.
The params argument may be either a dict or a list of
(key, value) tuples.
If it is a dict then the values in the dict may either be scalar values or a list or tuple thereof.
Scalar values means str, bytes, or anything else — even None — which will be coerced to str.
Strings are UTF-8 encoded.
async def query_params(reactor):
print("List of tuples")
resp = await treq.get(
"https://httpbin.org/get", params=[("foo", "bar"), ("baz", "bax")]
)
print(await resp.text())
print("Single value dictionary")
resp = await treq.get(
"https://httpbin.org/get", params={"foo": "bar", "baz": "bax"}
)
print(await resp.text())
print("Multi value dictionary")
resp = await treq.get(
"https://httpbin.org/get", params={b"foo": [b"bar", b"baz", b"bax"]}
)
print(await resp.text())
print("Mixed value dictionary")
resp = await treq.get(
"https://httpbin.org/get",
params={"foo": [1, 2, 3], "bax": b"quux", b"bar": "foo"},
)
print(await resp.text())
print("Preserved query parameters")
resp = await treq.get("https://httpbin.org/get?foo=bar", params={"baz": "bax"})
print(await resp.text())
Full example: query_params.py
If you prefer a strictly-typed API, try hyperlink.DecodedURL.
Its add() and set() methods manipulate query parameters without risk of accidental type coercion.
JSON
HTTPClient.request() supports a json keyword argument that gives a data structure to serialize as JSON (using json.dumps()).
This also implies a Content-Type: application/json request header.
The json parameter is mutually-exclusive with data.
The _Response.json() method decodes a JSON response body.
It buffers the whole response and decodes it with json.loads().
async def json_post(reactor):
response = await treq.post(
"https://httpbin.org/post",
json={"msg": "Hello!"},
)
data = await response.json()
pprint(data)
Full example: json_post.py
Auth
HTTP Basic authentication as specified in RFC 2617 is easily supported by
passing an auth keyword argument to any of the request functions.
The auth argument should be a tuple of the form ('username', 'password').
async def basic_auth(reactor):
resp = await treq.get(
"https://httpbin.org/basic-auth/treq/treq",
auth=("treq", "treq"),
)
await print_response(resp)
Full example: basic_auth.py
Redirects
treq handles redirects by default.
The following will print a 200 OK response.
async def redirects(reactor):
resp = await treq.get("https://httpbin.org/redirect/1")
await print_response(resp)
Full example: redirects.py
You can easily disable redirects by simply passing allow_redirects=False to any of the request methods.
async def disable_redirects(reactor):
resp = await treq.get(
"https://httpbin.org/redirect/1",
allow_redirects=False,
)
await print_response(resp)
Full example: disable_redirects.py
You can even access the complete history of treq response objects by calling
the history() method on the response.
async def response_history(reactor):
resp = await treq.get("https://httpbin.org/redirect/1")
print("Response history:")
print(resp.history())
await print_response(resp)
Full example: response_history.py
Customizing the Twisted Agent
The main treq module has helper functions that automatically instantiate
an instance of treq.client.HTTPClient. You can create an instance
of HTTPClient directly in order to customize the
parameters used to initialize it.
Internally, the HTTPClient wraps an instance of
twisted.web.client.Agent. When you create an instance of
HTTPClient, you must initialize it with an instance of
Agent. This allows you to customize its
behavior.
async def custom_agent(reactor):
my_agent = Agent(reactor, connectTimeout=42)
http_client = HTTPClient(my_agent)
resp = await http_client.get(
"https://secure.example.net/area51",
auth=("admin", "you'll never guess!"),
)
await print_response(resp)
Full example: custom_agent.py