Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-114812

No HTTP status code when HTTP reply received during body upload

    XMLWordPrintable

Details

    • Bug
    • Resolution: Out of scope
    • P2: Important
    • None
    • 6.5.1
    • Network: HTTP
    • None
    • Linux/X11
    • 21
    • 22f67be5f (dev)
    • Foundation Sprint 104, Foundation Sprint 105, Foundation Sprint 106, Foundation Sprint 107, Foundation Sprint 108, Foundation Sprint 109

    Description

      Using QNetworkAccessManager::post() to send a large file using QHttpMultiPart;

      If the HTTP server sends an HTTP response before the Qt app has uploaded the full request body, the QNetworkReply reports a QNetworkReply::RemoteHostClosedError error and  neither the HTTP status code nor the response body are available.

      Using wireshark it is possible to see that the response data was sent over the network with the header "Connection: close" before the connection was closed. And also that Qt retries  4 times before giving up and reporting the error.

      An easy way to reproduce the issue is by using a go server that will no read the body:

      func getRoot(w http.ResponseWriter, r *http.Request) {
      	fmt.Printf("got / request\n")
      
      	if r.Header.Get("Expect") == "100-continue" {
      		w.WriteHeader(http.StatusContinue)
      	}
      
      	w.WriteHeader(http.StatusBadRequest)
      	w.Header().Set("Content-Type", "application/json")
      	io.WriteString(w, "{\"foo\": null}")
      }
      
      func main() {
      	http.HandleFunc("/", getRoot)
      	err := http.ListenAndServe(":3333", nil)
      	if errors.Is(err, http.ErrServerClosed) {
      		fmt.Printf("server closed\n")
      	} else if err != nil {
      		fmt.Printf("error starting server: %s\n", err)
      		os.Exit(1)
      	}
      }
      

      With curl we get:

      $ curl  -F "file=@4GiB"  http://localhost:3333 --verbose
      *   Trying 127.0.0.1:3333...
      * Connected to localhost (127.0.0.1) port 3333 (#0)
      > POST / HTTP/1.1
      > Host: localhost:3333
      > User-Agent: curl/7.88.1
      > Accept: */*
      > Content-Length: 4294967492
      > Content-Type: multipart/form-data; boundary=------------------------d59b0074949dcd1e
      > Expect: 100-continue
      > 
      < HTTP/1.1 100 Continue
      < HTTP/1.1 400 Bad Request
      < Date: Thu, 22 Jun 2023 14:52:04 GMT
      < Content-Length: 13
      < Content-Type: text/plain; charset=utf-8
      < Connection: close
      < 
      * we are done reading and this is set to close, stop send
      * Closing connection 0
      {"foo": null}⏎
      

      With Qt:

      QCoreApplication app(argc, argv);
      
          QNetworkRequest request;
          request.setUrl({"http://localhost:3333/"});
          QByteArray data;
          data.resize(1024 * 1024 * 1024);
      
      
          auto multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);          
      
          QHttpPart part;
          part.setHeader(QNetworkRequest::ContentDispositionHeader,
                              QString("form-data; name=\"file\"; filename=\"4GiB\""));
          part.setHeader(QNetworkRequest::ContentTypeHeader,
                              QString("application/octet-stream"));
          part.setBody(data);
          multiPart->append(part);
      
      
          QNetworkAccessManager nam;
          auto reply = nam.post(request, multiPart);
          QObject::connect(reply, &QNetworkReply::finished, [reply]() {
              qDebug() << reply->error();                                             // QNetworkReply::RemoteHostClosedError
              qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); // QVariant(Invalid)
              qDebug() << reply->readAll();                                           // ""
              qApp->exit();
          });
          return app.exec();
      

      Attachments

        For Gerrit Dashboard: QTBUG-114812
        # Subject Branch Project Status CR V

        Activity

          People

            mate Máté Barany
            bterrier Benjamin Terrier
            Vladimir Minenko Vladimir Minenko
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes