• 搜索
  • 夜间模式
    ©2026  依刻学习 Theme by OneBlog

    依刻学习博客

    搜索
    标签
  • 首页>
  • 学习的一天>
  • 正文
  • nginx:location与反向代理

    2025年03月25日 18 阅读 0 评论 5203 字

    前言

    nginx复习,深入学习location与反向代理

    一开始学的时候就对于location与反向代理末尾/的问题烦恼了很久才有苗条,现在过了一段时间再来复习复习

    关于location

    location,路由规则,是配置再http的server中的,实际上就是匹配URI

    location <sign> <path> {}
    • sign

      sign含义
      =精确匹配(差一点都不行)
      ^~优先匹配,不支持正则
      ~区分大小写的正则匹配
      ~*不区分大小写的正则匹配
      !~区分大小写不匹配的正则
      !~*不区分大小写不匹配的正则
      空格普通匹配,不支持正则

      优先级

      1. = 一旦匹配到立刻停止匹配
      2. ^~ 匹配最长的,即全部扫描一遍
      3. ~,~\*,! ~,!~\ 一旦匹配到立刻停止匹配
      4. 空格 匹配最长的,即全部扫描一遍
    • path

      关于path末尾有无/的问题

      • 如果path末尾有/如/app/,那么只能匹配/app
      • 如果path末尾没有/如/app,那么可以匹配/app,也可以匹配/app/xxx

      关键点

      虽然path看上去是目录的层级,但是匹配起来不同于目录只需要 开头匹配

      例如访问 http://yk.cn/ABVFGTYHJNBG ,location匹配规则只有/和/A,它会匹配到/A!这个问题当初磨了好久才明白,这个匹配规则只要URI开头匹配上就行,后面不管(当然,请注意符号的优先级)

    关于proxy_pass

    这是反向代理的核心配置,我的理解就是nginx修改原始请求去访问后端服务器,然后返回给客户端

    这里面存在着两个很重要的问题

    1. nginx是如何修改原始请求的?
    2. 后端返回的请求如何给真实客户端?

    nginx修改原始请求(proxy_pass)

    如图,客户端请求的URI(/app/index.html?user=yk)会由proxy_pass进行处理

    location路径: /app/

    剩余原始URI: index.html?user=yk

    proxy_pass抽象意义转发URL
    http://192.168.1.1/server_name后有/就已有location路径,加剩余URIhttp://192.168.1.1/index.html?user=yk
    http://192.168.1.1/data/server_name后有/就已有location路径,加剩余URIhttp://192.168.1.1/data/index.html?user=yk
    http://192.168.1.1./dataserver_name后有/就已有location路径,加剩余URIhttp://192.168.1.1./dataindex.html?user=yk
    http://192.168.1.1server_name后无/就无location路径,加全部URIhttp://192.168.1.1/app/index.html?user=yk

    这个我也研究了不少时间,才搞明白,可以发现第三个实际上是错误的,也就是说proxy_pass尽可能末尾加/ ,这里给出我之前参考的博客nginx中proxy_pass的作用以及注意事项(不看后悔一生)_proxypass域名-CSDN博客

    讲的确实不错,给了我很多启发,但是对于为什么是这样加URI,我做出了更好的解释,就是server_name后有无/,有就加剩余URI,没有就加全部URI,这样记起来更加方便

    需要注意,不要与location的匹配弄混了,到了proxy_pass就已经匹配到location了,换句话说就是和location没有关系了

    nginx修改后端返回的请求URL(proxy_redirect)

    proxy_redirect指令用于重写后端返回的 Location 和 Refresh 响应头,确保客户端重定向时指向代理服务器而非后端服务器,一般用于后端响应301/302跳转

    简单介绍一下流程,后端301/302响应,要重定向,给nginx发了一个重定向的URL,nginx就要返回给客户端,但是这个URL客户端是无法使用的,因为它无法直接访问后端服务器,nginx就要修改URL,把他改成nginx的指定的location(有反向代理到该后端服务器的),这样再经过一遍反向代理就行了

    这里面也有两个重要的问题

    1. nginx是怎么修改后端响应的URL的?
    2. 客户端为什么能够凭这个URL进行重定向?
    • nginx修改后端响应的URL

      这是通过proxy_redirect实现的

      proxy_redirect有3个值: default/off/<regex\>

      proxy_redirect default

      • 当后端返回相对路径(如 Location: /new_path)时,Nginx 会将其拼接为 原请求的协议+Host(server_name)+相对路径,例如 http://ym.cn/new_path。
      • 当后端返回绝对路径(如 Location: http://backend:8080/new_path)时,Nginx 会尝试将 backend:8080 替换为当前代理服务器的 Host(server_name)。

      注意,默认拼接会丢弃原始请求的路径和参数,但是一般重定向是需要携带原来的参数的(这个具体看后端需不需要),此时就需要使用显式定义proxy_redirect

      # 替换后端绝对路径(这里替换目标可以省略Host)
      # http://backend:8080/index -> http://yk.cn/app/index
      proxy_redirect http://backend:8080/ /app/;
      #等价于(server_name yk.cn)
      proxy_redirect http://backend:8080/ http://yk.cn/app/;
      
      
      # 替换后端相对路径
      # /new_path/index --> http://yk.cn/app/new_path/index
      proxy_redirect /new_path /app/new_path; 
      # 动态拼接,保留原始参数
      # /new_path --> http://yk.cn/new_path?user=yk
      proxy_redirect /new_path /new_path$is_args$args;

      可以发现这些配置都是只能替换开头的,固定重定向(后端只有一个重定向响应)可以通过加长替换目标解决,但是如果后端有多个重定向呢?多个重定向的同时还需要添加参数

      最简单就是使用多个proxy_redirect解决,但是这样会显得臃肿,更高效的处理方式是使用正则匹配(基础正则)

      proxy_redirect ~^/new_path(/?.*)$ /new_path$1$is_args$args;
    • 客户端使用重定向URL

      客户端原始请求URL为http://ym.cn/data/index?name=user,后端重定向,nginx修改后返回的URL(假设协议为http,携带参数)为http://ym.cn/new_data/index?name=user

      可以发现,其实访问的域名都是一样的,因为proxy_redirect修改的时候使用原始协议+本server(这里就是ym.cn)+返回URI+原始参数(参数需要显式拼接)进行拼接,访问后就是重新走一遍反向代理流程,与初次请求除了反向代理的URI不同外没有任何区别

    后谈

    这里我其实还有一个问题没有解决,就是关于动态拼接时如果替换的只是开头的一部分,那么是否会在末尾添加参数?
    个人认为不会(纯猜测,没有验证过!!!),因为动态拼接时也可以手动添加参数,如果手动加了参数,nginx如何判断应不应该加参数?应该没有判断,根本不会自动拼接(猜测)

    # /new_path/index --> http://yk.cn/new_path?user=yk(index) ??
    #这里直接使用捕获组添加参数
    proxy_redirect /new_path /new_path$is_args$args;

    还是说必须使用捕获组才可以将这个index移至/new_path后,这个暂时无法验证,但是尽可能匹配全部URL可以避免犯错

    总结

    • location末尾加/
    • proxy_pass末尾加/
    • proxy_redirect尽量替换全部的响应URL而不是只替换开头的URL

    这些问题我搞明白至少花了一天的时间,有的时候最难的就是一些细节,一旦去验证就要花大把的时间

    本文著作权归作者 [ wymm ] 享有,未经作者书面授权,禁止转载,封面图片来源于 [ 互联网 ] ,本文仅供个人学习、研究和欣赏使用。如有异议,请联系博主及时处理。
    取消回复

    发表留言
    回复

    Copyright©2026  All Rights Reserved.  Load:0.032 s
    Theme by OneBlog V3.6.5
    夜间模式

    开源不易,请尊重作者版权,保留基本的版权信息。