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

Мы разрабатываем веб-сайт с 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);
  } 
}

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

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


person FVod    schedule 03.10.2017    source источник
comment
Основываясь на получении 401, который является неавторизованным, как вы аутентифицируете запросы API? Некоторое значение заголовка/параметр запроса/данные POST? Подробнее пожалуйста :)   -  person Danila Vershinin    schedule 03.10.2017
comment
Авторизация осуществляется через отправку токена в заголовке.   -  person FVod    schedule 03.10.2017


Ответы (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);
  }
}
person FVod    schedule 03.10.2017

Я полагаю, что по-прежнему буду публиковать сообщения для людей, которые применяют 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";
    }
    ...
}

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

person Danila Vershinin    schedule 03.10.2017