swoole / swoole-src

🚀 Coroutine-based concurrency library for PHP
https://www.swoole.com
Apache License 2.0
18.27k stars 3.16k forks source link

Http2 - sendfile failing on safari #4991

Open AdamSGit opened 1 year ago

AdamSGit commented 1 year ago

When enabling http2 and using sendfile response method, it fail on safari 16.2 with the error kCFErrorDomainCFNetwork. It work fine on other major browsers.

This issue seem to be caused by the Content-Length header. From my understanding, http2 send 9 bits headers for each chunks of data, which result in incorrect content length size. The quite simple solution to this would be to have the possibility to disable the content-length header in response, which is currently computed automatically.

  1. What did you do? If possible, provide a simple script for reproducing the error.

Please find snippet here (test should have ssl working, as http2 require ssl

// Define server instance
$swoole_server_instance = new Swoole\Http\Server('0.0.0.0', 9010, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);

// Set server instance attributes
$swoole_server_instance->set([
    'worker_num'             => 4,
    'open_http2_protocol'    => true,
    'ssl_cert_file' => './fullchain.pem',
    'ssl_key_file' => './privkey.pem',
]);

$swoole_server_instance->on('request', static function (Swoole\Http\Request $request, Swoole\Http\Response $response) : void {
    $response->setStatusCode(200);

    $response->header('Content-Type', 'application/pdf');
    $response->sendfile('./test.pdf');
});

// Spin up swoole
$swoole_server_instance->start();
  1. What did you expect to see? Safari displaying the pdf as other browsers do

  2. What did you see instead? kCFErrorDomainCFNetwork error 303

  3. What version of Swoole are you using (show your php --ri swoole)?

    
    swoole

Swoole => enabled Author => Swoole Team team@swoole.com Version => 5.0.1 Built => Feb 24 2023 18:16:06 coroutine => enabled with boost asm context kqueue => enabled rwlock => enabled openssl => OpenSSL 1.1.1s 1 Nov 2022 dtls => enabled http2 => enabled json => enabled pcre => enabled zlib => 1.2.11 async_redis => enabled

Directive => Local Value => Master Value swoole.enable_coroutine => On => On swoole.enable_library => On => On swoole.enable_preemptive_scheduler => Off => Off swoole.display_errors => On => On swoole.use_shortname => On => On swoole.unixsock_buffer_size => 262144 => 262144



6. What is your machine environment used (show your `uname -a` & `php -v` & `gcc -v`) ?
```Darwin MacBook-Pro.local 21.6.0 Darwin Kernel Version 21.6.0: Sun Nov  6 23:31:16 PST 2022; root:xnu-8020.240.14~1/RELEASE_X86_64 x86_64```
NathanFreeman commented 1 year ago

I can not reproduce it. What is the size of your file?

AdamSGit commented 1 year ago

I tested with multiples pdf, jpg and svg files from size starting to 80ko up to 3mo, the result is the same. Weird that you can't reproduce it. Your test environment share the same safari version and swoole build options ?

Sanart99 commented 1 month ago

I was going to write about it.

I found the same bug in Safari 15 and 17 while finding out that a specific js file wasn't being served on my website. I found out that it actually happens when I send anything over ~70kb. Only the start of the file is able to transfer (~47kb) and then the loading bar seems to infinitely wait for the server while on the console in Safari 15 I have an "kCFErrorDomainCFNetwork error 303" error, on Safari 17 the error is "Failed to load resource: cannot parse response."

Ofc I don't have this problem when Safari uses HTTP1.1.

Swoole version:

Author => Swoole Team <team@swoole.com>
Version => 5.1.1
Built => Dec  1 2023 13:40:59
coroutine => enabled with boost asm context
epoll => enabled
eventfd => enabled
signalfd => enabled
cpu_affinity => enabled
spinlock => enabled
rwlock => enabled
sockets => enabled
openssl => OpenSSL 3.0.2 15 Mar 2022
dtls => enabled
http2 => enabled
json => enabled
curl-native => enabled
pcre => enabled
mutex_timedlock => enabled
pthread_barrier => enabled
futex => enabled
mysqlnd => enabled
async_redis => enabled

Directive => Local Value => Master Value
swoole.enable_coroutine => On => On
swoole.enable_library => On => On
swoole.enable_fiber_mock => Off => Off
swoole.enable_preemptive_scheduler => Off => Off
swoole.display_errors => On => On
swoole.use_shortname => On => On
swoole.unixsock_buffer_size => 8388608 => 8388608
Sanart99 commented 1 month ago

I managed to reproduce the error by copy/pasting Adam's snippet, "worker_num" doesn't really matter it seems, and instead of sending a file I just sent a text over 65.6kb in size.

<?php
// Define server instance
$swoole_server_instance = new Swoole\Http\Server('0.0.0.0', 443, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);

// Set server instance attributes
$swoole_server_instance->set([
    'worker_num'             => 1,
    'open_http2_protocol'    => true,
    'ssl_cert_file' => './fullchain.pem',
    'ssl_key_file' => './privkey.pem'
]);

$swoole_server_instance->on('request', static function (Swoole\Http\Request $request, Swoole\Http\Response $response) : void {
    $response->end(<<<'DATA'
[>65.6kb text here]
DATA);
});

// Spin up swoole
$swoole_server_instance->start();
?>
Sanart99 commented 1 month ago

Here's a tcpdump of the entire communication between Swoole and Safari 17 when I tried to serve 65.7kb of text.

tcpdump: data link type LINUX_SLL2
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
19:35:19.520273 ens5  In  IP [CLIENT] > [SERVER]: Flags [SEW], seq 3078932986, win 65535, options [mss 1379,nop,wscale 6,nop,nop,TS val 3968401389 ecr 0,sackOK,eol], length 0
19:35:19.520309 ens5  Out IP [SERVER] > [CLIENT]: Flags [S.E], seq 375749904, ack 3078932987, win 62643, options [mss 8961,sackOK,TS val 2139453843 ecr 3968401389,nop,wscale 7], length 0
19:35:19.536320 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 1, win 2050, options [nop,nop,TS val 3968401405 ecr 2139453843], length 0
19:35:19.537957 ens5  In  IP [CLIENT] > [SERVER]: Flags [P.], seq 1:518, ack 1, win 2050, options [nop,nop,TS val 3968401407 ecr 2139453843], length 517
19:35:19.537982 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], ack 518, win 486, options [nop,nop,TS val 2139453861 ecr 3968401407], length 0
19:35:19.538997 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 1:1368, ack 518, win 486, options [nop,nop,TS val 2139453862 ecr 3968401407], length 1367
19:35:19.539001 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 1368:1576, ack 518, win 486, options [nop,nop,TS val 2139453862 ecr 3968401407], length 208
19:35:19.554800 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 1576, win 2025, options [nop,nop,TS val 3968401424 ecr 2139453862], length 0
19:35:19.560385 ens5  In  IP [CLIENT] > [SERVER]: Flags [P.], seq 518:598, ack 1576, win 2048, options [nop,nop,TS val 3968401429 ecr 2139453862], length 80
19:35:19.560670 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 1576:1831, ack 598, win 486, options [nop,nop,TS val 2139453884 ecr 3968401429], length 255
19:35:19.561191 ens5  In  IP [CLIENT] > [SERVER]: Flags [P.], seq 598:962, ack 1576, win 2048, options [nop,nop,TS val 3968401429 ecr 2139453862], length 364
19:35:19.562078 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 1831:3198, ack 962, win 484, options [nop,nop,TS val 2139453885 ecr 3968401429], length 1367
19:35:19.562084 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 3198:4565, ack 962, win 484, options [nop,nop,TS val 2139453885 ecr 3968401429], length 1367
19:35:19.562089 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 4565:5932, ack 962, win 484, options [nop,nop,TS val 2139453885 ecr 3968401429], length 1367
19:35:19.562090 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 5932:7299, ack 962, win 484, options [nop,nop,TS val 2139453885 ecr 3968401429], length 1367
19:35:19.562126 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 7299:8666, ack 962, win 484, options [nop,nop,TS val 2139453885 ecr 3968401429], length 1367
19:35:19.562127 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 8666:10033, ack 962, win 484, options [nop,nop,TS val 2139453885 ecr 3968401429], length 1367
19:35:19.562136 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 10033:11400, ack 962, win 484, options [nop,nop,TS val 2139453885 ecr 3968401429], length 1367
19:35:19.562138 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 11400:12767, ack 962, win 484, options [nop,nop,TS val 2139453885 ecr 3968401429], length 1367
19:35:19.562162 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 12767:14134, ack 962, win 484, options [nop,nop,TS val 2139453885 ecr 3968401429], length 1367
19:35:19.576509 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 1831, win 2044, options [nop,nop,TS val 3968401446 ecr 2139453884], length 0
19:35:19.576545 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 14134:15501, ack 962, win 484, options [nop,nop,TS val 2139453900 ecr 3968401446], length 1367
19:35:19.576550 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 15501:16868, ack 962, win 484, options [nop,nop,TS val 2139453900 ecr 3968401446], length 1367
19:35:19.578097 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 14134, win 1855, options [nop,nop,TS val 3968401447 ecr 2139453885], length 0
19:35:19.578108 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 16868:18235, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578110 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 18235:19602, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578114 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 19602:20969, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578115 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 20969:22336, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578163 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 22336:23703, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578167 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 23703:25070, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578173 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 25070:26437, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578174 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 26437:27804, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578194 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 27804:29171, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578195 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 14134, win 2048, options [nop,nop,TS val 3968401447 ecr 2139453885], length 0
19:35:19.578198 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 29171:30538, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578204 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 30538:31905, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578205 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 31905:33272, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578223 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 33272:34639, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578224 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 34639:36006, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578253 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 36006:37373, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578254 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 37373:38740, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578257 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 38740:40107, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578258 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 40107:41474, ack 962, win 484, options [nop,nop,TS val 2139453901 ecr 3968401447], length 1367
19:35:19.578812 ens5  In  IP [CLIENT] > [SERVER]: Flags [P.], seq 962:993, ack 14134, win 2048, options [nop,nop,TS val 3968401447 ecr 2139453885], length 31
19:35:19.592450 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 16868, win 2005, options [nop,nop,TS val 3968401462 ecr 2139453900], length 0
19:35:19.592484 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 41474:42841, ack 993, win 484, options [nop,nop,TS val 2139453916 ecr 3968401447], length 1367
19:35:19.592489 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 42841:44208, ack 993, win 484, options [nop,nop,TS val 2139453916 ecr 3968401447], length 1367
19:35:19.592497 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 44208:45575, ack 993, win 484, options [nop,nop,TS val 2139453916 ecr 3968401447], length 1367
19:35:19.592499 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 45575:46942, ack 993, win 484, options [nop,nop,TS val 2139453916 ecr 3968401447], length 1367
19:35:19.592540 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 16868, win 2048, options [nop,nop,TS val 3968401462 ecr 2139453900], length 0
19:35:19.594058 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 37373, win 1727, options [nop,nop,TS val 3968401463 ecr 2139453901], length 0
19:35:19.594072 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 46942:48309, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594074 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 48309:49676, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594075 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 49676:51043, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594076 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 51043:52410, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594082 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 52410:53777, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594082 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 53777:55144, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594083 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 55144:56511, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594084 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 56511:57878, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594132 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 57878:59245, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594134 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 59245:60612, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594135 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 60612:61979, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594135 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 61979:63346, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594148 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 63346:64713, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594149 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 64713:66080, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594150 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], seq 66080:67447, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 1367
19:35:19.594151 ens5  Out IP [SERVER] > [CLIENT]: Flags [P.], seq 67447:68015, ack 993, win 484, options [nop,nop,TS val 2139453917 ecr 3968401463], length 568
19:35:19.594166 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 41474, win 1663, options [nop,nop,TS val 3968401463 ecr 2139453901], length 0
19:35:19.594284 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 41474, win 2048, options [nop,nop,TS val 3968401463 ecr 2139453901], length 0
19:35:19.608336 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 42841, win 2026, options [nop,nop,TS val 3968401478 ecr 2139453916], length 0
19:35:19.608428 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 46942, win 2048, options [nop,nop,TS val 3968401478 ecr 2139453916], length 0
19:35:19.610117 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 68015, win 2487, options [nop,nop,TS val 3968401479 ecr 2139453917], length 0
19:35:19.610190 ens5  In  IP [CLIENT] > [SERVER]: Flags [.], ack 68015, win 2816, options [nop,nop,TS val 3968401479 ecr 2139453917], length 0
19:35:19.610466 ens5  In  IP [CLIENT] > [SERVER]: Flags [P.], seq 993:1028, ack 68015, win 2816, options [nop,nop,TS val 3968401479 ecr 2139453917], length 35
19:35:19.652398 ens5  Out IP [SERVER] > [CLIENT]: Flags [.], ack 1028, win 484, options [nop,nop,TS val 2139453976 ecr 3968401479], length 0
^C
75 packets captured
76 packets received by filter
0 packets dropped by kernel

I think that for those who understand all that they can figure out where the problem lies. (I don't understand what I'm seeing yet)