Magento 2 - Перенаправление Гео IP и лакирование


Мы запускаем магазин Magento 2.1.8 с модулем перенаправления IP-адресов Amasty Geo.

К сожалению, он неправильно работает с лаком. Амасти написал, что сейчас они не знают рабочего решения. Я поискал другие модули - все они сейчас не работают с лаком.

Есть ли у кого-нибудь идеи, как этого добиться?

Наше текущее состояние таково, что параметры сеанса для модуля перенаправления не записаны, и пользователь перенаправляется каждый раз. Так что переключение хранить невозможно.

Это серьезная проблема для нас. Отключение лака не является решением, так как необходимо повысить производительность.

Author: Johnny Longneck, 2017-09-19

5 answers

Ладно, похоже, у меня все получилось после борьбы. В нашем случае мы всегда перенаправляем первого посетителя в нужный магазин. Перенаправление непосредственно с Лака. Никакого обхода.

Это очень грязно, но если у кого-то есть лучшее решение, не стесняйтесь размещать его здесь.

Установить модуль ГеоИП Лака
https://rageagainstshell.com/2016/05/geoip-location-in-varnish/
Убедитесь, что вы клонировали правильную ветвь (относительно вашей версии лака) иначе это не сработает. В моем случае это было:
git clone https://github.com/varnish/libvmod-geoip --branch=4.1

Добавьте это в начало файла с лаком. (Скорее всего, в /etc/лак/default.vcl) добавить
import geoip;

Внутри раздела sub vcl_recv добавьте что-то вроде этого:

if (req.http.Cookie !~ "PHPSESSID=") {
    set req.http.X-Country-Code = geoip.country_code(req.http.X-Forwarded-For);
    if(req.url !~ "/(pub/)?(media|static)/") {
        if (req.url !~ "/de/" && req.http.X-Country-Code == "DE") {
            set req.http.subshop = "/de/";
            return (synth(750, "Redirect"));
        } elseif (req.url !~ "/us/" && req.http.X-Country-Code ~ "(US|MX|CA)") {
            set req.http.subshop ="/us/";
            return (synth(750, "Redirect"));
         }
    }
}

Если сеанс уже есть -> Неважно
В противном случае проверьте, не является ли запрос статическим файлом
Затем проверьте, находится ли пользователь уже в правильном магазине. В противном случае установите переменную для последующего использования (см. Ниже)
Возвращает ошибку синтезатора.

В нижней части ваш файл по умолчанию.vcl добавьте это для перенаправления:

sub vcl_synth {
    if (resp.status == 750) {
    if(req.url != resp.http.Location) {
    set resp.status = 301;
    set resp.http.Location = req.http.subshop + regsuball(req.url, "^(/de/|/us/|)","")
    }
    return (deliver);
    }
}

Сначала предотвратите циклы перенаправления. Установить статус ответа на перенаправление Удалите коды store_view_codes из URL-адреса и замените его правильным.

 2
Author: Johnny Longneck, 2018-03-14 14:47:24

Я реализовал то, что, на мой взгляд, является лучшим сверхпроектным решением, по крайней мере, для нашего варианта использования. Мы не используем Гео-IP-перенаправление Amasty. Вместо этого мы решили разработать собственное индивидуальное решение, которое, вероятно, в конечном итоге оказалось довольно похожим. Плагин для метода отправки интерфейсного контроллера, я полагаю?

Наш вариант использования

Мы запускаем несколько веб-сайтов, каждый с одной группой/магазином, и все они находятся в одном домене. Наши веб-сайты относятся к нашим регионам обслуживания, поэтому имеют очень динамические страны, заданные в конфигурации Magento.

Наши требования

  • Посетители в первый раз никогда не должны обходить кэш лаков, по крайней мере, не для рендеринга страницы.
  • Лак должен обслуживать правильную версию из кэша на основе гео-IP.
  • Конфигурация Magento все равно должна определять, какой веб-сайт обслуживается, поэтому виртуальные модули GeoIP и жестко закодированные регулярные выражения отсутствуют.

Наше Решение

Давайте извлекем заголовок X-Magento-Vary из серверная часть, использующая легкую конечную точку, затем используйте ее для обслуживания правильной страницы из кэша. Это позволит первым делом доставить посетителей в нужный регион, что минимально повлияет на производительность. После долгих исследований я решил решить эту проблему с помощью cUrl VMOD. HTTP VMOD не был для нас вариантом, потому что мы используем Varnish v4.

