Pourquoi le téléchargement de fichiers ~2,5 MiB ou plus de provoquer une réinitialisation de la connexion?

0

La question

Nous essayons de mettre en œuvre le téléchargement de l'image par le biais de requêtes POST. Nous voulons également de limiter les images de ~1,0 MiB. Il fonctionne très bien sur les petites images, mais rien de ~2,5 MiB ou de grandes causes de la connexion pour réinitialiser. Il semble également envoyer plusieurs demandes après la première pour le même gestionnaire.

principal.aller:

package main

import (
    "log"
    "net/http"
)

func main() {
    http.HandleFunc("/", uploadHandler)
    http.ListenAndServe("localhost:8080", nil)
}

func uploadHandler(w http.ResponseWriter, r *http.Request) {
    if r.Method == "POST" {
        postHandler(w, r)
        return
    } else {
        http.ServeFile(w, r, "index.html")
    }
}

func postHandler(w http.ResponseWriter, r *http.Request) {
    // Send an error if the request is larger than 1 MiB
    if r.ContentLength > 1<<20 {
        // if larger than ~2,5 MiB, this will print 2 or more times
        log.Println("File too large")
        // And this error will never arrive, instead a Connection reset
        http.Error(w, "response too large", http.StatusRequestEntityTooLarge)
        return
    }
    return
}

index.html:

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <form method="POST" enctype="multipart/form-data">
      <input type="file" accept="image/*" name="profile-picture"><br>
      <button type="submit" >Upload</button>
  </form>
  </body>
</html>

Sortie lors du téléchargement d'un ~2,4 fichier MiB

$ go run main.go
2021/11/23 22:00:14 File too large

Il montre également la "demande trop grand" dans le navigateur

Sortie lors du téléchargement de ~2,5 fichier MiB

$ go run main.go
2021/11/23 22:03:25 File too large
2021/11/23 22:03:25 File too large

Le navigateur montre maintenant que la connexion a été réinitialisée

go http
2021-11-23 20:06:27
1

La meilleure réponse

3

Le client tente d'envoyer des données au serveur. Le serveur n'est pas de la lecture des données, c'est juste en regardant les en-têtes et la fermeture de la connexion. Le client est l'interprétation de ce que "la connexion a été réinitialisée". C'est hors de votre contrôle.

Au lieu de vérifier l'en-tête l'en-tête peut mentir, l'utilisation http.MaxBytesReader pour lire le contenu réel, mais l'erreur si elle est trop grande.

const MAX_UPLOAD_SIZE = 1<<20

func postHandler(w http.ResponseWriter, r *http.Request) {
    // Wrap the body in a reader that will error at MAX_UPLOAD_SIZE
    r.Body = http.MaxBytesReader(w, r.Body, MAX_UPLOAD_SIZE)

    // Read the body as normal. Check for an error.
    if err := r.ParseMultipartForm(MAX_UPLOAD_SIZE); err != nil {
        // We're assuming it errored because the body is too large.
        // There are other reasons it could error, you'll have to
        // look at err to figure that out.
        log.Println("File too large")
        http.Error(w, "Your file is too powerful", http.StatusRequestEntityTooLarge)
        return
    }

    fmt.Fprintf(w, "Upload successful")
}

Voir Comment le processus de l'upload de fichiers en Aller pour plus de détails.

2021-11-23 20:55:11

Cela semble fonctionner pour l'étendre et correspond à nos besoins. Toutefois, il provoque toujours une réinitialisation de la connexion avec une assez grande image comme ceci, par exemple, si je voulais soulever le MAX_UPLOAD_SIZE à 20 << 20 pour quelque raison que ce soit, je ne serais pas en mesure de télécharger quoi que ce soit de cette taille.
urist

J'ai aussi pensé à l' r.ContentLength pourrait être utilisé comme un moyen rapide de vérifier avant tout les fichiers sont encore téléchargé à tous, même si je sais qu'il pourrait être usurpée. Je suppose que vous pourriez mettre en œuvre ce dans le côté client de choses
urist

Je pense que j'ai compris pourquoi la réinitialisation de la connexion de mon commentaire ci-dessus, vous avez besoin pour commencer à utiliser les données (par exemple avec r.FormFile), sinon il sera tout simplement s'arrêter et de revenir, et de fermer la connexion une fois qu'il commence à être agacé par la constante données envoyées par le client.
urist

Dans d'autres langues

Cette page est dans d'autres langues

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................