AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / server / 问题 / 1146183
Accepted
Predaytor
Predaytor
Asked: 2023-10-19 21:33:31 +0800 CST2023-10-19 21:33:31 +0800 CST 2023-10-19 21:33:31 +0800 CST

漆。如何使用 cookie 根据区域设置进行重定向?

  • 772

我需要为多语言站点实现基于 cookie 的重定向逻辑。我有 Next.js 中间件的工作代码,但不幸的是它无法在 Docker 的独立设置中工作(我不使用 Vercel)。

import { NextRequest, NextResponse } from 'next/server';

export const config = {
    matcher: [
        /*
         * Match all request paths except for the ones starting with:
         * - api (API routes)
         * - _next (static files)
         * - URLs ending with a file extension (e.g., .html, .js, .css, etc.)
         */
        '/((?!api|_next|\\.\\.).+)',
    ],
};

export function middleware(request: NextRequest) {
    const { pathname, search, defaultLocale, locale } = request.nextUrl;

    const localeCookie = request.cookies.get('NEXT_LOCALE')?.value;

    if (!localeCookie && locale !== defaultLocale) {
        return NextResponse.redirect(new URL(`/${defaultLocale}${pathname}${search}`, request.url));
    }

    if (localeCookie && locale !== localeCookie) {
        return NextResponse.redirect(new URL(`/${localeCookie}${pathname}${search}`, request.url));
    }

    return NextResponse.next();
}

我想实现 Varnish 设置而不是 Next.js 解决方案:

vcl 4.1;

import cookie;

sub vcl_recv {
    ...

    if (req.url ~ "^/_next" || req.url ~ "/api/" || req.url ~ "/\.(.*)$/") {
        return (pass);
    }

    # Extract the locale from the URL, the default locale is hidden
    if (req.url ~ "^/[a-z]{2}/") {
        set req.http.locale = regsub(req.url, "^/([a-z]{2})(/.*)?$", "\1");
    } else {
        set req.http.locale = "";
    }

    # Extract NEXT_LOCALE cookie
    if (req.http.cookie) {
        cookie.parse(req.http.cookie);
        set req.http.localeCookie = cookie.get("NEXT_LOCALE");
        set req.http.cookie = cookie.get_string();
    }

    // If locale is specified and NEXT_LOCALE is missing, redirect to the default locale.
    if (req.http.locale != "" && !req.http.localeCookie) {
        # set req.http.X-Redirect-Url = ...;
        return (synth(302));
    }
    // If NEXT_LOCALE is present and the locale is not equal to the locale from cookie, then redirect to the cookie locale
    else if (req.http.locale != "" && req.http.locale != req.http.localeCookie) {
        # set req.http.X-Redirect-Url = ...;
        return (synth(302));
    }

    ...

    return (hash);
}

sub vcl_synth {
    # Perform the actual redirection based on the X-Redirect-Url header
    if (resp.status == 302 && req.http.X-Redirect-Url) {
        set resp.http.location = req.http.X-Redirect-Url;
        set resp.reason = "Moved";
        return (deliver);
    }
}
varnish
  • 2 2 个回答
  • 128 Views

