Проблема с лаком

Мы разрабатываем сайт с использованием React и Redux. Мы только что добавили кэш Varnish в наш API, и, хотя, кажется, что все работает хорошо при тестировании API на Postman, это не работает на нашем веб-сайте.

По какой-то причине все запросы API не выполняются с кодом состояния 401 в первый раз, когда они выполняются, однако они работают нормально после первого сбоя.

Такое поведение только начинается, когда мы добавили кэш Varnish, но мы не можем найти ошибку.

Файл конфигурации Varnish выглядит следующим образом:

vcl 4.0;

backend default {
    .host = ...;
    .port = ...;
}

sub vcl_backend_response {
    set beresp.ttl = 5m;

    # Don't cache non-200 responses
    if ( beresp.status != 200 ) {
        set beresp.ttl = 0s;
    }
    # Don't cache if "no-cache" or "private" on cache control
    if (beresp.http.cache-control ~ "(no-cache|private)" ||
        beresp.http.pragma ~ "no-cache") {
            set beresp.ttl = 0s;
    }

}

sub vcl_recv {
    # Do not cache Healthcheck call
    if (req.url == "/api/healthcheck") {
        return (pass);
    }

    # Do not cache POST methods
    if (req.method == "POST") {
        return (pass);
    }

    # Do not cache users' calls as each user will be different
    if (req.url ~ "\/api\/v[a-zA-Z0-9\.]+\/users\/.*") {
        return (pass);
    } 

    # Ensure that cache is enabled to any call to the API
    if (req.url ~ "/api/*") {
        return (hash);
    }   
}

sub vcl_deliver {
  if (req.url ~ "/api/*") {
    set resp.http.Access-Control-Allow-Headers = "Accept, Accept-Encoding, Authorization, Content-Type, Dnt, Origin, User-Agent, X-CSRFToken, X-Requested-With";
    return (deliver);
  } 
}

Что может происходить?

большое спасибо

2 ответа

Решение

Я наконец нашел свою проблему, в моем файле конфигурации отсутствовал возврат (хэш).

Правильный файл конфигурации выглядит следующим образом:

vcl 4.0;

backend default {
    .host = ...;
    .port = ...;
}

sub vcl_backend_response {
    set beresp.ttl = 5m;

    # Don't cache non-200 responses
    if ( beresp.status != 200 ) {
        set beresp.ttl = 0s;
    }
    # Don't cache if "no-cache" or "private" on cache control
    if (beresp.http.cache-control ~ "(no-cache|private)" ||
        beresp.http.pragma ~ "no-cache") {
            set beresp.ttl = 0s;
    }

}

sub vcl_recv {
    # Do not cache Healthcheck call
    if (req.url == "/api/healthcheck") {
        return (pass);
    }

    if (req.method != "GET" && req.method != "HEAD") {
        # We only deal with GET and HEAD by default
        return (pass);
    }

    # Do not cache users' calls as each user will be different
    if (req.url ~ "\/api\/v[a-zA-Z0-9\.]+\/users\/.*") {
        return (pass);
    }
    return (hash);
}

sub vcl_deliver {
  if (req.url ~ "/api/*") {
    set resp.http.Access-Control-Allow-Headers = "Accept, Accept-Encoding, Authorization, Content-Type, Dnt, Origin, User-Agent, X-CSRFToken, X-Requested-With";
    return (deliver);
  }
}

Я полагаю, что все еще буду публиковать сообщения для людей, которые применяют Varnish к запросам API, которые требуют какой-либо авторизации (даже если вы говорите, что решили свою проблему).

Если вам требуется авторизация для путей за пределами \/api\/v[a-zA-Z0-9\.]+\/users\/.* область действия, то 401 могут все еще происходить, потому что эти запросы могут все еще кэшироваться.

Кроме того, вы можете (и должны по соображениям производительности) также кэшировать аутентифицированные запросы. Простым решением этой проблемы и ошибки 401 будет изменение вашего кэша в зависимости от значения заголовка токена.

Решение 1.

Вы можете изменить код приложения, просто отправив дополнительный HTTP-заголовок: Vary: X-Token, Этого достаточно, чтобы указать Varnish, что кеш должен отличаться для разных пользователей вашего API.

Решение 2.

Если у вас нет возможности настроить приложение, вам может помочь какой-то VCL:

sub vcl_backend_response {
     if (!beresp.http.Vary) { # no Vary at all
        set beresp.http.Vary = "X-Token";
    } elsif (beresp.http.Vary !~ "X-Token") { # add to existing Vary
        set beresp.http.Vary = beresp.http.Vary + ", X-Token";
    }
    ...
}

PS вообще не рекомендуется ставить "трейлинг" return в vcl_recv чтобы гарантировать, что встроенные подпрограммы vcl_recv все еще будут работать.

Другие вопросы по тегам