Mercurial 没有收到推送

Mercurial 没有收到推送

我在服务器上安装了 mercurial web-frontend (hgwebdir.cgi),并按照朋友的建议在它前面安装了 nginx 作为 web-frontend 的反向代理。但是,每当推送大型变更集(通过脚本)时,它都会失败。我找到了一个问题单@google-代码描述了类似的问题,并且有一个解决方案说(#39)

因此,服务器端的答案是:不要过早地发回 401。像“hg serve”一样慢/笨,并让 hg 客户端发送两次包。

我该怎么做?我当前的 nginx 配置

location /repo/testdomain.com {
    rewrite ^(.*) http://bpj.kkr.gov.my$1/hgwebdir.cgi;
}
location /repo/testdomain.com/ {
    rewrite ^(.*) http://bpj.kkr.gov.my$1hgwebdir.cgi;
}
location /repo/testdomain.com/hgwebdir.cgi {
    proxy_pass http://localhost:81/repo/testdomain.com/hgwebdir.cgi;
    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_buffering on;
    client_max_body_size 4096M;
    proxy_read_timeout 30000;
    proxy_send_timeout 30000;
}

从访问日志中我们不断看到 408 条条目

incoming.ip.address - - [18/Nov/2009:08:29:31 +0800] "POST /repo/testdomain.com/hgwebdir.cgi/example_repository?cmd=unbundle&heads=73121b2b6159afc47cc3a028060902883d5b1e74 HTTP/1.1" 408 0 "-" "mercurial/proto-1.0"
incoming.ip.address - - [18/Nov/2009:08:37:14 +0800] "POST /repo/testdomain.com/hgwebdir.cgi/example_repository?cmd=unbundle&heads=73121b2b6159afc47cc3a028060902883d5b1e74 HTTP/1.1" 408 0 "-" "mercurial/proto-1.0"

我还可以在服务器上做什么吗?因为最好在服务器端解决它:/

进一步的发现

Bitbucket 似乎已经在服务器端解决了这个问题(检查 liquidhg bitbucket 项目和诊断 wiki 页面),但是在任何地方都找不到配置 :/

  1. 接下来发生的情况取决于您的服务器。有些服务器拒绝 BODY,只是关闭来自客户端的管道并导致 Mercurial 失败。有些服务器,如 Apache(至少是我配置的方式,这可能是问题的一部分)和 nginx(BitBucket.org 配置的方式),接受 BODY,尽管可能需要重试几次。底线:如果 Mercurial 没有使推送失败,它会将变更集数据至少发送一次到已经告诉它缺少凭据的服务器(有关此内容的更多信息,请参阅 Blame)。
  2. 假设 Mercurial 仍在运行,它会重新发送“解除捆绑”请求和数据,这次带有身份验证。
  3. 最后,Apache 成功接受了数据。另一方面,Nginx 至少在 BitBucket 的配置下似乎重新组合了之前的主体(缺少身份验证的主体),并以某种方式阻止 Mercurial 重新发送整个主体。

答案1

我花了很长时间尝试让 hgwebdir 与 nginx 协同工作,但这有点麻烦,因为 hgwebdir 不会将请求发送到浏览器进行身份验证。最后我这样解决了它:

server {
        listen 80;
        listen 10240;
        server_name code.zofrex.com;
        access_log /home/zofrex/websites/code.zofrex.com/logs/access.log;
        error_log /home/zofrex/websites/code.zofrex.com/logs/errors.log;

        location / {
                limit_except GET {
                        proxy_pass http://localhost:81;
                }
                fastcgi_pass 127.0.0.1:10001;
                include fastcgi_params;
        }

        location ~ ^/(HGBot|ZeroBotAHD|zoebot|FZeroZBot|RDPrototype|RSPS3000|zerobot|rmi)  {
                proxy_pass http://localhost:81;
        }

        include defaults;
}

server {
        listen 81;

        access_log /home/zofrex/websites/code.zofrex.com/logs/access_secure.log;
        error_log /home/zofrex/websites/code.zofrex.com/logs/errors_secure.log;

        location / {
                auth_basic           "Restricted";
                auth_basic_user_file /home/zofrex/passwords;
                fastcgi_pass 127.0.0.1:10001;
                include fastcgi_params;
        }

        include defaults;
}

这确实是你能做到的唯一方法,因为 limit_except 不能与 fastcgi_pass 结合使用 - 事实上没有条件可以,但它们可以与 proxy_pass 结合使用。不知道为什么。

那么它是如何工作的呢?如果收到 GET 请求,它会立即传递给 hgwebdir。如果收到 POST(即推送),请求会上传到端口 81 上的代理,然后总是提示基本身份验证,从而确保它发生。

为什么位置带有巨大的正则表达式? 这些都是受保护的项目,我希望即使是读取访问也需要身份验证。

为什么要监听 10240 端口?我不记得为什么会有这个端口。

哦,我使用的是 wsgi 和 spawn-fcgi,这就是为什么它是 fastcgi_pass。这个确切的配置可能不适合您,但希望同样的技巧可以解决您的推送问题。

答案2

问题是 httplib 是半双工的,响应后主动关闭套接字的服务器(其中包括 nginx)会导致 httplib 写入损坏的管道。1.4 版中有一个临时解决方法,但它并没有真正加快速度,只是不太可能完全崩溃。我不知道如何配置 nginx 来做你想做的事情,但我知道在足够大的推送时 BitBucket 也存在同样的问题。

您使用的是哪个版本的 Apache 和 nginx?这可能是我拥有更“完整”测试设置的好方法。

您使用什么进行身份验证?Apache 二进制文件中的某个东西?可能是 Apache 在身份验证失败后关闭大门太快了。

此外,FWIW,liquidhg 是 Brad Olson 的杰作,仅托管在 BitBucket 上。只是想给予应有的赞扬。

答案3

我最近遇到了类似的问题,但拒绝尝试listen 81解决方法。我想出了这个。我认为我们遇到了类似的问题,请在此处查看我的问题/答案:Nginx 不会将 POST 发送到 FastCGI 后端,但 GET 可以正常工作?

答案4

为什么不简单地这样做:

server {
    listen 80;
    listen 10240;
    server_name code.zofrex.com;
    access_log /home/zofrex/websites/code.zofrex.com/logs/access.log;
    error_log /home/zofrex/websites/code.zofrex.com/logs/errors.log;

    location / {
        fastcgi_pass 127.0.0.1:10001;
        include fastcgi_params;

        limit_except GET HEAD {
            auth_basic "Restricted";
            auth_basic_user_file /home/zofrex/passwords;
        }
    }

    location ~ ^/(HGBot|ZeroBotAHD|zoebot|FZeroZBot|RDPrototype|RSPS3000|zerobot|rmi)  {
        auth_basic "Restricted";
        auth_basic_user_file /home/zofrex/passwords;
    }

    include defaults;
}

它从 nginx 0.8.48 开始起作用,在旧版本中存在一个fastcgi_pass未在 limit_except 块内继承的错误。

相关内容