<h3 dir="auto">Describe the bug</h3>
<p dir="auto">The problem is basically the one described here:<br>
<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="413523205" data-permission-text="Title is private" data-url="https://github.com/tiangolo/fastapi/issues/51" data-hovercard-type="issue" data-hovercard-url="/tiangolo/fastapi/issues/51/hovercard?comment_id=522035784&amp;comment_type=issue_comment" href="https://github.com/tiangolo/fastapi/issues/51#issuecomment-522035784">#51 (comment)</a><br>
My fastapi app is behind a reverse proxy that forwards all requests for /api/v1/* and rewrites them to /*.<br>
The application itself doesn't know that but the FastAPI object which has openapi_prefix="/api/v1".</p>
<p dir="auto">If I have an endpoint</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="@app.get(&quot;/hello&quot;)
def foo():
    return &quot;hello&quot;"><pre class="notranslate"><span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-en">get</span>(<span class="pl-s">"/hello"</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">foo</span>():
    <span class="pl-k">return</span> <span class="pl-s">"hello"</span></pre></div>
<p dir="auto">and I query /api/v1/hello, it works fine. If I add an extra slash at the end, a redirect occurs but tries to send the user to /hello instead of /api/v1/hello.<br>
I'm not sure if it's a bug or if I don't use the app correctly. Maybe it would be simpler for me to make the fastapi app aware of the /api/v1 prefix and remove the rewrite rule? What do you think?</p>
<h3 dir="auto">To Reproduce</h3>
<p dir="auto">Behind a reverse proxy forwarding the requests for /api/v1/* and rewriting those to /*</p>
<ol dir="auto">
<li>Create a file with:</li>
</ol>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from fastapi import FastAPI

app = FastAPI(openapi_prefix=&quot;/api/v1&quot;)


@app.get(&quot;/hello&quot;)
def read_root():
    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-s1">app</span> <span class="pl-c1">=</span> <span class="pl-v">FastAPI</span>(<span class="pl-s1">openapi_prefix</span><span class="pl-c1">=</span><span class="pl-s">"/api/v1"</span>)


<span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-en">get</span>(<span class="pl-s">"/hello"</span>)</span>
<span class="pl-k">def</span> <span class="pl-en">read_root</span>():
    <span class="pl-k">return</span> {<span class="pl-s">"Hello"</span>: <span class="pl-s">"World"</span>}</pre></div>
<ol start="3" dir="auto">
<li>Open the browser and call the endpoint <code class="notranslate">/api/v1/hello/</code>.</li>
<li>It returns a 404 because there is a redirect to /hello.</li>
<li>But I expected the redirect to be to /api/v1/hello.</li>
</ol>
<h3 dir="auto">Expected behavior</h3>
<p dir="auto">The redirection shouldn't remove the openapi_prefix.</p>
<h3 dir="auto">Environment</h3>
<ul dir="auto">
<li>OS: Linux / Windows</li>
<li>FastAPI Version 0.52.0 from pip</li>
<li>python 3.7.4.</li>
</ul>
<h1 dir="auto">Schema is auto-added when using file uploads with no clear reason to why</h1>
<ul dir="auto">
<li>View template and re-review suggestions <g-emoji class="g-emoji" alias="white_check_mark" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/2705.png">✅</g-emoji></li>
<li>Try to find exiting issues/solutions <g-emoji class="g-emoji" alias="white_check_mark" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/2705.png">✅</g-emoji></li>
</ul>
<h2 dir="auto">Problem:</h2>
<p dir="auto">When adding a file upload using the FastAPI's <code class="notranslate">File</code> and <code class="notranslate">UploadFile</code> two schema's seem to be automatically added without any clear reason why and with seemingly no working way to replace/overwrite/remove them. As they don't provide any meaningful information for the consumers of my API I would like to replace/remove them <g-emoji class="g-emoji" alias="sweat_smile" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f605.png">😅</g-emoji><br>
<a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/49159860/109162955-13b04780-7779-11eb-8356-d832a09f8af0.png"><img src="https://user-images.githubusercontent.com/49159860/109162955-13b04780-7779-11eb-8356-d832a09f8af0.png" alt="image" style="max-width: 100%;"></a></p>
<h2 dir="auto">Questions</h2>
<ul dir="auto">
<li>
<p dir="auto">Is this intended behaviour? (As in, shouldn't the specified responses and/or response models take precedence?)</p>
<ul dir="auto">
<li>No -&gt; Ticket should be tagged with a <g-emoji class="g-emoji" alias="bug" fallback-src="https://github.githubassets.com/images/icons/emoji/unicode/1f41b.png">🐛</g-emoji></li>
</ul>
</li>
<li>
<p dir="auto">Is there a way to overwrite/remove these?</p>
<ul dir="auto">
<li><a href="https://fastapi.tiangolo.com/advanced/extending-openapi/#modify-the-openapi-schema" rel="nofollow">Yes!</a> (Answered by <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/NicolasRondon/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/NicolasRondon">@NicolasRondon</a>)</li>
</ul>
</li>
</ul>
<h2 dir="auto">Source</h2>
<p dir="auto"><code class="notranslate">src/main.py</code></p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from api.http.routers import ROUTERS
from api.settings import SETTINGS

# Setting up application logger
logging.basicConfig(level=logging.DEBUG)

# Initialize application with settings
app = FastAPI(**SETTINGS[&quot;app&quot;])

# Add the routers
[app.include_router(router) for router in ROUTERS]
# ..."><pre class="notranslate"><span class="pl-k">from</span> <span class="pl-s1">api</span>.<span class="pl-s1">http</span>.<span class="pl-s1">routers</span> <span class="pl-k">import</span> <span class="pl-v">ROUTERS</span>
<span class="pl-k">from</span> <span class="pl-s1">api</span>.<span class="pl-s1">settings</span> <span class="pl-k">import</span> <span class="pl-v">SETTINGS</span>

<span class="pl-c"># Setting up application logger</span>
<span class="pl-s1">logging</span>.<span class="pl-en">basicConfig</span>(<span class="pl-s1">level</span><span class="pl-c1">=</span><span class="pl-s1">logging</span>.<span class="pl-v">DEBUG</span>)

<span class="pl-c"># Initialize application with settings</span>
<span class="pl-s1">app</span> <span class="pl-c1">=</span> <span class="pl-v">FastAPI</span>(<span class="pl-c1">**</span><span class="pl-v">SETTINGS</span>[<span class="pl-s">"app"</span>])

<span class="pl-c"># Add the routers</span>
[<span class="pl-s1">app</span>.<span class="pl-en">include_router</span>(<span class="pl-s1">router</span>) <span class="pl-k">for</span> <span class="pl-s1">router</span> <span class="pl-c1">in</span> <span class="pl-v">ROUTERS</span>]
<span class="pl-c"># ...</span></pre></div>
<p dir="auto"><code class="notranslate">src/api/http/routers/file.py</code></p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="# ... imports
_dbucket = SETTINGS[&quot;backend&quot;][&quot;storage&quot;][&quot;default_bucket&quot;]
_dfile = SETTINGS[&quot;backend&quot;][&quot;storage&quot;][&quot;default_file&quot;]

router = APIRouter()

# ... Other routers

# router usage
@router.post(
    path=&quot;/file/upload&quot;,
    operation_id=&quot;api.http.routers.file.upload&quot;,
    tags=[&quot;Uploads &amp; Downloads&quot;],
    response_model=Result,
    responses=FileResponses.upload_direct)
async def upload_direct(
    name: str = _dfile, bucket: str = _dbucket, file: UploadFile = File(...)
):
    &quot;&quot;&quot;Admin/debugging call for direct file upload&quot;&quot;&quot;
    if StorageClient.lookup_file(name, bucket):
        raise HTTPException(
            status_code=409, detail=&quot;The file already exists&quot;
        )
    else:
        file.filename = name
        StorageClient.upload_direct(bucket, file)
        return Result(detail=[{&quot;msg&quot;: &quot;File uploaded sucessfully&quot;}])"><pre class="notranslate"><span class="pl-c"># ... imports</span>
<span class="pl-s1">_dbucket</span> <span class="pl-c1">=</span> <span class="pl-v">SETTINGS</span>[<span class="pl-s">"backend"</span>][<span class="pl-s">"storage"</span>][<span class="pl-s">"default_bucket"</span>]
<span class="pl-s1">_dfile</span> <span class="pl-c1">=</span> <span class="pl-v">SETTINGS</span>[<span class="pl-s">"backend"</span>][<span class="pl-s">"storage"</span>][<span class="pl-s">"default_file"</span>]

<span class="pl-s1">router</span> <span class="pl-c1">=</span> <span class="pl-v">APIRouter</span>()

<span class="pl-c"># ... Other routers</span>

<span class="pl-c"># router usage</span>
<span class="pl-en">@<span class="pl-s1">router</span>.<span class="pl-en">post</span>(</span>
<span class="pl-en">    <span class="pl-s1">path</span><span class="pl-c1">=</span><span class="pl-s">"/file/upload"</span>,</span>
<span class="pl-en">    <span class="pl-s1">operation_id</span><span class="pl-c1">=</span><span class="pl-s">"api.http.routers.file.upload"</span>,</span>
<span class="pl-en">    <span class="pl-s1">tags</span><span class="pl-c1">=</span>[<span class="pl-s">"Uploads &amp; Downloads"</span>],</span>
<span class="pl-en">    <span class="pl-s1">response_model</span><span class="pl-c1">=</span><span class="pl-v">Result</span>,</span>
<span class="pl-en">    <span class="pl-s1">responses</span><span class="pl-c1">=</span><span class="pl-v">FileResponses</span>.<span class="pl-s1">upload_direct</span>)</span>
<span class="pl-k">async</span> <span class="pl-k">def</span> <span class="pl-en">upload_direct</span>(
    <span class="pl-s1">name</span>: <span class="pl-s1">str</span> <span class="pl-c1">=</span> <span class="pl-s1">_dfile</span>, <span class="pl-s1">bucket</span>: <span class="pl-s1">str</span> <span class="pl-c1">=</span> <span class="pl-s1">_dbucket</span>, <span class="pl-s1">file</span>: <span class="pl-v">UploadFile</span> <span class="pl-c1">=</span> <span class="pl-v">File</span>(...)
):
    <span class="pl-s">"""Admin/debugging call for direct file upload"""</span>
    <span class="pl-k">if</span> <span class="pl-v">StorageClient</span>.<span class="pl-en">lookup_file</span>(<span class="pl-s1">name</span>, <span class="pl-s1">bucket</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">409</span>, <span class="pl-s1">detail</span><span class="pl-c1">=</span><span class="pl-s">"The file already exists"</span>
        )
    <span class="pl-k">else</span>:
        <span class="pl-s1">file</span>.<span class="pl-s1">filename</span> <span class="pl-c1">=</span> <span class="pl-s1">name</span>
        <span class="pl-v">StorageClient</span>.<span class="pl-en">upload_direct</span>(<span class="pl-s1">bucket</span>, <span class="pl-s1">file</span>)
        <span class="pl-k">return</span> <span class="pl-v">Result</span>(<span class="pl-s1">detail</span><span class="pl-c1">=</span>[{<span class="pl-s">"msg"</span>: <span class="pl-s">"File uploaded sucessfully"</span>}])</pre></div>
<p dir="auto"><code class="notranslate">src/api/models/generic.py</code></p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from typing import List
from pydantic import BaseModel


class Message(BaseModel):
    &quot;&quot;&quot;Generic message model&quot;&quot;&quot;
    msg: str


class Result(BaseModel):
    &quot;&quot;&quot;File/bucket generic result&quot;&quot;&quot;
    detail: List[Message]"><pre class="notranslate"><span class="pl-k">from</span> <span class="pl-s1">typing</span> <span class="pl-k">import</span> <span class="pl-v">List</span>
<span class="pl-k">from</span> <span class="pl-s1">pydantic</span> <span class="pl-k">import</span> <span class="pl-v">BaseModel</span>


<span class="pl-k">class</span> <span class="pl-v">Message</span>(<span class="pl-v">BaseModel</span>):
    <span class="pl-s">"""Generic message model"""</span>
    <span class="pl-s1">msg</span>: <span class="pl-s1">str</span>


<span class="pl-k">class</span> <span class="pl-v">Result</span>(<span class="pl-v">BaseModel</span>):
    <span class="pl-s">"""File/bucket generic result"""</span>
    <span class="pl-s1">detail</span>: <span class="pl-v">List</span>[<span class="pl-v">Message</span>]</pre></div>
<h2 dir="auto">Additional information for reproduction</h2>
<ul dir="auto">
<li>Python version: 3.8.7 64bit</li>
<li><code class="notranslate">FileResponses</code> is just a container class holding responses as described <a href="https://fastapi.tiangolo.com/advanced/additional-responses/" rel="nofollow">here</a> in docs</li>
<li><a href="https://github.com/tiangolo/fastapi/files/6043511/requirements-dump.txt">requirements-dump.txt</a></li>
</ul>