title: ConnectionResetError when trying to send PUT request
body: <p>I'm trying to upload a file using a PUT REST Api, but I get a <code>ConnectionResetError</code>. I've tried using <code>urllib.request.Request()</code> with <code>urllib.request.urlopen()</code>, as well as <code>requests.put()</code>.</p>
  
  <p>It works correctly when I'm using cURL:</p>
  
  <pre><code>$ curl -X PUT http://localhost:5000/root.bar/test/1.0/jre -H 'Content-Type: application/java-archive' -H 'Content-Name: bfg-1.12.16.jar' -H 'Authorization: Basic cm9vdDphbHBpbmU=' -d @C:/Users/niklas/Desktop/bfg-1.12.16.jar
  </code></pre>
  
  <p>The important portion of the code:</p>
  
  <pre><code>headers = {'Content-Type': args.mime, 'Content-Name': args.name}
  if args.auth:
    headers['Authorization'] = build_basicauth(username, password)
  url = args.apiurl.rstrip('/') + '/{}/{}/{}/{}'.format(*parts)
  if not urllib.parse.urlparse(url).scheme:
    url = 'https://' + url
  
  if args.test:
    command = ['curl', '-X', 'PUT', url]
    for key, value in headers.items():
      command += ['-H', '{}: {}'.format(key, value)]
    command += ['-d', '@' + args.file.name]
    print('$', ' '.join(map(shlex.quote, command)))
    return 0
  
  response = requests.put(url, data=args.file, headers=headers)
  print(response)
  </code></pre>
  
  <p><strong>What am I missing that cURL is doing?</strong></p>
  
  <p>(PS: I've also tried sending <code>bytes</code> instead of a file-like object using <code>requests.put()</code> by passing <code>data=args.file.read()</code> instead)</p>
  
  <hr>
  
  <p>The full traceback:</p>
  
  <pre><code>$ python -m fatartifacts.web.cli http://localhost:5000 root.bar:test:1.0:jre ~/Desktop/bfg-1.12.16.jar  -m application/java-archive -u root:alpine
  Traceback (most recent call last):
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\urllib3\connectionpool.py", line 601, in urlopen
      chunked=chunked)
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\urllib3\connectionpool.py", line 357, in _make_request
      conn.request(method, url, **httplib_request_kw)
    File "c:\users\niklas\appdata\local\programs\python\python36\Lib\http\client.py", line 1239, in request
      self._send_request(method, url, body, headers, encode_chunked)
    File "c:\users\niklas\appdata\local\programs\python\python36\Lib\http\client.py", line 1285, in _send_request
      self.endheaders(body, encode_chunked=encode_chunked)
    File "c:\users\niklas\appdata\local\programs\python\python36\Lib\http\client.py", line 1234, in endheaders
      self._send_output(message_body, encode_chunked=encode_chunked)
    File "c:\users\niklas\appdata\local\programs\python\python36\Lib\http\client.py", line 1065, in _send_output
      self.send(chunk)
    File "c:\users\niklas\appdata\local\programs\python\python36\Lib\http\client.py", line 986, in send
      self.sock.sendall(data)
  ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host
  
  During handling of the above exception, another exception occurred:
  
  Traceback (most recent call last):
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\requests\adapters.py", line 440, in send
      timeout=timeout
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\urllib3\connectionpool.py", line 639, in urlopen
      _stacktrace=sys.exc_info()[2])
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\urllib3\util\retry.py", line 357, in increment
      raise six.reraise(type(error), error, _stacktrace)
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\urllib3\packages\six.py", line 685, in reraise
      raise value.with_traceback(tb)
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\urllib3\connectionpool.py", line 601, in urlopen
      chunked=chunked)
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\urllib3\connectionpool.py", line 357, in _make_request
      conn.request(method, url, **httplib_request_kw)
    File "c:\users\niklas\appdata\local\programs\python\python36\Lib\http\client.py", line 1239, in request
      self._send_request(method, url, body, headers, encode_chunked)
    File "c:\users\niklas\appdata\local\programs\python\python36\Lib\http\client.py", line 1285, in _send_request
      self.endheaders(body, encode_chunked=encode_chunked)
    File "c:\users\niklas\appdata\local\programs\python\python36\Lib\http\client.py", line 1234, in endheaders
      self._send_output(message_body, encode_chunked=encode_chunked)
    File "c:\users\niklas\appdata\local\programs\python\python36\Lib\http\client.py", line 1065, in _send_output
      self.send(chunk)
    File "c:\users\niklas\appdata\local\programs\python\python36\Lib\http\client.py", line 986, in send
      self.sock.sendall(data)
  urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None))
  
  During handling of the above exception, another exception occurred:
  
  Traceback (most recent call last):
    File "c:\users\niklas\appdata\local\programs\python\python36\Lib\runpy.py", line 193, in _run_module_as_main
      "__main__", mod_spec)
    File "c:\users\niklas\appdata\local\programs\python\python36\Lib\runpy.py", line 85, in _run_code
      exec(code, run_globals)
    File "C:\Users\niklas\repos\fatartifacts\fatartifacts\web\cli.py", line 106, in &lt;module&gt;
      main_and_exit()
    File "C:\Users\niklas\repos\fatartifacts\fatartifacts\web\cli.py", line 102, in main_and_exit
      sys.exit(main())
    File "C:\Users\niklas\repos\fatartifacts\fatartifacts\web\cli.py", line 97, in main
      response = requests.put(url, data=args.file, headers=headers)
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\requests\api.py", line 126, in put
      return request('put', url, data=data, **kwargs)
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\requests\api.py", line 58, in request
      return session.request(method=method, url=url, **kwargs)
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\requests\sessions.py", line 508, in request
      resp = self.send(prep, **send_kwargs)
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\requests\sessions.py", line 618, in send
      r = adapter.send(request, **kwargs)
    File "C:\Users\niklas\.virtualenvs\fatartifacts-LoWBpE4v\lib\site-packages\requests\adapters.py", line 490, in send
      raise ConnectionError(err, request=request)
  requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(10054, 'An existing connection was forcibly closed by the remote host', None, 10054, None))
  </code></pre>
  
  <hr>
  
  <p>The REST API is implemented with <code>flask</code> and <code>flask-restful</code>. This exception seems to happen when</p>
  
  <ul>
  <li>issuing the request using Python (<code>urllib.request</code>, <code>requests</code>)</li>
  <li>the API returns a non-200 status code using <code>flask.abort()</code></li>
  </ul>