<h3 dir="auto">First check</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I added a very descriptive title to this issue.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I used the GitHub search to find a similar issue and didn't find it.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I searched the FastAPI documentation, with the integrated search.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already searched in Google "How to X in FastAPI" and didn't find any information.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already read and followed all the tutorial in the docs and didn't find an answer.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already checked if it is not related to FastAPI but to <a href="https://github.com/samuelcolvin/pydantic">Pydantic</a>.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already checked if it is not related to FastAPI but to <a href="https://github.com/swagger-api/swagger-ui">Swagger UI</a>.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already checked if it is not related to FastAPI but to <a href="https://github.com/Redocly/redoc">ReDoc</a>.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> After submitting this, I commit to one of:
<ul dir="auto">
<li>Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.</li>
<li>I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.</li>
<li>Implement a Pull Request for a confirmed bug.</li>
</ul>
</li>
</ul>
<h3 dir="auto">Description</h3>
<p dir="auto">Hello! I have noticed that fastAPI's HTTP 204's <code class="notranslate">No Content</code> response does not appear to conform to the HTTP spec by default. Per the HTTP spec: <a href="https://tools.ietf.org/html/rfc2616#section-10.2.5" rel="nofollow">https://tools.ietf.org/html/rfc2616#section-10.2.5</a>:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="   The 204 response MUST NOT include a message-body, and thus is always
   terminated by the first empty line after the header fields."><pre class="notranslate"><code class="notranslate">   The 204 response MUST NOT include a message-body, and thus is always
   terminated by the first empty line after the header fields.
</code></pre></div>
<p dir="auto">It appears that fastapi is attempting to serialize as a JSON, and thus adding data to the message body. Here is an example that you can use to reproduce:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from fastapi import FastAPI, HTTPException

app = FastAPI()

@app.get(&quot;/&quot;)
def read_root():
    raise HTTPException(status_code=204)"><pre class="notranslate"><span class="pl-k">from</span> <span class="pl-s1">fastapi</span> <span class="pl-k">import</span> <span class="pl-v">FastAPI</span>, <span class="pl-v">HTTPException</span>

<span class="pl-s1">app</span> <span class="pl-c1">=</span> <span class="pl-v">FastAPI</span>()

<span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-en">get</span>(<span class="pl-s">"/"</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">read_root</span>():
    <span class="pl-k">raise</span> <span class="pl-v">HTTPException</span>(<span class="pl-s1">status_code</span><span class="pl-c1">=</span><span class="pl-c1">204</span>)</pre></div>
<p dir="auto">Curling this will result in:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="curl -v localhost:8000/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
&gt; GET / HTTP/1.1
&gt; Host: 127.0.0.1:8000
&gt; User-Agent: curl/7.64.1
&gt; Accept: */*
&gt; 
&lt; HTTP/1.1 204 No Content
&lt; date: Mon, 29 Mar 2021 20:28:47 GMT
&lt; server: uvicorn
&lt; content-length: 23
&lt; content-type: application/json
&lt; 
* Excess found in a non pipelined read: excess = 23 url = / (zero-length body)
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0"><pre class="notranslate"><code class="notranslate">curl -v localhost:8000/
*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 8000 (#0)
&gt; GET / HTTP/1.1
&gt; Host: 127.0.0.1:8000
&gt; User-Agent: curl/7.64.1
&gt; Accept: */*
&gt; 
&lt; HTTP/1.1 204 No Content
&lt; date: Mon, 29 Mar 2021 20:28:47 GMT
&lt; server: uvicorn
&lt; content-length: 23
&lt; content-type: application/json
&lt; 
* Excess found in a non pipelined read: excess = 23 url = / (zero-length body)
* Connection #0 to host 127.0.0.1 left intact
* Closing connection 0
</code></pre></div>
<p dir="auto">This line indicates the issue:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="* Excess found in a non pipelined read: excess = 23 url = / (zero-length body)"><pre class="notranslate"><code class="notranslate">* Excess found in a non pipelined read: excess = 23 url = / (zero-length body)
</code></pre></div>
<p dir="auto">It looks as though it's adding the following to the body:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="{&quot;detail&quot;:&quot;No Content&quot;}"><pre class="notranslate"><code class="notranslate">{"detail":"No Content"}
</code></pre></div>
<h3 dir="auto">Expected Behavior</h3>
<p dir="auto">The expected behavior is to not return anything in the body. This behavior should be the default when handling <code class="notranslate">HTTPException</code> of a status code of <code class="notranslate">204</code>.</p>
<p dir="auto">The current behavior can cause issues if you have your service being fronted with a proxy that strongly enforces the HTTP spec.</p>
<p dir="auto">I don't have time today to attempt to fix, but would be happy to.</p>
<h3 dir="auto">Environment</h3>
<ul dir="auto">
<li>OS: [e.g. Linux / Windows / macOS]: macOS</li>
<li>FastAPI Version [e.g. 0.3.0]: 0.63.0</li>
<li>Python version: 3.8.5</li>
</ul>
<h3 dir="auto">First check</h3>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I added a very descriptive title to this issue.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I used the GitHub search to find a similar issue and didn't find it.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I searched the FastAPI documentation, with the integrated search.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already searched in Google "How to X in FastAPI" and didn't find any information.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already read and followed all the tutorial in the docs and didn't find an answer.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already checked if it is not related to FastAPI but to <a href="https://github.com/samuelcolvin/pydantic">Pydantic</a>.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already checked if it is not related to FastAPI but to <a href="https://github.com/swagger-api/swagger-ui">Swagger UI</a>.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I already checked if it is not related to FastAPI but to <a href="https://github.com/Redocly/redoc">ReDoc</a>.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> After submitting this, I commit to one of:
<ul dir="auto">
<li>Read open issues with questions until I find 2 issues where I can help someone and add a comment to help there.</li>
<li>I already hit the "watch" button in this repository to receive notifications and I commit to help at least 2 people that ask questions in the future.</li>
<li>Implement a Pull Request for a confirmed bug.</li>
</ul>
</li>
</ul>

