darkweak / souin

An HTTP cache system, RFC compliant, compatible with @tyktechnologies, @traefik, @caddyserver, @go-chi, @bnkamalesh, @beego, @devfeel, @labstack, @gofiber, @go-goyave, @go-kratos, @gin-gonic, @roadrunner-server, @zalando, @zeromicro, @nginx and @apache
https://docs.souin.io
MIT License
712 stars 56 forks source link

[BUG?] Apiplatform with souin PATCH reponse body: null #540

Closed g-ra closed 3 months ago

g-ra commented 3 months ago

image i have some trouble on patch method - on my general project, i dont use jsonld, maybe this is the problem? or because I have headlines somewhere?

in greeting project apip almost ok

null Response body upd the request itself is successful, and the data is entered into the database Response Headers

 accept-patch: application/json 
 cache-control: no-cache,private 
 cache-status: Souin; fwd=bypass; detail=UNSUPPORTED-METHOD 
 content-length: 4 
 content-type: application/json; charset=utf-8 
 date: Tue,06 Aug 2024 16:54:30 GMT 
 link: <http://localhost:81/docs.jsonld>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation" 
 permissions-policy: browsing-topics=() 
 server: Caddy 
 vary: Accept 
 x-content-type-options: nosniff 
 x-debug-token: 80a3d9 
 x-debug-token-link: http://localhost:81/_profiler/80a3d9 
 x-frame-options: deny 
 x-robots-tag: noindex 

api_platform.yaml

api_platform:

    show_webby: false
    mapping:
        paths: [ '%kernel.project_dir%/src/Entity', '%kernel.project_dir%/src/Document' ]
    http_cache:
        invalidation:
            # We assume that your API can reach your caddy instance by the hostname http://caddy.
            # The endpoint /souin-api/souin is the default path to the invalidation API.
            urls:
                - 'http://php/souin-api/souin'
            purger: api_platform.http_cache.purger.souin
    title: CRM Продажи
    version: 1.0.0
    # Mercure integration, remove if unwanted
    mercure:
        include_type: true
    formats:
        jsonld: ['application/ld+json']
    docs_formats:
        jsonld: ['application/ld+json']
        jsonopenapi: ['application/vnd.openapi+json']
        html: ['text/html']
    # Good defaults for REST APIs
    defaults:
        pagination_client_enabled: true
        stateless: true
        cache_headers:
            vary: ['Content-Type', 'Authorization', 'Origin']
        extra_properties:
            standard_put: true
            rfc_7807_compliant_errors: true
        pagination_items_per_page: 30
        formats:
            json: [ 'application/json' ]

    keep_legacy_inflector: false
#    use_symfony_listeners: true

    path_segment_name_generator: 'api_platform.metadata.path_segment_name_generator.dash'
    swagger:
        api_keys:
            JWT:
                name: Authorization
                type: header
            role:
                name: role
                type: header
            key:
                name: apiServiceKey
                type: header
    eager_loading:
        max_joins: 80

Caddyfile

