diff --git a/docs/api.md b/docs/api.md
index 3889d8c..c63d4ec 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -38,6 +38,13 @@
     :docstring:
     :members: headers cookies params request get head options post put patch delete build_request send close
 
+## `AsyncClient`
+
+::: httpx.AsyncClient
+    :docstring:
+    :members: headers cookies params request get head options post put patch delete build_request send
+
+
 ## `Response`
 
 *An HTTP response.*
diff --git a/httpx/_client.py b/httpx/_client.py
index 2a310e2..3976522 100644
--- a/httpx/_client.py
+++ b/httpx/_client.py
@@ -426,7 +426,7 @@ class Client(BaseClient):
     request URLs.
     * **dispatch** - *(optional)* A dispatch class to use for sending requests
     over the network.
-    * **app** - *(optional)* An ASGI application to send requests to,
+    * **app** - *(optional)* An WSGI application to send requests to,
     rather than sending actual network requests.
     * **trust_env** - *(optional)* Enables or disables usage of environment
     variables for configuration.
diff --git a/httpx/_content_streams.py b/httpx/_content_streams.py
index afffed3..dd6c51f 100644
--- a/httpx/_content_streams.py
+++ b/httpx/_content_streams.py
@@ -71,8 +71,6 @@ class ByteStream(ContentStream):
         self.body = body.encode("utf-8") if isinstance(body, str) else body
 
     def get_headers(self) -> typing.Dict[str, str]:
-        if not self.body:
-            return {}
         content_length = str(len(self.body))
         return {"Content-Length": content_length}
 

Sync client fails on ASGI apps with unhelpful traceback
I tried using httpx with with an ASGI app in the way that was implied by the docs.  It throws an error that feels like a problem with httpx, as FastAPI is currently being used in production in other ways.  If you confirm that this is a bug in httpx, I'm willing (and probably capable) to fix it and submit a patch.

```
import httpx
from fastapi import FastAPI

app = FastAPI()


@app.get("/users/{user_id}")
async def read_user(user_id: str):
    return {'user_id': user_id}

with httpx.Client(app=app) as client:
    response = client.get("http://www.example.com/users/foo")
```

Throws the error:
```
Traceback (most recent call last):
  File "temp.py", line 12, in <module>
    response = client.get("http://www.example.com/users/foo")
  File "/Users/singletoned/.envs/testino/lib/python3.7/site-packages/httpx/_client.py", line 714, in get
    timeout=timeout,
  File "/Users/singletoned/.envs/testino/lib/python3.7/site-packages/httpx/_client.py", line 571, in request
    request, auth=auth, allow_redirects=allow_redirects, timeout=timeout,
  File "/Users/singletoned/.envs/testino/lib/python3.7/site-packages/httpx/_client.py", line 591, in send
    request, auth=auth, timeout=timeout, allow_redirects=allow_redirects,
  File "/Users/singletoned/.envs/testino/lib/python3.7/site-packages/httpx/_client.py", line 618, in send_handling_redirects
    request, auth=auth, timeout=timeout, history=history
  File "/Users/singletoned/.envs/testino/lib/python3.7/site-packages/httpx/_client.py", line 654, in send_handling_auth
    response = self.send_single_request(request, timeout)
  File "/Users/singletoned/.envs/testino/lib/python3.7/site-packages/httpx/_client.py", line 678, in send_single_request
    response = dispatcher.send(request, timeout=timeout)
  File "/Users/singletoned/.envs/testino/lib/python3.7/site-packages/httpx/_dispatch/wsgi.py", line 90, in send
    result = self.app(environ, start_response)
TypeError: __call__() missing 1 required positional argument: 'send'
```
diff --git a/tests/client/test_headers.py b/tests/client/test_headers.py
index 22b0ba1..5c4dbb4 100755
--- a/tests/client/test_headers.py
+++ b/tests/client/test_headers.py
@@ -40,6 +40,7 @@ async def test_client_header():
             "accept": "*/*",
             "accept-encoding": "gzip, deflate, br",
             "connection": "keep-alive",
+            "content-length": "0",
             "example-header": "example-value",
             "host": "example.org",
             "user-agent": f"python-httpx/{__version__}",
@@ -61,6 +62,7 @@ async def test_header_merge():
             "accept": "*/*",
             "accept-encoding": "gzip, deflate, br",
             "connection": "keep-alive",
+            "content-length": "0",
             "host": "example.org",
             "user-agent": "python-myclient/0.2.1",
             "x-auth-token": "FooBarBazToken",
@@ -82,6 +84,7 @@ async def test_header_merge_conflicting_headers():
             "accept": "*/*",
             "accept-encoding": "gzip, deflate, br",
             "connection": "keep-alive",
+            "content-length": "0",
             "host": "example.org",
             "user-agent": f"python-httpx/{__version__}",
             "x-auth-token": "BazToken",
@@ -105,6 +108,7 @@ async def test_header_update():
             "accept": "*/*",
             "accept-encoding": "gzip, deflate, br",
             "connection": "keep-alive",
+            "content-length": "0",
             "host": "example.org",
             "user-agent": f"python-httpx/{__version__}",
         }
@@ -117,6 +121,7 @@ async def test_header_update():
             "accept-encoding": "gzip, deflate, br",
             "another-header": "AThing",
             "connection": "keep-alive",
+            "content-length": "0",
             "host": "example.org",
             "user-agent": "python-myclient/0.2.1",
         }
@@ -147,6 +152,7 @@ async def test_host_with_auth_and_port_in_url():
             "accept": "*/*",
             "accept-encoding": "gzip, deflate, br",
             "connection": "keep-alive",
+            "content-length": "0",
             "host": "example.org",
             "user-agent": f"python-httpx/{__version__}",
             "authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQ=",
@@ -171,6 +177,7 @@ async def test_host_with_non_default_port_in_url():
             "accept": "*/*",
             "accept-encoding": "gzip, deflate, br",
             "connection": "keep-alive",
+            "content-length": "0",
             "host": "example.org:123",
             "user-agent": f"python-httpx/{__version__}",
             "authorization": "Basic dXNlcm5hbWU6cGFzc3dvcmQ=",
diff --git a/tests/client/test_redirects.py b/tests/client/test_redirects.py
index 190ff09..63403a6 100644
--- a/tests/client/test_redirects.py
+++ b/tests/client/test_redirects.py
@@ -279,7 +279,7 @@ async def test_body_redirect():
     response = await client.post(url, data=data)
     assert response.url == URL("https://example.org/redirect_body_target")
     assert response.json()["body"] == "Example request body"
-    assert "content-length" in response.json()["headers"]
+    assert response.json()["headers"]["content-length"] == "20"
 
 
 @pytest.mark.usefixtures("async_environment")
@@ -293,7 +293,7 @@ async def test_no_body_redirect():
     response = await client.post(url, data=data)
     assert response.url == URL("https://example.org/redirect_body_target")
     assert response.json()["body"] == ""
-    assert "content-length" not in response.json()["headers"]
+    assert response.json()["headers"]["content-length"] == "0"
 
 
 @pytest.mark.usefixtures("async_environment")
diff --git a/tests/models/test_requests.py b/tests/models/test_requests.py
index c72e0af..0461394 100644
--- a/tests/models/test_requests.py
+++ b/tests/models/test_requests.py
@@ -10,7 +10,7 @@ def test_request_repr():
 
 def test_no_content():
     request = httpx.Request("GET", "http://example.org")
-    assert "Content-Length" not in request.headers
+    assert request.headers["Content-Length"] == "0"
 
 
 def test_content_length_header():
diff --git a/tests/test_content_streams.py b/tests/test_content_streams.py
index c5eb961..84999ef 100644
--- a/tests/test_content_streams.py
+++ b/tests/test_content_streams.py
@@ -25,7 +25,9 @@ async def test_empty_content():
     async_content = b"".join([part async for part in stream])
 
     assert stream.can_replay()
-    assert stream.get_headers() == {}
+    assert stream.get_headers() == {
+        "Content-Length": "0",
+    }
     assert sync_content == b""
     assert async_content == b""
 
@@ -196,7 +198,9 @@ async def test_empty_request():
     async_content = b"".join([part async for part in stream])
 
     assert stream.can_replay()
-    assert stream.get_headers() == {}
+    assert stream.get_headers() == {
+        "Content-Length": "0",
+    }
     assert sync_content == b""
     assert async_content == b""
 