<h3 dir="auto">Example</h3>
<p dir="auto">Here's a self-contained, <a href="https://stackoverflow.com/help/minimal-reproducible-example" rel="nofollow">minimal, reproducible, example</a> with my use case:</p>

<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from fastapi import FastAPI, HTTPException

app = FastAPI()


@app.get(&quot;/&quot;)
def read_root(gimme_coffee: bool = False):
    if gimme_coffee:
        raise HTTPException(status_code=418, detail=&quot;I'm a teapot.&quot;)
    return {&quot;Hello&quot;: &quot;World&quot;}"><pre class="notranslate"><span class="pl-k">from</span> <span class="pl-s1">fastapi</span> <span class="pl-k">import</span> <span class="pl-v">FastAPI</span>, <span class="pl-v">HTTPException</span>

<span class="pl-s1">app</span> <span class="pl-c1">=</span> <span class="pl-v">FastAPI</span>()


<span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-en">get</span>(<span class="pl-s">"/"</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">read_root</span>(<span class="pl-s1">gimme_coffee</span>: <span class="pl-s1">bool</span> <span class="pl-c1">=</span> <span class="pl-c1">False</span>):
    <span class="pl-k">if</span> <span class="pl-s1">gimme_coffee</span>:
        <span class="pl-k">raise</span> <span class="pl-v">HTTPException</span>(<span class="pl-s1">status_code</span><span class="pl-c1">=</span><span class="pl-c1">418</span>, <span class="pl-s1">detail</span><span class="pl-c1">=</span><span class="pl-s">"I'm a teapot."</span>)
    <span class="pl-k">return</span> {<span class="pl-s">"Hello"</span>: <span class="pl-s">"World"</span>}</pre></div>
<h3 dir="auto">Description</h3>

<ul dir="auto">
<li>Open the browser and call the endpoint <code class="notranslate">/docs</code></li>
<li>Note that the only listed response codes are 200 and 422</li>
<li>Execute the route with <code class="notranslate">gimme_coffee</code> set to true and note that it returns a 418 status code</li>
</ul>
<p dir="auto">How do I set the status code for 418 in the OpenAPI docs? I was expecting to be able to pass in a list of possible HTTPExceptions and have them be automatically converted, but there does not appear to be any way to do that. The closest thing I found was <a href="https://fastapi.tiangolo.com/advanced/additional-status-codes/" rel="nofollow">Additional Status Codes</a> but that seemed at best tangentially relevant since I am raising HTTPExceptions, not looking to build out a custom exception JSON response.</p>
<p dir="auto">Properly documenting error states is just as important as documenting the success state. I really hope FastAPI provides an easy way to do this.</p>
<h3 dir="auto">Environment</h3>
<ul dir="auto">
<li>OS: Linux (Docker container using standard python-3.8 image)</li>
<li>FastAPI Version: 0.61.1</li>
<li>Python version: 3.8.5</li>
</ul>