# Caddyfile
{
    {$CADDY_GLOBAL_OPTIONS}

    frankenphp {
       {$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

    servers {
       metrics
    }

    cache {
        allowed_http_verbs GET POST PATCH
        api {
            prometheus
            souin
        }

        timeout {
            backend 10s
            cache 10ms
        }
    }

    log {
          output file /var/log/caddy/caddy_main.log {
          roll_size 100MiB
          roll_keep 5
          roll_keep_for 100d
       }
       format json
       level INFO
    }

    admin 0.0.0.0:2019
}

{$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
             }
          }
       }
    }

    cache
    root * /app/public
    encode zstd gzip

    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

    # Add links to the API docs and to the Mercure Hub if not set explicitly (e.g. the PWA)
    header ?Link `</docs.jsonld>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation", </.well-known/mercure>; rel="mercure"`
    # Disable Topics tracking if not enabled explicitly: https://github.com/jkarlin/topics
    header ?Permissions-Policy "browsing-topics=()"

    # Matches requests for HTML documents, for static files and for Next.js files,
    # except for known API paths and paths with extensions handled by API Platform
    # @pwa expression `(
    #     header({'Accept': '*text/html*'})
    #     && !path(
    #        '/docs*', '/graphql*', '/bundles*', '/contexts*', '/_profiler*', '/_wdt*',
    #        '*.json*', '*.html', '*.csv', '*.yml', '*.yaml', '*.xml'
    #     )
    #  )
    #  || path('/favicon.ico', '/manifest.json', '/robots.txt', '/_next*', '/sitemap*')`

    # Comment the following line if you don't want Next.js to catch requests for HTML documents.
    # In this case, they will be handled by the PHP app.
    # reverse_proxy @pwa http://{$PWA_UPSTREAM}

    @blocked {
       path /docs/*
       path /templates/*
    }
    respond @blocked 403

    php_server
}

Dockerfile

#syntax=docker/dockerfile:1.4

# Adapted from https://github.com/dunglas/symfony-docker

# Versions
FROM dunglas/frankenphp:latest-builder AS builder
COPY --from=caddy:builder /usr/bin/xcaddy /usr/bin/xcaddy

# Set environment variables for PIE
ENV CGO_ENABLED=1
ENV XCADDY_SETCAP=1
ENV XCADDY_GO_BUILD_FLAGS="-ldflags \"-w -s -extldflags '-Wl,-z,stack-size=0x80000'\""
ENV   CGO_CFLAGS="-fPIC" \
     CGO_LDFLAGS="-pie" \
     GOFLAGS="-buildmode=pie"
RUN xcaddy build \
    --output /usr/local/bin/frankenphp \
    --with github.com/dunglas/frankenphp \
    --with github.com/dunglas/frankenphp/caddy\
    --with github.com/dunglas/mercure/caddy \
    --with github.com/dunglas/vulcain/caddy \
    --with github.com/darkweak/souin/plugins/caddy@b0a36db1b550b66f768a3793701b69358200fed3 \
    --with github.com/darkweak/souin@b0a36db1b550b66f768a3793701b69358200fed3

FROM dunglas/frankenphp:latest AS frankenphp_upstream
COPY --from=builder --link /usr/local/bin/frankenphp /usr/local/bin/frankenphp

# Base FrankenPHP image
FROM frankenphp_upstream AS frankenphp_base

WORKDIR /app

RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends gnupg wget ca-certificates lsb-release; \
    wget -qO - https://www.mongodb.org/static/pgp/server-5.0.asc | gpg --dearmor -o /usr/share/keyrings/mongodb-archive-keyring.gpg; \
    echo "deb [signed-by=/usr/share/keyrings/mongodb-archive-keyring.gpg] http://repo.mongodb.org/apt/debian $(lsb_release -cs)/mongodb-org/5.0 main" | tee /etc/apt/sources.list.d/mongodb-org-5.0.list;

# Install system dependencies
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
        acl \
        file \
        gettext \
        git \
        mongodb-database-tools \
        libreoffice \
        supervisor \
        cron \
    && rm -rf /var/lib/apt/lists/*

# Install build tools and libraries
RUN apt-get update && apt-get install -y --no-install-recommends \
        build-essential \
        autoconf \
        libc6-dev \
        pkg-config

RUN curl -L -o /tmp/imagick.tar.gz https://github.com/Imagick/imagick/archive/7088edc353f53c4bc644573a79cdcd67a726ae16.tar.gz \
    && tar --strip-components=1 -xf /tmp/imagick.tar.gz \
    && phpize \
    && ./configure \
    && make \
    && make install \
    && echo "extension=imagick.so" > /usr/local/etc/php/conf.d/ext-imagick.ini \
    && rm -rf /tmp/* \

# Install PHP dependencies
RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        libicu-dev \
        libzip-dev \
        libgd-dev \
        imagemagick \
        libmagickwand-dev \
        libmagickcore-dev \
        libc-client-dev \
        libssl-dev \
        libkrb5-dev \
    ; \
    apt-get install -y php-imagick || echo "php-imagick not found, compiling from source..."; \
    rm -rf /var/lib/apt/lists/*; \
    docker-php-ext-configure imap --with-kerberos --with-imap-ssl; \
    docker-php-ext-install \
        intl \
        opcache \
        zip \
        bcmath \
        gd \
        imap \
    ; \
    pecl install mongodb; \
    docker-php-ext-enable mongodb;

# https://getcomposer.org/doc/03-cli.md#composer-allow-superuser
ENV COMPOSER_ALLOW_SUPERUSER=1

###> recipes ###
###> doctrine/doctrine-bundle ###
RUN set -eux; \
    install-php-extensions pdo_pgsql
###< doctrine/doctrine-bundle ###
###< recipes ###

# add custom font
COPY --link NotoSansFont.ttf ./
RUN mkdir -p /usr/share/fonts/truetype/
RUN install -m644 NotoSansFont.ttf /usr/share/fonts/truetype/
RUN rm ./NotoSansFont.ttf
#

COPY --link frankenphp/conf.d/app.ini $PHP_INI_DIR/conf.d/
COPY --link --chmod=755 frankenphp/docker-entrypoint.sh /usr/local/bin/docker-entrypoint
COPY --link frankenphp/Caddyfile /etc/caddy/Caddyfile

RUN chmod +x /usr/bin/supervisord

RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends $PHPIZE_DEPS; \
    pecl install excimer; \
    docker-php-ext-enable excimer; \
    apt-get remove -y $PHPIZE_DEPS; \
    apt-get autoremove -y; \
    apt-get clean; \
    rm -rf /var/lib/apt/lists/*

# Supervisor
ARG SUPERVISOR_ENABLED=false
ENV SUPERVISOR_ENABLED=$SUPERVISOR_ENABLED
RUN if [ "$SUPERVISOR_ENABLED" = 'true' ]; then \
        apt-get update && apt-get install -y supervisor && apt-get clean; \
    fi
RUN if [ "$SUPERVISOR_ENABLED" = 'true' ]; then \
        chmod +x /usr/bin/supervisord; \
    fi

COPY docker/supervisord/supervisord.conf /etc/supervisor/conf.d/supervisord.conf

ADD docker/cron/scheduler /etc/cron.d/scheduler
RUN touch /var/log/cron.log

COPY . /app

# Run the cron
RUN crontab /etc/cron.d/scheduler
ENTRYPOINT ["docker-entrypoint"]

HEALTHCHECK --start-period=60s CMD curl -f http://localhost:2019/metrics || exit 1
CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile" ]

# Dev FrankenPHP image
FROM frankenphp_base AS frankenphp_dev
ARG XDEBUG_MODE=off
ENV APP_ENV=dev XDEBUG_MODE=$XDEBUG_MODE PHP_IDE_CONFIG=serverName=xdebug-crm

VOLUME /app/var/

RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
COPY --link frankenphp/conf.d/app.dev.ini $PHP_INI_DIR/conf.d/

RUN if [ "$XDEBUG_MODE" = "debug" ]; then \
            apt-get update && apt-get install -y \
            gcc \
            make \
            autoconf \
            wget \
            && apt-get clean; \
        set -eux; \
        install-php-extensions xdebug; \
    fi

CMD [ "frankenphp", "run", "--config", "/etc/caddy/Caddyfile", "--watch" ]

# Test FrankenPHP image
FROM frankenphp_dev AS frankenphp_test
ENV APP_ENV=test

# Prod FrankenPHP image
FROM frankenphp_base AS frankenphp_prod

ENV APP_ENV=prod
ENV FRANKENPHP_CONFIG="import worker.Caddyfile"

RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

COPY --link frankenphp/conf.d/app.prod.ini $PHP_INI_DIR/conf.d/
COPY --link frankenphp/worker.Caddyfile /etc/caddy/worker.Caddyfile

# prevent the reinstallation of vendors at every changes in the source code
COPY --link composer.* symfony.* ./
RUN set -eux; \
    composer install --no-cache --prefer-dist --no-dev --no-autoloader --no-scripts --no-progress

# copy sources
COPY --link . ./
RUN rm -Rf frankenphp/

RUN set -eux; \
    mkdir -p var/cache var/log; \
    composer dump-autoload --classmap-authoritative --no-dev; \
    composer dump-env prod; \
    composer run-script --no-dev post-install-cmd; \
    chmod +x bin/console; sync;
darkweak commented 3 months ago

Hello @g-ra IMHO that doesn't come from Souin but from your application. And I don't recommend to allow PATCH requests to be cached. Remove the PATCH from the allowed_http_verbs in the configuration.

g-ra commented 3 months ago

yes, it's possible that this is a bug after moving to new versions of libraries and the apiplatform itself