pip install -e .
parse_log_pytest
requirements.txt
pytest pytest-asyncio pytest-trio pytest-cov pytest-xdist pytest-mock
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
aspy.refactor-imports==3.0.2
attrs==25.3.0
autoflake==2.3.1
babel==2.17.0
backrefs==5.8
black==25.1.0
brotlipy==0.7.0
certifi==2025.1.31
cffi==1.17.1
chardet==3.0.4
charset-normalizer==3.4.1
click==8.1.8
colorama==0.4.6
coverage==7.8.0
cryptography==44.0.2
exceptiongroup==1.2.2
execnet==2.1.1
flake8==7.2.0
flake8-bugbear==24.12.12
flake8-pie==0.16.0
ghp-import==2.1.0
h11==0.9.0
h2==3.2.0
hpack==3.0.0
hstspreload==2025.1.1
-e git+https://github.com/encode/httpx.git@21f533774f87292c2381376eb40f3216a48eee06#egg=httpx
hyperframe==5.2.0
idna==2.10
importlib_metadata==8.6.1
iniconfig==2.1.0
isort==6.0.1
Jinja2==3.1.6
Markdown==3.7
MarkupSafe==3.0.2
mccabe==0.7.0
mergedeep==1.3.4
mkautodoc==0.2.0
mkdocs==1.6.1
mkdocs-get-deps==0.2.0
mkdocs-material==9.6.10
mkdocs-material-extensions==1.3.1
mypy==1.15.0
mypy-extensions==1.0.0
outcome==1.3.0.post0
packaging==24.2
paginate==0.5.7
pathspec==0.12.1
platformdirs==4.3.7
pluggy==1.5.0
pycodestyle==2.13.0
pycparser==2.22
pyflakes==3.3.2
Pygments==2.19.1
pymdown-extensions==10.14.3
pytest==8.3.5
pytest-asyncio==0.26.0
pytest-cov==6.0.0
pytest-mock==3.14.0
pytest-trio==0.8.0
pytest-xdist==3.6.1
python-dateutil==2.9.0.post0
PyYAML==6.0.2
pyyaml_env_tag==0.1
requests==2.32.3
rfc3986==1.5.0
seed-isort-config==2.2.0
six==1.17.0
sniffio==1.3.1
sortedcontainers==2.4.0
tomli==2.2.1
trio==0.29.0
trustme==1.2.1
typing_extensions==4.13.0
urllib3==1.26.20
uvicorn==0.34.0
watchdog==6.0.0
zipp==3.21.0

name: httpx
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - tzdata=2025a=h04d1e81_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - aspy-refactor-imports==3.0.2
      - attrs==25.3.0
      - autoflake==2.3.1
      - babel==2.17.0
      - backrefs==5.8
      - black==25.1.0
      - brotlipy==0.7.0
      - certifi==2025.1.31
      - cffi==1.17.1
      - chardet==3.0.4
      - charset-normalizer==3.4.1
      - click==8.1.8
      - colorama==0.4.6
      - coverage==7.8.0
      - cryptography==44.0.2
      - exceptiongroup==1.2.2
      - execnet==2.1.1
      - flake8==7.2.0
      - flake8-bugbear==24.12.12
      - flake8-pie==0.16.0
      - ghp-import==2.1.0
      - h11==0.9.0
      - h2==3.2.0
      - hpack==3.0.0
      - hstspreload==2025.1.1
      - hyperframe==5.2.0
      - idna==2.10
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - isort==6.0.1
      - jinja2==3.1.6
      - markdown==3.7
      - markupsafe==3.0.2
      - mccabe==0.7.0
      - mergedeep==1.3.4
      - mkautodoc==0.2.0
      - mkdocs==1.6.1
      - mkdocs-get-deps==0.2.0
      - mkdocs-material==9.6.10
      - mkdocs-material-extensions==1.3.1
      - mypy==1.15.0
      - mypy-extensions==1.0.0
      - outcome==1.3.0.post0
      - packaging==24.2
      - paginate==0.5.7
      - pathspec==0.12.1
      - platformdirs==4.3.7
      - pluggy==1.5.0
      - pycodestyle==2.13.0
      - pycparser==2.22
      - pyflakes==3.3.2
      - pygments==2.19.1
      - pymdown-extensions==10.14.3
      - pytest==8.3.5
      - pytest-asyncio==0.26.0
      - pytest-cov==6.0.0
      - pytest-mock==3.14.0
      - pytest-trio==0.8.0
      - pytest-xdist==3.6.1
      - python-dateutil==2.9.0.post0
      - pyyaml==6.0.2
      - pyyaml-env-tag==0.1
      - requests==2.32.3
      - rfc3986==1.5.0
      - seed-isort-config==2.2.0
      - six==1.17.0
      - sniffio==1.3.1
      - sortedcontainers==2.4.0
      - tomli==2.2.1
      - trio==0.29.0
      - trustme==1.2.1
      - typing-extensions==4.13.0
      - urllib3==1.26.20
      - uvicorn==0.34.0
      - watchdog==6.0.0
      - zipp==3.21.0
prefix: /opt/conda/envs/httpx