Вот основной рэп:

  1. Добавьте облегченную конечную точку в пользовательский модуль Magento для возврата заголовка X-Magento-Vary. Я добавил простое контроллер, который возвращает RESULT_RAW без содержимого, только заголовки. Эта конечная точка должна выполнить логику в вашем модуле перенаправления, чтобы установить правильное хранилище, самое главное, обновив значения контекста HTTP, чтобы убедиться, что в файлах cookie возвращается правильная строка vary.

  2. Установите VMOD curl: https://github.com/varnish/libvmod-curl

  3. Объедините следующее в свой файл .vcl, заменив путь завитка своим легким конечная точка

`

... Import the cUrl VMOD

import curl;

...

sub vcl_recv {

... # After all your return(pass) logic, get vary header from the backend if not yet checked

    # For first time visitors, determine X-Magento-Vary hash via backend API call that uses geo-ip
    if (req.http.cookie !~ "X-Varnish-GeoIP=") {

        # Copy required headers. Host and Proto prevent redirect, 
        # Forwarded-For sets correct IP for geo-IP lookup behind proxies
        curl.header_add("X-Forwarded-For: " + req.http.X-Forwarded-For);
        curl.header_add("X-Forwarded-Proto: https");
        curl.header_add("Host: " + req.http.host);
        curl.get("http://127.0.0.1:8080/geoip/redirect/varnishService");

        if (curl.header("Set-Cookie") ~ "X-Magento-Vary="){

            if (req.http.cookie){
                set req.http.cookie = req.http.cookie + 
                    "; " + regsub(curl.header("Set-Cookie"), "^.*?(X-Magento-Vary=[^;]+);*.*$", "\1");
            } else {
                set req.http.cookie = regsub(curl.header("Set-Cookie"), "^.*?(X-Magento-Vary=[^;]+);*.*$", "\1");
            }

            # Set store cookies so it's sent back to the backend for a cache MISS. This prevents subsequent geo-IP lookup
            if (curl.header("Set-Cookie") ~ "store="){
                set req.http.cookie = req.http.cookie +  
                    "; " + regsub(curl.header("Set-Cookie"), "^.*?(store=[^;]+);*.*$", "\1");
            }
        }
    }

...     

}

...


sub vcl_deliver {

... An attempt has been made to get the Vary header, this cookie stops subsequent checks.

    if (curl.status() > 0){
        # It would be better to not rely on user-sent cookie but AFAIK there's not a way to store a persistent variable in varnish.
        if (resp.http.Set-Cookie){
            set resp.http.Set-Cookie = resp.http.Set-Cookie + "; X-Varnish-GeoIP=true; path=/; domain=" + req.http.Host + ";";
        } else {
            set resp.http.Set-Cookie = "X-Varnish-GeoIP=true; path=/; domain=" + req.http.Host + ";";
        }   
    }

...

}

`

Файл cookie X-Varnish-GeoIP гарантирует, что серверная часть в большинстве случаев вызывается только один раз. Это было лучшее решение, чем полагаться на файлы cookie магазина или сеанса.

Устранение неполадок

Я столкнулся с различными проблемами при реализации своего решения. Я тестировал как встроенные, так и настроенные на лак экземпляры Magento, так как хотел иметь возможность отключить лак, если у нас возникнут какие-либо проблемы. Вот некоторые с которыми я столкнулся.

  • Изначально мы использовали наблюдатель событий controller_action_predispatch для нашего перенаправления GeoIP. Это приводило к отсутствию кэша для встроенного кэша при первом посещении магазинов, отличных от стандартного. Причина, по которой это произошло, заключается в том, что кэш страниц использует плагин around, который всегда выполняется перед отправкой события. Мы перенесли нашу логику перенаправления в плагин BeforeMethod с сортировщиком-1, чтобы гарантировать, что он всегда выполняется перед кэшем страницы плагины.

  • При переключении на новое представление магазина убедитесь, что вы также обновили объект \Magento\Framwork\App\Http\Context новыми значениями. Невыполнение этого требования может привести к кэшированию возвращаемой страницы с использованием неправильной строки X-Magento-Vary.

Ниже приведен код, который мы используем для установки нового представления магазина в нашем плагине bEforeDispatch (точно имитирует \Magento\Store\Модель\Storeswitcher). Обратите внимание, что в хранилище по умолчанию нет файла cookie хранилища или набора заголовков, который является По умолчанию в Magento.

