dunglas / frankenphp

šŸ§Ÿ The modern PHP app server
https://frankenphp.dev
MIT License
7.01k stars 243 forks source link

FrankenPHP response isn't gzipped? #707

Closed tfirdaus closed 6 months ago

tfirdaus commented 7 months ago

What happened?

While testing WordPress with FrankenPHP, I noticed that the response isn't actually gzipped? Take a look at these screenshots:

Screenshot 2024-04-09 at 3 05 35 PM Screenshot 2024-04-09 at 3 06 08 PM

As we can see there, the size of the document in FrankenPHP's response is significantly larger compared to WordPress with Apache below.šŸ‘‡

Screenshot 2024-04-09 at 3 04 04 PM Screenshot 2024-04-09 at 3 04 15 PM

Both configurations are using the stock configuration from Docker WordPress and FrankenPHP. The only difference is that HTTPS redirect is disabled. Is there anything we need to configure to make it work similarly to WordPress with Apache? It would be great if we could also get the missing headers: Content-Encoding and Content-Length.

Build Type

Docker (Debian Bookworm)

Worker Mode

No

Operating System

macOS

CPU Architecture

Apple Silicon

PHP configuration

PHP Version 8.2.17
WordPress 6.5

Relevant log output

No response

withinboredom commented 7 months ago

Sorry to leave you hanging for so long, I've been curious how this is going on. Are you using the default caddyfile?

Can you share your request headers? Particularly the Accept-Encoding headers?

withinboredom commented 7 months ago

Also, how are you running this? Are you running this in a docker container or cli? If a cli, can you share the incantation? If a docker container, can you share the docker file?

tfirdaus commented 7 months ago

Hi, @withinboredom šŸ‘‹ . It's running within a Docker container. Everything is pretty much the default.

Here is the Dockerfile:

FROM dunglas/frankenphp:latest-php8.2

# install the PHP extensions we need (https://make.wordpress.org/hosting/handbook/handbook/server-environment/#php-extensions)
RUN install-php-extensions \
    bcmath \
    exif \
    gd \
    intl \
    mysqli \
    zip \
    imagick \
    opcache