tests/client/test_headers.py::test_client_header tests/client/test_headers.py::test_header_merge tests/client/test_headers.py::test_header_merge_conflicting_headers tests/client/test_headers.py::test_header_update tests/client/test_headers.py::test_host_with_auth_and_port_in_url tests/client/test_headers.py::test_host_with_non_default_port_in_url tests/client/test_redirects.py::test_no_body_redirect[asyncio] tests/client/test_redirects.py::test_no_body_redirect[trio] tests/models/test_requests.py::test_no_content tests/test_content_streams.py::test_empty_content tests/test_content_streams.py::test_empty_request
tests/client/test_headers.py::test_header_does_not_exist tests/client/test_redirects.py::test_no_redirect[asyncio] tests/client/test_redirects.py::test_no_redirect[trio] tests/client/test_redirects.py::test_redirect_301[asyncio] tests/client/test_redirects.py::test_redirect_301[trio] tests/client/test_redirects.py::test_redirect_302[asyncio] tests/client/test_redirects.py::test_redirect_302[trio] tests/client/test_redirects.py::test_redirect_303[asyncio] tests/client/test_redirects.py::test_redirect_303[trio] tests/client/test_redirects.py::test_disallow_redirects[asyncio] tests/client/test_redirects.py::test_disallow_redirects[trio] tests/client/test_redirects.py::test_relative_redirect[asyncio] tests/client/test_redirects.py::test_relative_redirect[trio] tests/client/test_redirects.py::test_malformed_redirect[asyncio] tests/client/test_redirects.py::test_malformed_redirect[trio] tests/client/test_redirects.py::test_no_scheme_redirect[asyncio] tests/client/test_redirects.py::test_no_scheme_redirect[trio] tests/client/test_redirects.py::test_fragment_redirect[asyncio] tests/client/test_redirects.py::test_fragment_redirect[trio] tests/client/test_redirects.py::test_multiple_redirects[asyncio] tests/client/test_redirects.py::test_multiple_redirects[trio] tests/client/test_redirects.py::test_too_many_redirects[asyncio] tests/client/test_redirects.py::test_too_many_redirects[trio] tests/client/test_redirects.py::test_too_many_redirects_calling_next[asyncio] tests/client/test_redirects.py::test_too_many_redirects_calling_next[trio] tests/client/test_redirects.py::test_redirect_loop[asyncio] tests/client/test_redirects.py::test_redirect_loop[trio] tests/client/test_redirects.py::test_cross_domain_redirect[asyncio] tests/client/test_redirects.py::test_cross_domain_redirect[trio] tests/client/test_redirects.py::test_same_domain_redirect[asyncio] tests/client/test_redirects.py::test_same_domain_redirect[trio] tests/client/test_redirects.py::test_body_redirect[asyncio] tests/client/test_redirects.py::test_body_redirect[trio] tests/client/test_redirects.py::test_can_stream_if_no_redirect[asyncio] tests/client/test_redirects.py::test_can_stream_if_no_redirect[trio] tests/client/test_redirects.py::test_cannot_redirect_streaming_body[asyncio] tests/client/test_redirects.py::test_cannot_redirect_streaming_body[trio] tests/client/test_redirects.py::test_cross_subdomain_redirect[asyncio] tests/client/test_redirects.py::test_cross_subdomain_redirect[trio] tests/client/test_redirects.py::test_redirect_cookie_behavior[asyncio] tests/client/test_redirects.py::test_redirect_cookie_behavior[trio] tests/models/test_requests.py::test_request_repr tests/models/test_requests.py::test_content_length_header tests/models/test_requests.py::test_url_encoded_data tests/models/test_requests.py::test_json_encoded_data tests/models/test_requests.py::test_read_and_stream_data tests/models/test_requests.py::test_aread_and_stream_data tests/models/test_requests.py::test_cannot_access_content_without_read tests/models/test_requests.py::test_transfer_encoding_header tests/models/test_requests.py::test_override_host_header tests/models/test_requests.py::test_override_accept_encoding_header tests/models/test_requests.py::test_override_content_length_header tests/models/test_requests.py::test_url tests/models/test_requests.py::test_invalid_urls tests/test_content_streams.py::test_base_content tests/test_content_streams.py::test_bytes_content tests/test_content_streams.py::test_iterator_content tests/test_content_streams.py::test_aiterator_content tests/test_content_streams.py::test_json_content tests/test_content_streams.py::test_urlencoded_content tests/test_content_streams.py::test_multipart_files_content tests/test_content_streams.py::test_multipart_data_and_files_content tests/test_content_streams.py::test_invalid_argument
httpx/_content_streams.py docs/api.md httpx/_client.py
httpx/_content_streams.py docs/api.md httpx/_client.py