3 votes

Mercurial ne reçoit pas de push

J'ai un web-frontend mercurial (hgwebdir.cgi) installé sur un serveur, et une installation de nginx a été installée en face de celui-ci comme un reverse proxy vers le web-frontend comme l'a suggéré mon ami. Cependant, chaque fois qu'un grand jeu de modifications est poussé (via un script), il échoue. J'ai trouvé un ticket de problème @google-code qui décrivent un problème similaire, et il y a une solution qui dit (#39)

La réponse côté serveur est donc la suivante : ne pas renvoyer le 401 plus tôt. Soyez aussi lent/imbécile que 'hg serve' et faites en sorte que le client hg envoie le bundle deux fois.

Comment faire ? Ma configuration actuelle de 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;
}

Dans le journal d'accès, nous voyons toujours 408 entrées

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"

Y a-t-il autre chose que je puisse faire sur le serveur car il est préférable de résoudre le problème du côté du serveur :/

Autres conclusions

Bitbucket semble avoir résolu ce problème (voir le projet liquidhg bitbucket et la page wiki Diagnosis) côté serveur, mais je ne trouve la configuration nulle part :/

  1. Ce qui se passe ensuite varie en fonction de votre serveur. Certains serveurs refusent le BODY, fermant simplement le tuyau du client et du client et provoquent l'échec de Mercurial échoue. D'autres, comme Apache (du moins tel que je le configure), et cela pourrait être une partie du problème) et nginx (la façon dont BitBucket.org le configure), acceptent le BODY acceptent le BODY, bien que cela puisse prendre quelques tentatives. Conclusion : si Mercurial n'échoue pas le push, il envoie le changeset au moins une fois à un serveur qui lui a déjà dit qu'il manque d'informations d'identification (plus d'informations à ce sujet à Blame).
  2. En supposant que Mercurial fonctionne toujours, il renvoie la demande de "dégroupage" et les données et les données, cette fois avec l'authentification.
  3. Enfin, Apache accepte les données avec succès. Nginx, quant à lui, au moins dans la configuration de BitBucket, semble réassembler les données (celui qui n'avait pas d'authentification ) et empêcher d'une manière ou d'une autre Mercurial de renvoyer l'ensemble du entier.

1voto

durin42 Points 241

Le problème est que httplib est half-duplex et que les serveurs qui ferment agressivement les sockets après avoir répondu (nginx entre autres) font que httplib écrit dans un tuyau cassé. Il y a une solution de fortune pour cela dans la version 1.4, mais elle ne rend pas vraiment les choses plus rapides, juste moins susceptibles de s'effondrer complètement. Je ne sais pas comment configurer nginx pour faire ce que vous voulez, mais je sais que BitBucket a le même problème sur des poussées suffisamment importantes.

Quelle version d'Apache et de nginx utilisez-vous ? Cela pourrait être un bon moyen pour moi d'avoir une configuration de test plus "complète".

Qu'utilisez-vous pour l'authentification ? Quelque chose dans le binaire Apache ? Il se peut qu'Apache ferme la porte trop rapidement après l'échec de l'authentification.

Par ailleurs, à titre d'information, liquidhg est le merveilleux travail de Brad Olson, et est simplement hébergé sur BitBucket. Je tenais simplement à rendre à César ce qui appartient à César.

0voto

ZoFreX Points 288

J'ai passé des heures à essayer de faire fonctionner hgwebdir avec nginx et c'est un peu compliqué, parce que hgwebdir n'envoie pas la requête au navigateur pour l'authentification. Finalement, j'ai résolu le problème comme suit :

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

C'est la seule façon de procéder, car limit_except ne peut pas être combiné avec fastcgi_pass - en fait, aucune condition ne peut l'être, mais elles peuvent être combinées avec proxy_pass. Je ne sais pas pourquoi.

Comment cela fonctionne-t-il ? Si une requête GET arrive, elle est immédiatement transmise à hgwebdir. Si une requête POST (c'est-à-dire un push) arrive, la requête est transmise en amont au proxy sur le port 81 qui toujours demande une authentification de base, ce qui permet de s'assurer qu'elle a bien lieu.

Pourquoi l'emplacement avec l'énorme expression rationnelle ? Ce sont des projets protégés pour lesquels je veux exiger une authentification, même pour l'accès en lecture.

Pourquoi l'écoute sur le port 10240 ? Je ne me souviens pas de la raison de sa présence.

Oh, et j'utilise wsgi avec spawn-fcgi, c'est pourquoi c'est fastcgi_pass. Cette configuration exacte ne vous conviendra probablement pas, mais j'espère que la même astuce résoudra vos problèmes de poussée.

0voto

J'ai eu un problème similaire récemment et j'ai refusé d'essayer le listen 81 solution de rechange. J'ai trouvé ceci. Je pense que nous avons des problèmes similaires, jetez un coup d'œil ici pour ma question/réponse : Nginx n'envoie pas de POST au backend FastCGI, mais GET fonctionne correctement ?

0voto

Chedy2149 Points 111

Pourquoi ne pas le faire tout simplement :

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

Cela fonctionne depuis nginx 0.8.48, dans les versions antérieures il y avait un bug où fastcgi_pass n'a pas été hérité à l'intérieur du bloc limit_except.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X