fix(sync-php): read Authorization via getallheaders and tolerate ETag forms
Apache commonly strips Authorization before PHP sees it, so every request looked unauthenticated on a stock XAMPP and answered 404. If-None-Match is now compared on the bare hash: a validator that lost its quotes, or a weak W/ tag, would never match and each request would silently re-download the whole snapshot - expensive on mobile data and invisible in the logs, a 200 looking perfectly normal.
This commit is contained in:
+20
-3
@@ -41,10 +41,22 @@ header('X-Content-Type-Options: nosniff');
|
|||||||
// Authentication
|
// Authentication
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
/** Bearer token, compared in constant time so a wrong guess leaks no timing. */
|
/**
|
||||||
|
* Bearer token, compared in constant time so a wrong guess leaks no timing.
|
||||||
|
*
|
||||||
|
* Three sources on purpose: Apache commonly strips Authorization before PHP
|
||||||
|
* sees it (it is only forwarded with CGIPassAuth on, or through a rewrite), so
|
||||||
|
* $_SERVER alone answers empty on a stock XAMPP and every request looks
|
||||||
|
* unauthenticated. getallheaders() reads what the client actually sent.
|
||||||
|
*/
|
||||||
function client_token(): string {
|
function client_token(): string {
|
||||||
$h = $_SERVER['HTTP_AUTHORIZATION'] ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ?? '';
|
$h = $_SERVER['HTTP_AUTHORIZATION'] ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] ?? '';
|
||||||
if (stripos($h, 'Bearer ') === 0) return substr($h, 7);
|
if ($h === '' && function_exists('getallheaders')) {
|
||||||
|
foreach (getallheaders() as $name => $value) {
|
||||||
|
if (strcasecmp($name, 'Authorization') === 0) { $h = $value; break; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stripos($h, 'Bearer ') === 0) return trim(substr($h, 7));
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,7 +97,12 @@ if ($method === 'HEAD' || $method === 'GET') {
|
|||||||
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', (int)filemtime(SYNC_FILE)) . ' GMT');
|
header('Last-Modified: ' . gmdate('D, d M Y H:i:s', (int)filemtime(SYNC_FILE)) . ' GMT');
|
||||||
|
|
||||||
// Save the round trip when the client already holds this version.
|
// Save the round trip when the client already holds this version.
|
||||||
if (trim($_SERVER['HTTP_IF_NONE_MATCH'] ?? '') === $etag) {
|
// Compared on the bare hash: a validator that loses its quotes or arrives
|
||||||
|
// as a weak tag (W/"…") would otherwise never match, and every request
|
||||||
|
// would silently download the whole snapshot again — costly on mobile data
|
||||||
|
// and invisible in the logs, since a 200 looks perfectly normal.
|
||||||
|
$sent = trim($_SERVER['HTTP_IF_NONE_MATCH'] ?? '');
|
||||||
|
if ($sent !== '' && trim($sent, 'W/" ') === trim($etag, '" ')) {
|
||||||
http_response_code(304);
|
http_response_code(304);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user