Empty request body for non-urlencoded content when using SIGNATURE_TYPE_QUERY OAuth signature type
Hello,
I have encountered an issue with the HTTPX Authlib Auth plugin when using the SIGNATURE_TYPE_QUERY OAuth signature type. The issue appears when the request body is non-urlencoded content, resulting in an empty request body for PUT requests.
In the auth_flow method, the body is used when returning self.prepare:
def auth_flow(self, request: Request) -> typing.Generator[Request, Response, None]:
url, headers, body = self.prepare(
request.method, str(request.url), request.headers, request.content)
headers['Content-Length'] = str(len(body))
yield build_request(url=url, headers=headers, body=body, initial_request=request)
However, in the prepare method, the body is set to empty at this line:
body = b''
Here is the relevant part of the prepare method:
def prepare(self, method, uri, headers, body):
...
if CONTENT_TYPE_FORM_URLENCODED in content_type:
headers['Content-Type'] = CONTENT_TYPE_FORM_URLENCODED
uri, headers, body = self.sign(method, uri, headers, body)
elif self.force_include_body:
# To allow custom clients to work on non form encoded bodies.
uri, headers, body = self.sign(method, uri, headers, body)
else:
# Omit body data in the signing of non form-encoded requests
uri, headers, _ = self.sign(method, uri, headers, b'')
body = b''
return uri, headers, body
This leads to an empty request body for PUT requests with the SIGNATURE_TYPE_QUERY OAuth signature type and non-urlencoded content.
To Reproduce
A minimal example to reproduce the behavior:
import httpx
from authlib.integrations.httpx_client import OAuth1Auth
async def main():
auth = OAuth1Auth(
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
access_token="YOUR_ACCESS_TOKEN",
token_secret="YOUR_TOKEN_SECRET",
signature_type="QUERY"
)
url = "https://api.example.com/resource"
headers = {"Content-Type": "application/json"}
data = {"key": "value"}
async with httpx.AsyncClient() as client:
response = await client.put(url, json=data, headers=headers, auth=auth)
print(response.text)
await main()
Expected behavior
When making a PUT request with non-urlencoded content and using the SIGNATURE_TYPE_QUERY OAuth signature type, I expect the request body to be properly included.
Environment:
- OS: macOS 11.2.3
- Python Version: 3.8
- Authlib Version: 1.2.0
Additional context
Seeing the same behavior with POST requests & JSON content. removing the body = b'' line referenced above fixes the issue for me. Happy to PR if that would be helpful