<p dir="auto">Hi</p>
<p dir="auto">When pool_block=True on an HTTPAdapter is used and the connection fails<br>
this one seems not return to the pool.</p>
<p dir="auto">To reproduce:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="# python
&gt;&gt;&gt; import requests
&gt;&gt;&gt; a = requests.adapters.HTTPAdapter(pool_maxsize=1, pool_block=True)
&gt;&gt;&gt; s = requests.Session()
&gt;&gt;&gt; s.mount(&quot;http://&quot;, a)
&gt;&gt;&gt; s.get(&quot;http://localhost:12345&quot;)
Traceback (most recent call last):
  File &quot;&lt;stdin&gt;&quot;, line 1, in &lt;module&gt;
  File &quot;/usr/local/lib/python2.7/dist-packages/requests/sessions.py&quot;, line 477, in get
    return self.request('GET', url, **kwargs)
  File &quot;/usr/local/lib/python2.7/dist-packages/requests/sessions.py&quot;, line 465, in request
    resp = self.send(prep, **send_kwargs)
  File &quot;/usr/local/lib/python2.7/dist-packages/requests/sessions.py&quot;, line 573, in send
    r = adapter.send(request, **kwargs)
  File &quot;/usr/local/lib/python2.7/dist-packages/requests/adapters.py&quot;, line 413, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', error(111, 'Connection refused'))
&gt;&gt;&gt; s.get(&quot;http://localhost:12345&quot;)

# here the session objects is stuck."><pre class="notranslate"><code class="notranslate"># python
&gt;&gt;&gt; import requests
&gt;&gt;&gt; a = requests.adapters.HTTPAdapter(pool_maxsize=1, pool_block=True)
&gt;&gt;&gt; s = requests.Session()
&gt;&gt;&gt; s.mount("http://", a)
&gt;&gt;&gt; s.get("http://localhost:12345")
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 477, in get
    return self.request('GET', url, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 465, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 573, in send
    r = adapter.send(request, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/adapters.py", line 413, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', error(111, 'Connection refused'))
&gt;&gt;&gt; s.get("http://localhost:12345")

# here the session objects is stuck.
</code></pre></div>
<p dir="auto">Cheers,</p>
<p dir="auto">Requests with <code class="notranslate">Content-Type: multipart/form-data</code> need to also have a <code class="notranslate">; boundary=someUniqueString</code> in that header. I think this is actually true for all <code class="notranslate">multipart/*</code> MIME types.</p>
<p dir="auto"><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#multipartform-data" rel="nofollow">https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#multipartform-data</a></p>
<p dir="auto">This is how curl works, if you pass <code class="notranslate">Content-Type: multipart/form-data</code> it'll still add a boundary because users shouldn't need to know how all the HTTP headers work, that's the library's job. We are running into this issue when trying to convert curl commands into requests code <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="757369472" data-permission-text="Title is private" data-url="https://github.com/curlconverter/curlconverter/issues/248" data-hovercard-type="issue" data-hovercard-url="/curlconverter/curlconverter/issues/248/hovercard" href="https://github.com/curlconverter/curlconverter/issues/248">curlconverter/curlconverter#248</a> and it would be convenient if Requests did the same thing as curl.</p>
<p dir="auto">I don't see why anyone would ever want to pass <code class="notranslate">Content-Type: multipart/form-data</code> without a <code class="notranslate">boundary</code>, unless they just don't know about it. If you do actually need to not have a boundary you would have to explicitly add an empty one <code class="notranslate">; boundary=</code> to your header. But I can also see how it might surprise users that even if they pass a header manually it gets modified.</p>
<h2 dir="auto">Expected Result</h2>
<p dir="auto">Requests still adds a <code class="notranslate">boundary</code> to my header if I don't, i.e. when I pass <code class="notranslate">headers={'Content-Type': 'multipart/form-data'}</code> and <code class="notranslate">files=</code></p>
<h2 dir="auto">Actual Result</h2>
<p dir="auto">Requests uses the header as-is and the request fails.</p>
<h2 dir="auto">Reproduction Steps</h2>
<div class="highlight highlight-text-python-console notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; import requests
&gt;&gt;&gt; 
&gt;&gt;&gt; files = {
...     'hello': (None, 'world'),
... }
&gt;&gt;&gt; requests.post('http://example.com', files=files).request.headers['Content-Type']
'multipart/form-data; boundary=498931185311c522b8ca559425b2b965'
&gt;&gt;&gt; 
&gt;&gt;&gt; headers = {
...     'Content-Type': 'multipart/form-data',
... }
&gt;&gt;&gt; 
&gt;&gt;&gt; requests.post('http://example.com', headers=headers, files=files).request.headers['Content-Type']
'multipart/form-data'"><pre class="notranslate">&gt;&gt;&gt; <span class="pl-k">import</span> requests
&gt;&gt;&gt; 
&gt;&gt;&gt; files <span class="pl-k">=</span> {
...     <span class="pl-s"><span class="pl-pds">'</span>hello<span class="pl-pds">'</span></span>: (<span class="pl-c1">None</span>, <span class="pl-s"><span class="pl-pds">'</span>world<span class="pl-pds">'</span></span>),
... }
&gt;&gt;&gt; requests.post(<span class="pl-s"><span class="pl-pds">'</span>http://example.com<span class="pl-pds">'</span></span>, <span class="pl-v">files</span><span class="pl-k">=</span>files).request.headers[<span class="pl-s"><span class="pl-pds">'</span>Content-Type<span class="pl-pds">'</span></span>]
'multipart/form-data; boundary=498931185311c522b8ca559425b2b965'
&gt;&gt;&gt; 
&gt;&gt;&gt; headers <span class="pl-k">=</span> {
...     <span class="pl-s"><span class="pl-pds">'</span>Content-Type<span class="pl-pds">'</span></span>: <span class="pl-s"><span class="pl-pds">'</span>multipart/form-data<span class="pl-pds">'</span></span>,
... }
&gt;&gt;&gt; 
&gt;&gt;&gt; requests.post(<span class="pl-s"><span class="pl-pds">'</span>http://example.com<span class="pl-pds">'</span></span>, <span class="pl-v">headers</span><span class="pl-k">=</span>headers, <span class="pl-v">files</span><span class="pl-k">=</span>files).request.headers[<span class="pl-s"><span class="pl-pds">'</span>Content-Type<span class="pl-pds">'</span></span>]
'multipart/form-data'</pre></div>
<p dir="auto">Compare with curl:</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="$ curl -vvv example.com -H &quot;Content-Type: multipart/form-data&quot; -F &quot;hello=world&quot;
[...]
&gt; Content-Type: multipart/form-data; boundary=------------------------ff92aa2ea98d6cc3"><pre class="notranslate">$ curl -vvv example.com -H <span class="pl-s"><span class="pl-pds">"</span>Content-Type: multipart/form-data<span class="pl-pds">"</span></span> -F <span class="pl-s"><span class="pl-pds">"</span>hello=world<span class="pl-pds">"</span></span>
[...]
<span class="pl-k">&gt;</span> Content-Type: multipart/form-data<span class="pl-k">;</span> boundary=------------------------ff92aa2ea98d6cc3</pre></div>