Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

Not sure why, but it is happy sending a GET to the FastCGI backend (Mercurial hgwebdir in this case), but simply resorts to the filesystem if the request is a POST.

Relevant parts of nginx.conf:

    location / {
        root /var/www/htdocs/;
        index index.html;
        autoindex on;
    }

    location /hg {
        fastcgi_pass unix:/var/run/hg-fastcgi.socket;
        include fastcgi_params;

        if ($request_uri ~ ^/hg([^?#]*)) {
            set $rewritten_uri $1;
        }

        limit_except GET {
            allow all;
            deny all;

            auth_basic "hg secured repos";
            auth_basic_user_file /var/trac.htpasswd;
        }

        fastcgi_param SCRIPT_NAME "/hg";
        fastcgi_param PATH_INFO $rewritten_uri;

        # for authentication
        fastcgi_param AUTH_USER $remote_user;
        fastcgi_param REMOTE_USER $remote_user;

        #fastcgi_pass_header Authorization;
        #fastcgi_intercept_errors on;
    }

GET's work fine, but POST delivers this error to the error_log:

2010/05/17 14:12:27 [error] 18736#0: *1601 open() "/usr/html/hg/test" failed (2: No such file or directory), client: XX.XX.XX.XX, server: domain.com, request: "POST /hg/test HTTP/1.1", host: "domain.com"

What could possibly be the issue? I'm trying to allow read-only access via GET's to the page, but require authorization when using hg push to the same url which sends a POST request.

share|improve this question
add comment

2 Answers

This was a bug in nginx which was fixed in 0.8.48.

BTW, you have to use fastcgi_split_path_info as if does not get triggered correctly with limit_except.

So at the end something like that should work for you:

location /hg {
    fastcgi_pass unix:/var/run/hg-fastcgi.socket;
    include fastcgi_params;

    limit_except GET HEAD {
        auth_basic "hg secured repos";
        auth_basic_user_file /var/trac.htpasswd;
    }

    fastcgi_split_path_info ^(/hg)(.*)$;
    fastcgi_param SCRIPT_NAME $fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;

    # for authentication
    fastcgi_param AUTH_USER $remote_user;
    fastcgi_param REMOTE_USER $remote_user;
}
share|improve this answer
    
Awesome, thanks for the feedback. I will definitely be trying this out. –  dlamotte Mar 29 '11 at 15:24
add comment
up vote 1 down vote accepted

If anyone gets dug into the hole I did, here is how I dug out:

    location /hg {
        fastcgi_pass unix:/var/run/hg-fastcgi.socket;
        include fastcgi_params;

        if ($request_uri ~ ^/hg([^?#]*)) {
            set $rewritten_uri $1;
        }
        rewrite ^/hg$ /hg/ redirect;

        fastcgi_param SCRIPT_NAME "/hg";
        fastcgi_param PATH_INFO $rewritten_uri;

        # for authentication
        fastcgi_param AUTH_USER $remote_user;
        fastcgi_param REMOTE_USER $remote_user;

        fastcgi_intercept_errors on;
        error_page 401 = @hgauth;
    }

    location @hgauth {
        fastcgi_pass unix:/var/run/hg-fastcgi.socket;
        include fastcgi_params;

        if ($request_uri ~ ^/hg([^?#]*)) {
            set $rewritten_uri $1;
        }   
        auth_basic "hg secured repos";
        auth_basic_user_file /var/trac.htpasswd;

        fastcgi_param SCRIPT_NAME "/hg";
        fastcgi_param PATH_INFO $rewritten_uri;

        # for authentication
        fastcgi_param AUTH_USER $remote_user;
        fastcgi_param REMOTE_USER $remote_user;
    }

The important part is fastcgi_intercept_errors on;, error_page 401 = @hgauth;, and using location @hgauth {. I'm not sure it's possible to do this any other way. Please let me know if this answer helped!

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.