Skip to content

Commit feb404f

Browse files
Seperate content=... and data=... parameters (#1266)
* Seperate content=... and data=... parameters * Update compatibility.md
1 parent 54f7708 commit feb404f

17 files changed

+170
-56
lines changed

docs/compatibility.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,28 @@ This documentation outlines places where the API differs...
99
Accessing `response.url` will return a `URL` instance, rather than a string.
1010
Use `str(response.url)` if you need a string instance.
1111

12+
## Request Content
13+
14+
For uploading raw text or binary content we prefer to use a `content` parameter,
15+
in order to better separate this usage from the case of uploading form data.
16+
17+
For example, using `content=...` to upload raw content:
18+
19+
```python
20+
# Uploading text, bytes, or a bytes iterator.
21+
httpx.post(..., content=b"Hello, world")
22+
```
23+
24+
And using `data=...` to send form data:
25+
26+
```python
27+
# Uploading form data.
28+
httpx.post(..., data={"message": "Hello, world"})
29+
```
30+
31+
If you're using a type checking tool such as `mypy`, you'll see warnings issues if using test/byte content with the `data` argument.
32+
However, for compatibility reasons with `requests`, we do still handle the case where `data=...` is used with raw binary and text contents.
33+
1234
## Status Codes
1335

1436
In our documentation we prefer the uppercased versions, such as `codes.NOT_FOUND`, but also provide lower-cased versions for API compatibility with `requests`.

docs/quickstart.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,13 +249,18 @@ For more complicated data structures you'll often want to use JSON encoding inst
249249

250250
## Sending Binary Request Data
251251

252-
For other encodings, you should use either a `bytes` type or a generator
253-
that yields `bytes`.
252+
For other encodings, you should use the `content=...` parameter, passing
253+
either a `bytes` type or a generator that yields `bytes`.
254254

255-
You'll probably also want to set a custom `Content-Type` header when uploading
255+
```pycon
256+
>>> content = b'Hello, world'
257+
>>> r = httpx.post("https://httpbin.org/post", content=content)
258+
```
259+
260+
You may also want to set a custom `Content-Type` header when uploading
256261
binary data.
257262

258-
## Response Status Codes
263+
## Response Status Codes
259264

260265
We can inspect the HTTP status code of the response:
261266

httpx/_api.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
HeaderTypes,
1111
ProxiesTypes,
1212
QueryParamTypes,
13+
RequestContent,
1314
RequestData,
1415
RequestFiles,
1516
TimeoutTypes,
@@ -23,6 +24,7 @@ def request(
2324
url: URLTypes,
2425
*,
2526
params: QueryParamTypes = None,
27+
content: RequestContent = None,
2628
data: RequestData = None,
2729
files: RequestFiles = None,
2830
json: typing.Any = None,
@@ -46,8 +48,10 @@ def request(
4648
* **url** - URL for the new `Request` object.
4749
* **params** - *(optional)* Query parameters to include in the URL, as a
4850
string, dictionary, or list of two-tuples.
49-
* **data** - *(optional)* Data to include in the body of the request, as a
50-
dictionary
51+
* **content** - *(optional)* Binary content to include in the body of the
52+
request, as bytes or a byte iterator.
53+
* **data** - *(optional)* Form data to include in the body of the request,
54+
as a dictionary.
5155
* **files** - *(optional)* A dictionary of upload files to include in the
5256
body of the request.
5357
* **json** - *(optional)* A JSON serializable object to include in the body
@@ -89,6 +93,7 @@ def request(
8993
return client.request(
9094
method=method,
9195
url=url,
96+
content=content,
9297
data=data,
9398
files=files,
9499
json=json,
@@ -105,6 +110,7 @@ def stream(
105110
url: URLTypes,
106111
*,
107112
params: QueryParamTypes = None,
113+
content: RequestContent = None,
108114
data: RequestData = None,
109115
files: RequestFiles = None,
110116
json: typing.Any = None,
@@ -133,6 +139,7 @@ def stream(
133139
method=method,
134140
url=url,
135141
params=params,
142+
content=content,
136143
data=data,
137144
files=files,
138145
json=json,
@@ -266,6 +273,7 @@ def head(
266273
def post(
267274
url: URLTypes,
268275
*,
276+
content: RequestContent = None,
269277
data: RequestData = None,
270278
files: RequestFiles = None,
271279
json: typing.Any = None,
@@ -288,6 +296,7 @@ def post(
288296
return request(
289297
"POST",
290298
url,
299+
content=content,
291300
data=data,
292301
files=files,
293302
json=json,
@@ -307,6 +316,7 @@ def post(
307316
def put(
308317
url: URLTypes,
309318
*,
319+
content: RequestContent = None,
310320
data: RequestData = None,
311321
files: RequestFiles = None,
312322
json: typing.Any = None,
@@ -329,6 +339,7 @@ def put(
329339
return request(
330340
"PUT",
331341
url,
342+
content=content,
332343
data=data,
333344
files=files,
334345
json=json,
@@ -348,6 +359,7 @@ def put(
348359
def patch(
349360
url: URLTypes,
350361
*,
362+
content: RequestContent = None,
351363
data: RequestData = None,
352364
files: RequestFiles = None,
353365
json: typing.Any = None,
@@ -370,6 +382,7 @@ def patch(
370382
return request(
371383
"PATCH",
372384
url,
385+
content=content,
373386
data=data,
374387
files=files,
375388
json=json,

httpx/_client.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
HeaderTypes,
4040
ProxiesTypes,
4141
QueryParamTypes,
42+
RequestContent,
4243
RequestData,
4344
RequestFiles,
4445
TimeoutTypes,
@@ -226,6 +227,7 @@ def stream(
226227
method: str,
227228
url: URLTypes,
228229
*,
230+
content: RequestContent = None,
229231
data: RequestData = None,
230232
files: RequestFiles = None,
231233
json: typing.Any = None,
@@ -249,6 +251,7 @@ def stream(
249251
request = self.build_request(
250252
method=method,
251253
url=url,
254+
content=content,
252255
data=data,
253256
files=files,
254257
json=json,
@@ -269,6 +272,7 @@ def build_request(
269272
method: str,
270273
url: URLTypes,
271274
*,
275+
content: RequestContent = None,
272276
data: RequestData = None,
273277
files: RequestFiles = None,
274278
json: typing.Any = None,
@@ -294,6 +298,7 @@ def build_request(
294298
return Request(
295299
method,
296300
url,
301+
content=content,
297302
data=data,
298303
files=files,
299304
json=json,
@@ -679,6 +684,7 @@ def request(
679684
method: str,
680685
url: URLTypes,
681686
*,
687+
content: RequestContent = None,
682688
data: RequestData = None,
683689
files: RequestFiles = None,
684690
json: typing.Any = None,
@@ -708,6 +714,7 @@ def request(
708714
request = self.build_request(
709715
method=method,
710716
url=url,
717+
content=content,
711718
data=data,
712719
files=files,
713720
json=json,
@@ -962,6 +969,7 @@ def post(
962969
self,
963970
url: URLTypes,
964971
*,
972+
content: RequestContent = None,
965973
data: RequestData = None,
966974
files: RequestFiles = None,
967975
json: typing.Any = None,
@@ -980,6 +988,7 @@ def post(
980988
return self.request(
981989
"POST",
982990
url,
991+
content=content,
983992
data=data,
984993
files=files,
985994
json=json,
@@ -995,6 +1004,7 @@ def put(
9951004
self,
9961005
url: URLTypes,
9971006
*,
1007+
content: RequestContent = None,
9981008
data: RequestData = None,
9991009
files: RequestFiles = None,
10001010
json: typing.Any = None,
@@ -1013,6 +1023,7 @@ def put(
10131023
return self.request(
10141024
"PUT",
10151025
url,
1026+
content=content,
10161027
data=data,
10171028
files=files,
10181029
json=json,
@@ -1028,6 +1039,7 @@ def patch(
10281039
self,
10291040
url: URLTypes,
10301041
*,
1042+
content: RequestContent = None,
10311043
data: RequestData = None,
10321044
files: RequestFiles = None,
10331045
json: typing.Any = None,
@@ -1046,6 +1058,7 @@ def patch(
10461058
return self.request(
10471059
"PATCH",
10481060
url,
1061+
content=content,
10491062
data=data,
10501063
files=files,
10511064
json=json,
@@ -1313,6 +1326,7 @@ async def request(
13131326
method: str,
13141327
url: URLTypes,
13151328
*,
1329+
content: RequestContent = None,
13161330
data: RequestData = None,
13171331
files: RequestFiles = None,
13181332
json: typing.Any = None,
@@ -1342,6 +1356,7 @@ async def request(
13421356
request = self.build_request(
13431357
method=method,
13441358
url=url,
1359+
content=content,
13451360
data=data,
13461361
files=files,
13471362
json=json,
@@ -1599,6 +1614,7 @@ async def post(
15991614
self,
16001615
url: URLTypes,
16011616
*,
1617+
content: RequestContent = None,
16021618
data: RequestData = None,
16031619
files: RequestFiles = None,
16041620
json: typing.Any = None,
@@ -1617,6 +1633,7 @@ async def post(
16171633
return await self.request(
16181634
"POST",
16191635
url,
1636+
content=content,
16201637
data=data,
16211638
files=files,
16221639
json=json,
@@ -1632,6 +1649,7 @@ async def put(
16321649
self,
16331650
url: URLTypes,
16341651
*,
1652+
content: RequestContent = None,
16351653
data: RequestData = None,
16361654
files: RequestFiles = None,
16371655
json: typing.Any = None,
@@ -1650,6 +1668,7 @@ async def put(
16501668
return await self.request(
16511669
"PUT",
16521670
url,
1671+
content=content,
16531672
data=data,
16541673
files=files,
16551674
json=json,
@@ -1665,6 +1684,7 @@ async def patch(
16651684
self,
16661685
url: URLTypes,
16671686
*,
1687+
content: RequestContent = None,
16681688
data: RequestData = None,
16691689
files: RequestFiles = None,
16701690
json: typing.Any = None,
@@ -1683,6 +1703,7 @@ async def patch(
16831703
return await self.request(
16841704
"PATCH",
16851705
url,
1706+
content=content,
16861707
data=data,
16871708
files=files,
16881709
json=json,

0 commit comments

Comments
 (0)