Skip to content

Refine headers behaviour for Request() and client.build_request() #1226

Closed

Description

@lovelydinosaur

Currently Request() auto-generates a bunch of headers on __init__. Having thought about it for a bit I can see some refinements we could make here to:

  • Give users a bit more control over the default headers, such as allowing them to remove the User-Agent header.
  • Make Request() more generally useful, so that it only auto sets mandatory headers.

Rather than set the following headings on Request, we should instead include them on client.headers...

  • User-Agent: python-httpx/1.2.3
  • Accept: */*
  • Accept-Encoding: gzip, deflate
  • Connection: keep-alive

When passing Client(headers={...}) or setting client.headers = {} we should give precedence to explicitly set headers, but should include these defaults if they're not otherwise set.

# Create a client, with a custom Accept header.
# Other automatic headers are still included.
client = httpx.Client(headers={'Accept': 'application/json, */*;q=0.8'}

Or...

client = httpx.Client()

# Set a custom Accept header.
# Other automatic headers are still included.
client.headers = {'Accept': 'application/json, */*;q=0.8'}

If a user wants to actually remove one of these, they can do so by explicitly deleting it, eg...

# Create a client, without a User-Agent header.
client = httpx.Client()
del client.headers['User-Agent']

The recommended way of creating a request instance will continue to be client.build_request(...), but we'll want to highlight that more clearly, as instantiating a plain Request() instance will then give you a more basic set of behaviour by only auto-setting mandatory headers, and leaving everything else up to the user...

  • Set a Host header, if the request URL is an absolute URL.
  • Requests that mandate a body will always include either a Content-Length or Transfer-Encoding header.

Both of those cases will defer to any explicitly included header if one exists, and only auto set if those mandatory headers are omitted.

Also .prepare_headers() should become a private method.

This all ends up being beneficial, because users still get all the regular convenience of client.build_request(), but there's also a plainer style for creating Request() instances with complete control over the headers which doesn't make any assumptions about auto-including a set of default headers.

(Somewhat refs #1091)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions