Merge pull request #820 from EmanuelPeixoto/fix-upload-http-status
Some checks failed
Docker / e2e (push) Has been cancelled
Docker / build (./Dockerfile, , ghcr.io/${{ github.repository }}) (push) Has been cancelled
Docker / build (./Dockerfile.alpine, -alpine, ghcr.io/${{ github.repository }}) (push) Has been cancelled

Fix upload-speed inflation on HTTP errors and document request body limits
This commit is contained in:
sstidl 2026-07-30 07:06:37 +02:00 committed by GitHub
commit 1af6517eb9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 41 additions and 8 deletions

23
doc.md
View file

@ -60,6 +60,29 @@ Let's install the speed test.
Put all files on your web server via FTP or by copying them directly. You can install it in the root, or in a subdirectory.
**Web server upload limit:** The upload test sends POST requests up to 20 MB (configurable with `xhr_ul_blob_megabytes`). Without proper configuration, the server will reject these with HTTP 413, causing wildly inaccurate upload speeds. Configure your web server to accept large request bodies:
Nginx:
```
client_max_body_size 128m;
```
Apache:
```
LimitRequestBody 134217728
```
IIS: Add the following to `web.config` (value is in bytes):
```xml
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="134217728" />
</requestFiltering>
</security>
</system.webServer>
```
__Important:__ The speed test needs write permissions in the installation folder!
#### ipinfo.io

View file

@ -502,18 +502,28 @@ function ulTest(done) {
prevLoaded = event.loaded;
}.bind(this);
xhr[i].upload.onload = function() {
// this stream sent all the garbage data, start again
tverb("ul stream finished " + i);
testStream(i, 0);
// body uploaded, but response not yet available.
// xhr.onload below handles the full lifecycle.
}.bind(this);
xhr[i].upload.onerror = function() {
tverb("ul stream failed " + i);
if (settings.xhr_ignoreErrors === 0) failed = true; //abort
try {
xhr[i].abort();
} catch (e) {}
if (settings.xhr_ignoreErrors === 0) failed = true;
try { x.abort(); } catch (e) {}
delete xhr[i];
if (settings.xhr_ignoreErrors === 1) testStream(i, 0); //restart stream
if (settings.xhr_ignoreErrors === 1) testStream(i, 0);
}.bind(this);
xhr[i].onload = function() {
// response complete — check status on captured x, not xhr[i]
if (x.status >= 200 && x.status < 300) {
tverb("ul stream finished " + i);
testStream(i, 0);
} else {
tverb("ul stream failed with HTTP " + x.status + " " + i);
if (settings.xhr_ignoreErrors === 0) failed = true;
try { x.abort(); } catch (e) {}
delete xhr[i];
if (settings.xhr_ignoreErrors === 1) testStream(i, 0);
}
}.bind(this);
// send xhr
xhr[i].open("POST", settings.url_ul + url_sep(settings.url_ul) + (settings.mpot ? "cors=true&" : "") + "r=" + Math.random(), true); // random string to prevent caching