<p dir="auto">When JSON data is send in a POST (or PUT) body, if you don't consume this data, they appear in the method string of the next request and results in a 405 Method Not Allowed response.</p>
<p dir="auto">This example code reproduces the error.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="from flask import Flask, request, jsonify

app = Flask(__name__)

@app.post(&quot;/test_ajax&quot;)
def test_ajax():
    return jsonify({&quot;hello&quot;: &quot;world&quot;})

@app.get(&quot;/test&quot;)
def test():
    return (
        &quot;&lt;a href='javascript:test();'&gt;Test&lt;/a&gt;&quot;
        &quot;&lt;script&gt;&quot;
        &quot;function test() {&quot;
        &quot;    fetch('/test_ajax', {&quot;
        &quot;        method: 'POST',&quot;
        &quot;        headers: {'Content-Type': 'application/json'},&quot;
        &quot;        body: JSON.stringify({'foo': 'bar'})&quot;
        &quot;    });&quot;
        &quot;}&quot;
        &quot;&lt;/script&gt;&quot;
    )"><pre class="notranslate"><code class="notranslate">from flask import Flask, request, jsonify

app = Flask(__name__)

@app.post("/test_ajax")
def test_ajax():
    return jsonify({"hello": "world"})

@app.get("/test")
def test():
    return (
        "&lt;a href='javascript:test();'&gt;Test&lt;/a&gt;"
        "&lt;script&gt;"
        "function test() {"
        "    fetch('/test_ajax', {"
        "        method: 'POST',"
        "        headers: {'Content-Type': 'application/json'},"
        "        body: JSON.stringify({'foo': 'bar'})"
        "    });"
        "}"
        "&lt;/script&gt;"
    )
</code></pre></div>
<p dir="auto">This is the log result</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content=" * Detected change in 'app.py', reloading
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 128-473-016
172.27.0.1 - - [21/Apr/2022 12:55:39] &quot;GET /test HTTP/1.1&quot; 200 -
172.27.0.1 - - [21/Apr/2022 12:55:41] &quot;POST /test_ajax HTTP/1.1&quot; 200 -
172.27.0.1 - - [21/Apr/2022 12:55:42] &quot;{&quot;foo&quot;:&quot;bar&quot;}POST /test_ajax HTTP/1.1&quot; 405 -"><pre class="notranslate"><code class="notranslate"> * Detected change in 'app.py', reloading
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 128-473-016
172.27.0.1 - - [21/Apr/2022 12:55:39] "GET /test HTTP/1.1" 200 -
172.27.0.1 - - [21/Apr/2022 12:55:41] "POST /test_ajax HTTP/1.1" 200 -
172.27.0.1 - - [21/Apr/2022 12:55:42] "{"foo":"bar"}POST /test_ajax HTTP/1.1" 405 -
</code></pre></div>
<p dir="auto">Works ok for the first click, but not for the second.</p>
<p dir="auto">If I consumes the data,</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="from flask import Flask, request, jsonify

app = Flask(__name__)

@app.post(&quot;/test_ajax&quot;)
def test_ajax():
    app.logger.info(request.data)     # &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;
    return jsonify({&quot;hello&quot;: &quot;world&quot;})

@app.get(&quot;/test&quot;)
def test():
    return (
        &quot;&lt;a href='javascript:test();'&gt;Test&lt;/a&gt;&quot;
        &quot;&lt;script&gt;&quot;
        &quot;function test() {&quot;
        &quot;    fetch('/test_ajax', {&quot;
        &quot;        method: 'POST',&quot;
        &quot;        headers: {'Content-Type': 'application/json'},&quot;
        &quot;        body: JSON.stringify({'foo': 'bar'})&quot;
        &quot;    });&quot;
        &quot;}&quot;
        &quot;&lt;/script&gt;&quot;
    )"><pre class="notranslate"><code class="notranslate">from flask import Flask, request, jsonify

app = Flask(__name__)

@app.post("/test_ajax")
def test_ajax():
    app.logger.info(request.data)     # &lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;
    return jsonify({"hello": "world"})

@app.get("/test")
def test():
    return (
        "&lt;a href='javascript:test();'&gt;Test&lt;/a&gt;"
        "&lt;script&gt;"
        "function test() {"
        "    fetch('/test_ajax', {"
        "        method: 'POST',"
        "        headers: {'Content-Type': 'application/json'},"
        "        body: JSON.stringify({'foo': 'bar'})"
        "    });"
        "}"
        "&lt;/script&gt;"
    )
</code></pre></div>
<p dir="auto">It works as expected:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content=" * Detected change in 'app.py', reloading
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 128-473-016
172.27.0.1 - - [21/Apr/2022 13:01:10] &quot;GET /test HTTP/1.1&quot; 200 -
[2022-04-21 13:01:12,186] INFO in api: b'{&quot;foo&quot;:&quot;bar&quot;}'
172.27.0.1 - - [21/Apr/2022 13:01:12] &quot;POST /test_ajax HTTP/1.1&quot; 200 -
[2022-04-21 13:01:12,904] INFO in api: b'{&quot;foo&quot;:&quot;bar&quot;}'
172.27.0.1 - - [21/Apr/2022 13:01:12] &quot;POST /test_ajax HTTP/1.1&quot; 200 -"><pre class="notranslate"><code class="notranslate"> * Detected change in 'app.py', reloading
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 128-473-016
172.27.0.1 - - [21/Apr/2022 13:01:10] "GET /test HTTP/1.1" 200 -
[2022-04-21 13:01:12,186] INFO in api: b'{"foo":"bar"}'
172.27.0.1 - - [21/Apr/2022 13:01:12] "POST /test_ajax HTTP/1.1" 200 -
[2022-04-21 13:01:12,904] INFO in api: b'{"foo":"bar"}'
172.27.0.1 - - [21/Apr/2022 13:01:12] "POST /test_ajax HTTP/1.1" 200 -
</code></pre></div>
<p dir="auto">If I design a url to don't use data but the user send any, it will result in a hard to debug weird behaviour.</p>
<p dir="auto">Environment:</p>
<ul dir="auto">
<li>Python version: Python 3.8.10</li>
<li>Flask version: Flask==2.1.1</li>
</ul>
<p dir="auto">With the following example:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from flask import Flask

app = Flask(__name__)


@app.route('/', methods=['POST'])
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    app.run()"><pre class="notranslate"><span class="pl-k">from</span> <span class="pl-s1">flask</span> <span class="pl-k">import</span> <span class="pl-v">Flask</span>

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


<span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-en">route</span>(<span class="pl-s">'/'</span>, <span class="pl-s1">methods</span><span class="pl-c1">=</span>[<span class="pl-s">'POST'</span>])</span>
<span class="pl-k">def</span> <span class="pl-en">hello_world</span>():
    <span class="pl-k">return</span> <span class="pl-s">'Hello World!'</span>


<span class="pl-k">if</span> <span class="pl-s1">__name__</span> <span class="pl-c1">==</span> <span class="pl-s">'__main__'</span>:
    <span class="pl-s1">app</span>.<span class="pl-en">run</span>()</pre></div>
<p dir="auto">When you set the request body to <code class="notranslate">{}</code> with Postman or any HTTP clients, the first request will return 200, while the second request will return a 405 error response. The log shows the request method is <code class="notranslate">{}POST</code>:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="&quot;{}POST / HTTP/1.1&quot; 405"><pre class="notranslate"><code class="notranslate">"{}POST / HTTP/1.1" 405
</code></pre></div>
<p dir="auto">Notice the request body became the part of the request method.</p>