nginx 位置块可以匹配 URL 查询字符串吗?

nginx 位置块可以匹配 URL 查询字符串吗?

nginx location匹配 URL 查询字符串?

例如,哪些位置块可能与 HTTPGET请求匹配

GET /git/sample-repository/info/refs?service=git-receive-pack HTTP/1.1

答案1

nginx 位置块可以匹配 URL 查询字符串吗?

简短回答: 不。

长答案:如果我们只有少数这样的位置块,那么有一个解决方法。

以下是需要匹配特定查询字符串的 3 个位置块的示例解决方法:

server {
  #... common definitions such as server, root
    
  location / {
    error_page 418 = @queryone;
    error_page 419 = @querytwo;
    error_page 420 = @querythree;

    if ( $query_string = "service=git-receive-pack" ) { return 418; }
    if ( $args ~ "service=git-upload-pack" ) { return 419; }
    if ( $arg_somerandomfield = "somerandomvaluetomatch" ) { return 420; }

    # do the remaining stuff
    # ex: try_files $uri =404;
    
  }

  location @queryone {
    # do stuff when queryone matches
  }

  location @querytwo {
    # do stuff when querytwo matches
  }

  location @querythree {
    # do stuff when querythree matches
  }
}

您可以使用 $query_string、$args 或 $arg_fieldname。所有这些都可以完成工作。您可能了解有关官方文档中的 error_page

警告:请务必不是使用标准 HTTP 代码

答案2

我知道这个问题已经存在一年多了,但最近几天我一直在为类似的问题绞尽脑汁。我想要针对公共和私人存储库使用不同的身份验证和处理规则,包括推送和拉取。这是我最终想到的,所以我想我会分享一下。我知道这if是一个棘手的指令,但这对我来说似乎很好用:

# pattern for all repos, public or private, followed by username and reponame
location ~ ^(?:\/(private))?\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?$ {

    # if this is a pull request
    if ( $arg_service = "git-upload-pack" ) {

        # rewrite url with a prefix
        rewrite ^ /upload$uri;

    }

    # if this is a push request
    if ( $arg_service = "git-receive-pack" ) {

        # rewrite url with a prefix
        rewrite ^ /receive$uri;

    }

}

# for pulling public repos
location ~ ^\/upload(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {

    # auth_basic "git";
    # ^ if you want

    # ...
    # fastcgi_pass unix:/var/run/fcgiwrap.socket;
    # ...

}

# for pushing public repos
location ~ ^\/receive(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {

    # auth_basic "git";
    # ^ if you want

    # ...
    # fastcgi_pass unix:/var/run/fcgiwrap.socket;
    # ...

}

# for pulling private repos
location ~ ^\/upload\/private(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {

    # auth_basic "git";
    # ^ if you want

    # ...
    # fastcgi_pass unix:/var/run/fcgiwrap.socket;
    # ...

}

# for pushing private repos
location ~ ^\/receive\/private(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {

    # auth_basic "git";
    # ^ if you want

    # ...
    # fastcgi_pass unix:/var/run/fcgiwrap.socket;
    # ...

}

答案3

如果您使用 nginx 作为代理,还有另一种方法可以做到这一点。

在服务器块中设置一个变量:

set $nocache="0";

在位置块内,添加 if:

if ( $arg_<query string to match> = "<query string value>") { set $nocache "1"; }

并添加两个新的代理指令:

proxy_cache_bypass $nocache ;
proxy_no_cache $nocache ;

它将始终转发到没有缓存的上游服务器

相关内容