2 个回答

  • Voted
  1. Best Answer
    Predaytor
    2023-10-31T03:35:47+08:002023-10-31T03:35:47+08:00

    在 Chat-GPT 正则表达式的一点帮助下,我最终得到了更简单的基于 cookie 的重定向逻辑和默认(隐藏)区域设置处理。感谢您的建议。

    vcl 4.1;
    
    import std;
    import cookie;
    
    ...
    
    sub vcl_recv {
        ...
    
        // Bypass redirection logic for certain request paths
        if (req.url ~ "^/_next" || req.url ~ "/api/" || req.url ~ "/\.(.*)$/") {
            return (pass);
        }
    
        // Extract the locale from the URL
        if (req.url ~ "^/([a-z]{2})(/|$|\?)") {
            set req.http.X-Request-Locale = regsub(req.url, "^/([a-z]{2})(/|$|\?).*", "\1");
        }
    
        // Extract NEXT_LOCALE cookie
        if (req.http.cookie) {
            cookie.parse(req.http.cookie);
            set req.http.X-Next-Locale = cookie.get("NEXT_LOCALE");
            set req.http.cookie = cookie.get_string();
        }
    
        // If X-Next-Locale is `uk` (default) unset it
        if (req.http.X-Next-Locale == "uk") {
            unset req.http.X-Next-Locale;
        }
    
        // If X-Request-Locale is `uk` perform a 301 (Moved Permanently) redirect
        if (req.http.X-Request-Locale == "uk" && req.http.X-Next-Locale !~ "^(uk|ru)$") {
            set req.http.X-Status-Code = 301;
    
            // Remove the locale from the URL
            set req.url = regsub(req.url, "^/([a-z]{2})(/|$|\?)", "/\2");
    
            // Remove double slashes if present in the URL
            set req.url = regsuball(req.url, "//+", "/");
    
            return (synth(750));
        }
    
        // Perform a 307 (Temporary Redirect) redirect to X-Next-Locale (cookie locale) if:
        // X-Next-Locale is within existing locales and
        // X-Request-Locale is within existing locales or is missing and
        // X-Request-Locale (url locale) does not match X-Next-Locale (cookie locale)
        if (
            (req.http.X-Next-Locale ~ "^(uk|ru)$") &&
            (req.http.X-Request-Locale ~ "^(uk|ru)$" || !req.http.X-Request-Locale) &&
            (req.http.X-Next-Locale != req.http.X-Request-Locale)
        ) {
            set req.http.X-Status-Code = 307;
    
            if (req.url !~ "^/([a-z]{2})(/|$|\?)") {
                // If the URL doesn't contain a locale, add the X-Next-Locale to it
                set req.url = "/" + req.http.X-Next-Locale + req.url;
            } else {
                // If the URL already contains a locale, update it with X-Next-Locale
                set req.url = regsub(req.url, "^/([a-z]{2})(/|$|\?)", "/" + req.http.X-Next-Locale + "\2");
            }
    
            // Remove double slashes if present in the URL
            set req.url = regsuball(req.url, "//+", "/");
    
            return (synth(750));
        }
    
        // Remove any cookies left
        unset req.http.Cookie;
    
        return (hash);
    }
    
    sub vcl_synth {
        // Modify response status and location header for redirects
        if (resp.status == 750) {
            set resp.status = std.integer(req.http.X-Status-Code);
            set resp.http.location = "https://" + req.http.Host + req.url;
            set resp.reason = "Moved";
            return (deliver);
        }
    }
    

    PS 不要忘记绕过机器人用户代理的重定向。

    • 0
  2. Predaytor
    2023-10-31T21:36:30+08:002023-10-31T21:36:30+08:00

    如果有人对原始问题感兴趣,请“强制”重定向到默认区域设置,无论请求区域设置如何,除非设置了 cookie:

    vcl 4.1;
    
    import std;
    import cookie;
    
    sub vcl_recv {
        ...
    
        // Bypass redirection logic for certain request paths
        if (req.url ~ "^/_next" || req.url ~ "/api/" || req.url ~ "/\.(.*)$/") {
            return (pass);
        }
    
        // Extract the locale from the URL
        if (req.url ~ "^/([a-z]{2})(/|$|\?)") {
            set req.http.X-Request-Locale = regsub(req.url, "^/([a-z]{2})(/|$|\?).*", "\1");
        }
    
        // Extract NEXT_LOCALE cookie
        if (req.http.cookie) {
            cookie.parse(req.http.cookie);
            set req.http.X-Next-Locale = cookie.get("NEXT_LOCALE");
            set req.http.cookie = cookie.get_string();
        }
    
        // If X-Next-Locale is `uk` (default) unset it
        if (req.http.X-Next-Locale == "uk") {
            unset req.http.X-Next-Locale;
        }
    
        // If X-Next-Locale is not present and request locale is `uk` (default) perform a 301 (Moved Permanently) redirect
        if (req.http.X-Next-Locale !~ "^(uk|ru)$" && req.http.X-Request-Locale == "uk") {
            set req.http.X-Status-Code = 301;
    
            // Remove the locale from the URL
            set req.url = regsub(req.url, "^/([a-z]{2})(/|$|\?)", "/\2");
    
            // Remove double slashes if present in the URL
            set req.url = regsuball(req.url, "//+", "/");
    
            return (synth(750));
        }
    
        // If X-Request-Locale is within existing locales or X-Next-Locale is within existing locales and X-Request-Locale is missing and
        // X-Request-Locale (url locale) does not match X-Next-Locale (cookie locale)
        // redirect to X-Next-Locale (cookie) if present, or to the default locale if absent
        if (
            (req.http.X-Request-Locale ~ "^(uk|ru)$" || (req.http.X-Next-Locale ~ "^(uk|ru)$" && !req.http.X-Request-Locale)) &&
            (req.http.X-Next-Locale != req.http.X-Request-Locale)
        ) {
            // Perform a 307 (Temporary Redirect)
            set req.http.X-Status-Code = 307;
    
            // If the URL doesn't contain a locale, add the X-Next-Locale to it (the default locale is empty)
            if (req.url !~ "^/([a-z]{2})(/|$|\?)") {
                set req.url = "/" + req.http.X-Next-Locale + req.url;
            }
            // If the URL already contains a locale, update it with X-Next-Locale
            else {
                set req.url = regsub(req.url, "^/([a-z]{2})(/|$|\?)", "/" + req.http.X-Next-Locale + "\2");
            }
    
            // Remove double slashes if present in the URL
            set req.url = regsuball(req.url, "//+", "/");
    
            return (synth(750));
        }
    
        // Remove any cookies left
        unset req.http.Cookie;
    
        return (hash);
    }
    
    sub vcl_synth {
        ...
    }
    
    • 0

相关问题

  • 清漆配置仅缓存未登录用户

  • Varnish 缓存如何处理不同的域?

  • 缩放大文件下载?

  • Gzip 与反向代理缓存

  • 在 Windows XP 主机上使用虚拟化 linux 来宾评估 Varnish 的最简单方法是什么?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    新安装后 postgres 的默认超级用户用户名/密码是什么?

    • 5 个回答
  • Marko Smith

    SFTP 使用什么端口?

    • 6 个回答
  • Marko Smith

    命令行列出 Windows Active Directory 组中的用户?

    • 9 个回答
  • Marko Smith

    什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同?

    • 3 个回答
  • Marko Smith

    如何确定bash变量是否为空?

    • 15 个回答
  • Martin Hope
    Tom Feiner 如何按大小对 du -h 输出进行排序 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich 什么是 Pem 文件,它与其他 OpenSSL 生成的密钥文件格式有何不同? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent 如何确定bash变量是否为空? 2009-05-13 09:54:48 +0800 CST
  • Martin Hope
    cletus 您如何找到在 Windows 中打开文件的进程? 2009-05-01 16:47:16 +0800 CST

热门标签

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve