<p dir="auto">When I use a proxy in my code I find a problem. In the code below</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="s = requests.Session()
s.proxies = {'http':'127.0.0.1:3128'}
r = s.get(&quot;http://www.apple.com&quot;)"><pre class="notranslate"><span class="pl-s1">s</span> <span class="pl-c1">=</span> <span class="pl-s1">requests</span>.<span class="pl-v">Session</span>()
<span class="pl-s1">s</span>.<span class="pl-s1">proxies</span> <span class="pl-c1">=</span> {<span class="pl-s">'http'</span>:<span class="pl-s">'127.0.0.1:3128'</span>}
<span class="pl-s1">r</span> <span class="pl-c1">=</span> <span class="pl-s1">s</span>.<span class="pl-en">get</span>(<span class="pl-s">"http://www.apple.com"</span>)</pre></div>
<p dir="auto">If I set environmet var http_proxy='<a href="http://192.168.1.100:3128" rel="nofollow">http://192.168.1.100:3128</a>' then the request will use environment proxy rather than the proxy I have set in the code.<br>
But if I use proxy like below the program will use the proxy which I set in the code.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="s = requests.Session()
r = s.get(&quot;http://www.apple.com&quot;, proxies={'http':'127.0.0.1:3128'})"><pre class="notranslate"><span class="pl-s1">s</span> <span class="pl-c1">=</span> <span class="pl-s1">requests</span>.<span class="pl-v">Session</span>()
<span class="pl-s1">r</span> <span class="pl-c1">=</span> <span class="pl-s1">s</span>.<span class="pl-en">get</span>(<span class="pl-s">"http://www.apple.com"</span>, <span class="pl-s1">proxies</span><span class="pl-c1">=</span>{<span class="pl-s">'http'</span>:<span class="pl-s">'127.0.0.1:3128'</span>})</pre></div>
<p dir="auto">Is there any issue?</p>
<h1 dir="auto">Problem</h1>
<p dir="auto">Currently, tools (e.g., <a href="https://github.com/openstack/python-swiftclient/blob/3d0de79e26e2aa6285742c60aca3c164e9c2fbb9/swiftclient/client.py#L942..L945">openstack/python-swiftclient</a>) fight how requests sets the <code class="notranslate">Content-Type</code> header for a request. Notice that if the user of swiftclient doesn't provide their own <code class="notranslate">content_type</code> then the library sets the header's value to <code class="notranslate">''</code>. Ideally, setting <code class="notranslate">None</code> in a situation like this (where the Session has no default <code class="notranslate">Content-Type</code>) would prevent the request preparation from setting its own <code class="notranslate">Content-Type</code> header. This doesn't work because the per-session and per-request settings are <a href="https://github.com/kennethreitz/requests/blob/master/requests/sessions.py#L361">merged at the session level</a>.</p>
<h1 dir="auto">Potential solutions</h1>
<h2 dir="auto">Split the responsibility of merging settings</h2>
<p dir="auto">The merge at the session level could just take care of ensuring that the per-request settings have priority while waiting for the request preparation to remove <code class="notranslate">None</code>s. The downside of this behaviour is that it breaks backwards compatibility. Why? Consider the following:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import requests

s = requests.Session()
s.headers['Content-Type'] = 'application/json'
s.post(url, data={'some': 'formdata'}, headers={'Content-Type': None})"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">requests</span>

<span class="pl-s1">s</span> <span class="pl-c1">=</span> <span class="pl-s1">requests</span>.<span class="pl-v">Session</span>()
<span class="pl-s1">s</span>.<span class="pl-s1">headers</span>[<span class="pl-s">'Content-Type'</span>] <span class="pl-c1">=</span> <span class="pl-s">'application/json'</span>
<span class="pl-s1">s</span>.<span class="pl-en">post</span>(<span class="pl-s1">url</span>, <span class="pl-s1">data</span><span class="pl-c1">=</span>{<span class="pl-s">'some'</span>: <span class="pl-s">'formdata'</span>}, <span class="pl-s1">headers</span><span class="pl-c1">=</span>{<span class="pl-s">'Content-Type'</span>: <span class="pl-c1">None</span>})</pre></div>
<p dir="auto">This allows for requests to detect that it is in fact <code class="notranslate">application/x-www-form-urlencoded</code> by removing the default set by the session. Keeping backwards compatibility would mean that we would have to do extra work while merging settings on the session-level. We would have to check if the header was set on the session level, and then we would delete headers with value <code class="notranslate">None</code>, otherwise, persist the <code class="notranslate">None</code> value. This is clearly a lot of extra logic.</p>
<h2 dir="auto">Create a constant/singleton to mean "Do not autogenerate any of this for me"</h2>
<p dir="auto">We could potentially expose a new constant or singleton in requests to allow users to specify when they want to prevent requests from handling it for them. I dislike this idea a lot, but it's potentially easier to implement and a bit more explicit than overloading the already overloaded meaning of <code class="notranslate">None</code> in this context.</p>