Mercurial não recebendo push

3

Eu tenho um web-frontend mercurial (hgwebdir.cgi) instalado em um servidor, e uma instalação do nginx foi instalada na frente dele como um proxy reverso para o frontend web, como meu amigo sugeriu. No entanto, sempre que um changeset grande for enviado (por meio de um script), ele falhará. Eu encontrei um @ google-code para o problema que descreve um problema semelhante, e há um solução que diz (# 39)

So the server side answer is: don't send the 401 back early. Be as slow/dumb as 'hg serve' and make the hg client send the bundle twice.

Como faço isso? Minha configuração atual do 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;
}

No log de acesso, continuamos vendo 408 entradas

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"

Existe mais alguma coisa que eu possa fazer no servidor porque resolvê-lo no lado do servidor é preferível: /

Outras descobertas

Bitbucket parece ter resolvido isso (Check liquidhg bitbucket project e Diagnosis wiki page) no lado do servidor, mas não consegue encontrar a configuração em nenhum lugar: /

  1. O que acontece em seguida varia dependendo no seu servidor. Alguns servidores recusam o CORPO, simplificando o fechamento do tubo do cliente e causando Mercurial para falhar. Alguns, como o Apache (pelo menos do jeito que eu configuro, e isso poderia fazer parte do problema) e nginx (caminho BitBucket.org configura), aceita o CORPO, embora possa levar alguns tenta novamente. Resumindo: se Mercurial não falha o empurrão, ele envia o dados do changeset pelo menos uma vez para um servidor que já disse isso carece de credenciais (mais sobre isso em Culpa).
  2. Supondo que o Mercurial ainda esteja em execução, ele reenvia a solicitação "unbundle" e dados, desta vez com autenticação.
  3. Finalmente, o Apache aceita os dados com sucesso. Nginx, OTOH, pelo menos sob a configuração do BitBucket, parece remontar o anterior corpo (aquele que faltava autenticação) e de alguma forma manter Mercurial de re-enviar o todo corpo.
por Jeffrey04 18.11.2009 / 04:05

4 respostas

0

Eu passei muito tempo tentando fazer o hgwebdir trabalhar com o nginx e é um pouco difícil, porque o hgwebdir não envia a solicitação para o navegador para autenticação. No final resolvi assim:

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;
}

Esta é a única maneira que você pode fazer isso, na verdade, já que limit_except não pode ser combinado com fastcgi_pass - na verdade, nenhuma condicional pode, mas eles são combinados com proxy_pass. Não faço ideia do porquê.

Então, como isso funciona? Se uma solicitação GET chegar, ela será enviada para o hgwebdir imediatamente. Se um POST (ou seja, um push) entrar, o pedido se desloca para o proxy na porta 81, o que sempre solicita a autenticação básica, garantindo assim que isso aconteça.

Por que o local com o enorme regex? Esses são projetos protegidos que eu quero exigir autenticação para acesso de leitura.

Por que ouvir na porta 10240? Não me lembro porque está lá.

Ah, e estou usando o wsgi com o spawn-fcgi, e é por isso que ele é fastcgi_pass. Esta configuração exata provavelmente não será a certa para você, mas esperamos que o mesmo truque resolva suas dificuldades de empurrar.

    
por 01.01.2010 / 14:21
1

O problema é que o httplib é half-duplex e servidores que encerram agressivamente sockets após responder (nginx entre eles) fazem o httplib gravar em um pipe quebrado. Há uma solução de band-aid para isso em 1.4, mas isso não torna as coisas realmente mais rápidas, é menos provável que elas desmoronem completamente. Eu não sei como configurar o nginx para fazer o que você quer, mas eu sei que em pushes suficientemente grandes, o BitBucket tem esse mesmo problema.

Qual versão do Apache e do nginx você está usando? Pode ser uma boa maneira de ter uma configuração de teste mais "completa".

O que você está usando para autenticação? Algo no binário do Apache? Pode ser que o Apache esteja batendo a porta rapidamente depois de ter falhado a autenticação.

Além disso, FWIW, liquidhg é o trabalho maravilhoso de Brad Olson, e é meramente hospedado no BitBucket. Só queria dar crédito onde é devido.

    
por 22.12.2009 / 15:11
0

Eu tive um problema semelhante recentemente e me recusei a testar a solução listen 81 . Eu inventei isso. Acho que temos problemas semelhantes, confira aqui a minha pergunta / resposta: O Nginx não enviará o POST para o backend FastCGI, mas o GET funciona bem?

    
por 17.05.2010 / 22:24
0

Por que não simplesmente:

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;
}

Funciona desde o nginx 0.8.48, em versões mais antigas havia um bug em que fastcgi_pass não era herdado dentro do bloco limit_except.

    
por 12.03.2011 / 14:54