From 6130547ca69a5c74b76923ab393dac94dca6b6d0 Mon Sep 17 00:00:00 2001 From: Zwyx <29386932+Zwyx@users.noreply.github.com> Date: Sun, 24 Mar 2024 19:07:59 +0800 Subject: [PATCH] Add response header `X-Uncompressed-Content-Length` for JSON API Because the response from the API is PHP output, the usual `Content-Length` header is absent. This [custom header technique](https://stackoverflow.com/questions/15097712/how-can-i-use-deflated-gzipped-content-with-an-xhr-onprogress-function/32799706#32799706) allows the client to know the total length of the data being received, in order to display a progress indicator. Here's a code example with `XMLHttpRequest`: ``` xhr.addEventListener("progress", (e) => { if (e.lengthComputable) { onDownloadProgress({ loaded: e.loaded, total: e.total, }); } else { const uncompressedContentLength = xhr.getResponseHeader( "X-Uncompressed-Content-Length", ); if (uncompressedContentLength) { onDownloadProgress({ loaded: e.loaded, total: Number(uncompressedContentLength), }); } } }); ``` Notes: - `Fetch` can be used as well (only reason I use `XMLHttpRequest` is because `fetch` doesn't allow to track the progress of uploaded data (when creating a paste); whereas `XMLHttpRequest` does). - `e.loaded` can be different between browsers; Firefox reports the length of the compressed data, Chrome reports the length of uncompressed data (see https://github.com/whatwg/xhr/issues/388). A workaround for this is to manually set our progress indicator to 100% when the request finishes. --- lib/Controller.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Controller.php b/lib/Controller.php index dee03fe6..c97485a7 100644 --- a/lib/Controller.php +++ b/lib/Controller.php @@ -151,6 +151,8 @@ class Controller header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE'); header('Access-Control-Allow-Headers: X-Requested-With, Content-Type'); + header('X-Uncompressed-Content-Length: ' . strlen($this->_json)); + header('Access-Control-Expose-Headers: X-Uncompressed-Content-Length'); echo $this->_json; } else { $this->_view();