`

$this->storeManager->setCurrentStore($store->getCode());

$defaultStoreView = $this->storeManager->getDefaultStoreView();
if ($defaultStoreView !== null) {
    if ($defaultStoreView->getId() === $store->getId()) {
        $this->storeCookieManager->deleteStoreCookie($store);
        $this->httpContext->unsValue(Store::ENTITY);
        $this->httpContext->unsValue(Context::CONTEXT_CURRENCY);
    } else {
        $this->httpContext->setValue(Store::ENTITY, $store->getCode(), $defaultStoreView->getCode());
        $this->httpContext->setValue(Context::CONTEXT_CURRENCY, $store->getDefaultCurrencyCode(), $defaultStoreView->getDefaultCurrencyCode());
        $this->storeCookieManager->setStoreCookie($store);
    }
}

`

Другое Решение?

Эта проблема более или менее исчезла бы, если бы мы использовали отдельные домены для каждого представления магазина. Созданный Magento vcl добавляет домен в хэш, поэтому при использовании отдельных доменов внутренний поиск в этом решении по существу заменяется любым посещаемым доменом. Однако в этом случае пользователи, которые вошли через неправильный домен, не будут перенаправлены на нужный веб-сайт. Это еще одно преимущество нашего решения, хотя и накладные расходы на вызов внутреннего API.

 1
Author: micwallace, 2020-05-10 07:43:21

У Amasty есть частичное решение здесь Путем обхода лака, если это пользователи, впервые посещающие сайт.

 0
Author: Chris Rogers, 2018-03-01 05:27:13

После того, как я сошел с ума, чтобы найти решение для этого, наконец, я получил рабочее решение для Magento 2.3.2 + Лак + GeoIP. Для этого вы можете использовать Cache Context и Page Variations, которые очень просты в реализации.

Сначала создайте плагин в свой модуль для Magento\Framework\App\Http\Context.

Файл: app/code/Vendor/YourModule/etc/di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Framework\App\Http\Context">
        <plugin name="atwix_country_cache_context_plugin"
            type="Vendor\YourModule\Plugin\CustomerCountryCacheContextPlugin" />    
    </type>
</config>

Затем реализация плагина

Файл: Vendor/YourModule/Plugin/CustomerCountryCacheContextPlugin.php

/**
 * Plugin on \Magento\Framework\App\Http\Context
 */
class CustomerCountryCacheContextPlugin
{
    public function __construct(
        \Magento\Customer\Model\Session $customerSession
    ) {
        $this->customerSession = $customerSession;
    }
    /**
     * \Magento\Framework\App\Http\Context::getVaryString is used by Magento to retrieve unique identifier for selected context,
     * so this is a best place to declare custom context variables
     */
    function beforeGetVaryString(\Magento\Framework\App\Http\Context $subject)
    {
        $country = $this->yourWayToGetTheCountry();
        $defaultCountryContext = 'Brazil';
        $subject->setValue('CONTEXT_AGE', $country, $defaultCountryContext);
    }
}

И последний шаг - добавить файл cookie X-Magento-Vary для передачи контекста на HTTP-слое в вашем лаке.

sub vcl_hash {
    if (req.http.cookie ~ "X-Magento-Vary=") {
        hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1"));
    }
    ... more ...
}

Для получения дополнительной информации посетите:

Https://devdocs.magento.com/guides/v2.3/extension-dev-guide/cache/page-caching/public-content.html#configure-page-variations

Https://www.atwix.com/magento-2/cache-context-and-page-variations-in-magento-2/

 0
Author: jackcar, 2019-09-26 21:57:24

Я нашел простой способ решить свою проблему, просто обновив способ хэширования моего запроса: в моем случае я использую cloudflare, и он отправляет дополнительный запрос на мой сервер, и я использовал этот запрос для создания уникального хэша на его основе:

В файл VCL

sub vcl_hash {
if (req.http.cookie ~ "X-Magento-Vary=") {
    hash_data(regsub(req.http.cookie+req.http.cf-ipcountry, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1"));
}

# For multi site configurations to not cache each other's content
if (req.http.host) {
    hash_data(req.http.host+req.http.cf-ipcountry);
} else {
    hash_data(server.ip+req.http.cf-ipcountry);
}

# To make sure http users don't see ssl warning
#if (req.http.X-Forwarded-Proto) {
#    hash_data(req.http.X-Forwarded-Proto);
#}


if (req.url ~ "/graphql") {
    call process_graphql_headers;

enter image description here

Теперь первый пользователь из новой страны будет пропущен, а другой - из кэша

Для получения более подробной информации мой первый пост здесь

Https://magento2develop.blogspot.com/2020/02/geoip-magento-2-varnish-cloudflare.html

 0
Author: Tarek Adra, 2020-02-19 08:42:49