COPY --from=wordpress /usr/local/etc/php/conf.d/* /usr/local/etc/php/conf.d/
COPY --from=wordpress /usr/local/bin/docker-entrypoint.sh /usr/local/bin/
COPY --from=wordpress --chown=root:root /usr/src/wordpress /usr/src/wordpress

WORKDIR /var/www/html
VOLUME /var/www/html

ARG USER=www-data
RUN chown -R ${USER}:${USER} /data/caddy && chown -R ${USER}:${USER} /config/caddy

RUN sed -i \
    -e 's/\[ "$1" = '\''php-fpm'\'' \]/\[\[ "$1" == frankenphp* \]\]/g' \
    -e 's/php-fpm/frankenphp/g' \
    /usr/local/bin/docker-entrypoint.sh

USER ${USER}
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
CMD ["frankenphp", "run", "--config", "/etc/caddy/Caddyfile"]

And the Caddyfile.

{
        {$CADDY_GLOBAL_OPTIONS}

        frankenphp {
                #worker /path/to/your/worker.php
                {$FRANKENPHP_CONFIG}
        }

        # https://caddyserver.com/docs/caddyfile/directives#sorting-algorithm
        order mercure after encode
        order vulcain after reverse_proxy
        order php_server before file_server
        order php before file_server
}

{$CADDY_EXTRA_CONFIG}

{$SERVER_NAME:localhost} {
        #log {
        #       # Redact the authorization query parameter that can be set by Mercure
        #       format filter {
        #               wrap console
        #               fields {
        #                       uri query {
        #                               replace authorization REDACTED
        #                       }
        #               }
        #       }
        #}

        root * /var/www/html/
        encode zstd br gzip

        # Uncomment the following lines to enable Mercure and Vulcain modules
        #mercure {
        #       # Transport to use (default to Bolt)
        #       transport_url {$MERCURE_TRANSPORT_URL:bolt:///data/mercure.db}
        #       # Publisher JWT key
        #       publisher_jwt {env.MERCURE_PUBLISHER_JWT_KEY} {env.MERCURE_PUBLISHER_JWT_ALG}
        #       # Subscriber JWT key
        #       subscriber_jwt {env.MERCURE_SUBSCRIBER_JWT_KEY} {env.MERCURE_SUBSCRIBER_JWT_ALG}
        #       # Allow anonymous subscribers (double-check that it's what you want)
        #       anonymous
        #       # Enable the subscription API (double-check that it's what you want)
        #       subscriptions
        #       # Extra directives
        #       {$MERCURE_EXTRA_DIRECTIVES}
        #}
        #vulcain

        {$CADDY_SERVER_EXTRA_DIRECTIVES}

        php_server
}
withinboredom commented 7 months ago

Thank you! What are your request headers? I'd like to reproduce this and see what is going on.

tfirdaus commented 7 months ago

@withinboredom thanks for looking into this. Here is the request header:

GET / HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-US,en;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Cookie: wordpress_test_cookie=WP%20Cookie%20check; wordpress_logged_in_5214b3dbedcdaac350d3fae0091b00b4=admin%7C1702296930%7CIR0o0bEzfHT4WQ55tElgHQKM8xCIZH05vYw7m1jndaj%7C832b1c4cd9def387253f7798a31e0e80af56119536c89c5ca9b80c69fcb4a994; wp_lang=en_US; wordpress_logged_in_902cfb915e826c1bc98213218a1bdfdd=admin%7C1702570865%7CpseSJceaiuDN4vA5ad2Y9EBhLQv8mH4HE3dxu5wmsAd%7C44f06b888f592ace3c940d8755b97fbae1cd9244470a38485cd1075d23b77791; kinsta_staff=1; __stripe_mid=2606af91-4a79-4c48-a45a-2ca2716e3e1b55b7e9; kinsta_referral=eyJhZmZpbGlhdGVfaWQiOiIyMzg5Mzg0MDMiLCJyZWZlcnJhbF9pZCI6ImFhNGE0N2M4LTRhMTgtNDRjOC1hZGE1LTZjMzI5MGVmMTQ3OSJ9; wordpress_cdc97f8e5fb252306fcf35e314d7b2aa=kinsta%7C1712216025%7Cwut1o2A3XDOXc7Xz2JIZEJB7l55deG1I7QoMeEe5pOz%7Ca50b2d7ddae208c8653ef5ab8270bff0753372d1db0c868ec75ddd57781aa168; wordpress_logged_in_cdc97f8e5fb252306fcf35e314d7b2aa=kinsta%7C1712216025%7Cwut1o2A3XDOXc7Xz2JIZEJB7l55deG1I7QoMeEe5pOz%7C44c9c5cc52d4099b46a009f76c942215a824bffcf9cf6a4f138dfdf56b458846; wp-settings-1=deleted; wp-settings-time-1=1712555209; wordpress_logged_in_812ec203ee00103a80d847d7c3d0ace6=admin%7C1712789440%7CFCr919OZm5Y2KB7h4f0NRgRDKSuCEM3jeRErulsVXJg%7Ca092077eb858fca79503aee7bbcdb10998bffea1dd4b820bc34018d9b5ba08a8
DNT: 1
Host: localhost
Pragma: no-cache
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36
sec-ch-ua: "Chromium";v="123", "Not:A-Brand";v="8"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
withinboredom commented 7 months ago

Yeah, this one is weird. Doing a local build of frankenphp, I see encoding working correctly. But it isn't in the docker image or static build from the latest release.

Simplest repoducer:

<?php
#test.php

header('Content-Type: text/plain');
ksort($_SERVER);
var_dump($_SERVER);
./frankenphp php-server --listen :8080 &
curl -v -H "Accept-Encoding: gzip" localhost:8080/test.php

You should see the following output:

*   Trying 127.0.0.1:8080...
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /test.php HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.81.0
> Accept: */*
> Accept-Encoding: gzip
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Content-Encoding: gzip
< Content-Type: text/plain;charset=UTF-8
< Server: Caddy
< Vary: Accept-Encoding
< X-Powered-By: PHP/8.3.4-dev
< Date: Thu, 11 Apr 2024 16:14:21 GMT
< Transfer-Encoding: chunked
<
Warning: Binary output can mess up your terminal. Use "--output -" to tell
Warning: curl to output it to your terminal anyway, or consider "--output
Warning: <FILE>" to save to a file.
* Failure writing output to destination
* Failed reading the chunked-encoded stream
* Closing connection 0

@dunglas any idea why CI builds wouldn't be encoding output? I'm kinda scratching my head on this one.

dunglas commented 7 months ago

Is the Content-Length missing or the response size too small to trigger the encoder?

withinboredom commented 7 months ago

Same payload in both cases, very strange

https://asciinema.org/a/wmiKh5LBDImSJ2WwwsWaF7KrV

dunglas commented 7 months ago

I cannot reproduce the issue on Mac using the official Docker image (Linux ARM) or the Mac ARM binary running directly on the host.

StephenMiracle commented 6 months ago

hey! Iā€™m a little late. i know gzip is working correctly on the frankenwp image. Have you checked this repo? the default is brotli but also supports gzip as backup.

https://github.com/StephenMiracle/frankenwp

@tfirdaus

dunglas commented 6 months ago

I am closing for now as we haven't reproduced the issue yet.

Feel free to reopen if you can provide a minimal reproducer.