api-platform: Error 502 on some api routes "upstream sent too big header while reading response header from upstream"

Hello,

i’ve got 502 errors on some routes of my api on my dev machine running api-platform on docker.

The logs shows this :

api     | 2018/11/12 13:14:09 [error] 7#7: *6 upstream sent too big header while reading response header from upstream, client: 172.18.0.2, server: , request: "GET /v2/contact_functions HTTP/1.1", upstream: "fastcgi://172.19.0.4:9000", host: "api.test:8000", referrer: "http://api.test:8000/"
api     | 172.18.0.2 - - [12/Nov/2018:13:14:09 +0000] "GET /v2/contact_functions HTTP/1.1" 502 559 "http://api.test:8000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36" "172.18.0.1"

I’m not sure I get what’s wrong, it looks like it’s an nginx error. Can we add configs (it looks like fastcgi_buffers / fastcgi_buffer_size could help). Or is there a way to control these headers ?

On some other working routes, I can see a lot of informations under Cache-Tags Headers, could it be the problem ? Again, can I do something on these headers ?

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 2
  • Comments: 23 (11 by maintainers)

Commits related to this issue

Most upvoted comments

@purplefish32

This worked for me (api/docker/nginx/conf.d/default.conf) :

server {
    root /srv/api/public;

    location / {
        # try to serve file directly, fallback to index.php
        try_files $uri /index.php$is_args$args;
    }

    location ~ ^/index\.php(/|$) {
        # Comment the next line and uncomment the next to enable dynamic resolution (incompatible with Kubernetes)
        fastcgi_pass php:9000;
        #resolver 127.0.0.11;
        #set $upstream_host php;
        #fastcgi_pass $upstream_host:9000;

        fastcgi_buffer_size          128k;
        fastcgi_buffers              4 256k;

        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        # When you are using symlinks to link the document root to the
        # current version of your application, you should pass the real
        # application path instead of the path to the symlink to PHP
        # FPM.
        # Otherwise, PHP's OPcache may not properly detect changes to
        # your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
        # for more information).
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        # Prevents URIs that include the front controller. This will 404:
        # http://domain.tld/index.php/some-path
        # Remove the internal directive to allow URIs like this
        internal;
    }

    # return 404 for all other php files not matching the front controller
    # this prevents access to other php files you don't want to be accessible.
    location ~ \.php$ {
      return 404;
    }
}

fastcgi_busy_buffers_size does not exists for fastcgi

By the way, thank you all for your help !

What you’re looking for is fastcgi_buffer_size and friends.

This guide seems helpful: https://gist.github.com/magnetikonline/11312172

<?php

namespace App\EventListener;

use Symfony\Component\HttpKernel\Event\ResponseEvent;

class OverrideCacheTagsListener
{
    /**
     * Makes sure that the Cache-Tags header doesn't grow infinitely in larger projects
     */
    public function onKernelResponse(ResponseEvent $event): void
    {
        $request = $event->getRequest();
        $response = $event->getResponse();

        if (
            !$request->isMethodCacheable()
            || !$response->isCacheable()
        ) {
            return;
        }

        if ($response->headers->has('Cache-Tags') && strlen($response->headers->get('Cache-Tags')) > 32) {
            $response->headers->set('Cache-Tags', md5($response->headers->get('Cache-Tags')));
        }
    }
}
services:
    App\EventListener\OverrideCacheTagsListener:
        tags:
            - { name: kernel.event_listener, event: kernel.response, priority: -3 }

@janklan I can kiss you!! Thank you very much!

I am coming here from a strange Heroku issue: fetching 59 items from api platform works, but fetching 60 items I get a strange CORS error in the browser:

... blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource ...

Looking in the Heroku PHP logs I only find

Premature end of script headers: index.php and

Error parsing script headers

On Heroku there is no way to increase the Header Size. Thus, the headers have to be limited programatically.

Please Note: I had to update the first parameter of the onKernelResponse with a ResponseEvent

I was having this problem but only on the https version of the api (port :8443). To fix it I had to increase the buffer size of the h2-proxy (editing the file ./h2-proxy/conf.d/default.conf). Like this:

# api
server {
    listen 8443 ssl http2;
    listen [::]:8443 ssl http2;

    ssl_certificate /etc/nginx/ssl/cert.crt;
    ssl_certificate_key /etc/nginx/ssl/cert.key;

    location / {
        proxy_buffer_size 256k;       # added this line
        proxy_buffers 4 256k;         # added this line
        proxy_busy_buffers_size 256k; # added this line
        proxy_pass http://api;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Port 8443;
    }
}

Indeed we should change the default value, and add a section here: https://api-platform.com/docs/extra/troubleshooting/#troubleshooting

I think we could probably ship with a better default out of the box. 😄