2017-05-25 7 views
2

Je suis en train d'exécuter un serveur Web basé sur la structure Bottle. Ce cadre expose un point de terminaison où vous pouvez télécharger un fichier. Parfois, si le disque est plein, le serveur web est supposé renvoyer un code 429 sans lire le fichier. Pour une raison quelconque, quand je télécharger un fichier, si le serveur essaie de renvoyer un code 429 d'état l'exception suivante est soulevée:La bibliothèque de requêtes déclenche ConnectionError si le serveur Web renvoie une erreur mais uniquement lors du téléchargement d'un fichier volumineux

File "../hooks.py", line 325, in post_video_content 
    response = requests.post(url, data=fh) 
    File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 110, in post 
    return request('post', url, data=data, json=json, **kwargs) 
    File "/usr/local/lib/python2.7/site-packages/requests/api.py", line 56, in request 
    return session.request(method=method, url=url, **kwargs) 
    File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 488, in request 
    resp = self.send(prep, **send_kwargs) 
    File "/usr/local/lib/python2.7/site-packages/requests/sessions.py", line 609, in send 
    r = adapter.send(request, **kwargs) 
    File "/usr/local/lib/python2.7/site-packages/requests/adapters.py", line 473, in send 
    raise ConnectionError(err, request=request) 
ConnectionError: ('Connection aborted.', error(32, 'Broken pipe')) 

Mais si essayer exactement le même poste, mais au lieu d'afficher un fichier que j'ai simplement Après avoir envoyé une petite quantité de données, je récupère un objet de réponse de la demande et je peux inspecter le code d'état.

Reproduire:

webserver.py

from bottle import Bottle, route, run, request, response, get, post, put, abort 

@post('/content') 
@authenticate 
def content(): 
    response.status = 429 
    return "failed to write incoming movie to temp file (space might be full temporarily)" 

run(host="127.0.0.1", port=8080, debug=True) 

send_request.py

import requests 


# this works and prints the status code 
ret = requests.post("127.0.0.1:8080/content", data="sdfsdfsdfsdf") 
print ret.status_code 

# this part will throw an exception 
try: 
    with open("~/some_large_video_file.mp4", 'rb') as fh: 
     ret = requests.post('127.0.0.1:8080/content', data=fh) 
except: 
    print traceback.format_exc() 

EDIT - J'ai trouvé que cela dépend de la quantité de données. Si vous essayez de poster quelque chose comme 10KB de données, nous obtenons le code de retour 429. J'essaie de comprendre quelle est la limite qui l'amène à déclencher une exception.

EDIT2 - Il semble donc que la taille du fichier magique se situe entre 117K et 131K. Si j'essaie le premier, cela fonctionne comme prévu, j'obtiens la réponse de la requête et peux accéder au code d'état. Si j'essaie le premier, l'exception est levée.

Mes questions sont les suivantes:

  1. Pourquoi cela? Est-ce un bug en bouteille? Un bug dans les demandes? Pourquoi la taille/le type de données que je publie change-t-il la réponse?
  2. Y at-il un moyen de contourner ce problème? J'essaie d'associer une exception ConnectionError avec le serveur en panne et un code de réponse 429 indiquant que le disque est plein. Si je reçois la même exception pour les deux, je ne peux pas faire la différence entre les situations qui m'empêchent de mettre en place un back-off pour attendre l'ouverture de l'espace disque

Répondre

1

la page de demande de github de requêtes, et il semble que le problème se trouve dans le module httplib que les requêtes sont construites par-dessus, donc c'est un no-fix pour l'instant.

voir: https://github.com/kennethreitz/requests/issues/4062

+0

Vous devriez envisager de marquer cela comme une réponse, – user3351605

+0

Il ne me laisse pas pour un autre jour ou –