{"thread":{"id":"42449","subject":"Why is my git-http-backend solution using WebDAV on push?","startedAt":"2016-05-25T20:28:21Z","lastAt":"2016-05-25T22:16:49Z","messageCount":5,"participants":["Luke Madhanga","Jeff King","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"287508","messageId":"CABwKKP958cW3a5Cjxox+1FCtNLetdufJj0rrYBouAUhJSXKKWA@mail.gmail.com","threadId":"42449","inReplyTo":null,"subject":"Why is my git-http-backend solution using WebDAV on push?","fromName":"Luke Madhanga","fromEmail":"lmadhanga@gmail.com","sentAt":"2016-05-25T20:28:21Z","receivedAt":"2016-05-25T20:28:21Z","isPatch":false,"sender":{"key":"lmadhanga@gmail.com","avatar":"https://gravatar.com/avatar/141fddedb95625908dbda3c232ca719e0f64ab01628f1bf22d5850ba116237b1?d=mp&s=160"},"body":"I've implemented a PHP wrapper for git http backend which works well.\nI've done this to give me advanced control of who has access to\nrepositories on my server. You can see the implementation on\nhttp://stackoverflow.com/questions/36998492/channel-git-on-the-server-calls-through-php/37242591#37242591.\nI can pull from the server okay and all works well. However, I cannot\npush. When I read my trace code to see where it fails, I see that the\nlast request is a PROPFIND request. The URL for this request does not\nhave any of the usual 'info/refs' etc. that one usually gets on git\ncalls.\n\nDuring reading of the documentation and reviewing how git-http-backend\nshould be implemented, I can see that it should not be making a WebDAV\nrequest. I have also come across posts where people implementing\nhttp-backend the 'normal' way have also had this problem, e.g.\nhttp://serverfault.com/questions/390864/git-push-over-http-using-git-http-backend-and-apache-is-not-working\n\n\n\nSo the question is, why is WebDAV being used on push?\n\n\n\n\nTrace code from the push:\n\n[2016-05-25 09:49:35] ==========================\n[2016-05-25 09:49:35] REQUEST: {\n    \"q\": \"p\\/git-backend\\/run\\/1\\/info\\/refs\",\n    \"service\": \"git-receive-pack\"\n}\n[2016-05-25 09:49:35] SERVER: {\n    \"REDIRECT_STATUS\": \"200\",\n    \"HTTP_HOST\": \"...\",\n    \"HTTP_USER_AGENT\": \"git\\/2.7.4\",\n    \"HTTP_ACCEPT\": \"*\\/*\",\n    \"HTTP_ACCEPT_ENCODING\": \"gzip\",\n    \"HTTP_ACCEPT_LANGUAGE\": \"en-GB, en;q=0.9, *;q=0.8\",\n    \"HTTP_PRAGMA\": \"no-cache\",\n    \"PATH\": \"...\",\n    \"SERVER_SIGNATURE\": \"<address>Apache\\/2.4.18 (Ubuntu) Server at\n... Port 80<\\/address>\\n\",\n    \"SERVER_SOFTWARE\": \"Apache\\/2.4.18 (Ubuntu)\",\n    \"SERVER_NAME\": \"...\",\n    \"SERVER_ADDR\": \"...\",\n    \"SERVER_PORT\": \"80\",\n    \"REMOTE_ADDR\": \"...\",\n    \"DOCUMENT_ROOT\": \"...\",\n    \"REQUEST_SCHEME\": \"http\",\n    \"CONTEXT_PREFIX\": \"\",\n    \"CONTEXT_DOCUMENT_ROOT\": \"...\",\n    \"SERVER_ADMIN\": \"...\",\n    \"SCRIPT_FILENAME\": \"...\",\n    \"REMOTE_PORT\": \"49630\",\n    \"REDIRECT_URL\": \"\\/p\\/git-backend\\/run\\/1\\/info\\/refs\",\n    \"REDIRECT_QUERY_STRING\":\n\"q=p\\/git-backend\\/run\\/1\\/info\\/refs&service=git-receive-pack\",\n    \"GATEWAY_INTERFACE\": \"CGI\\/1.1\",\n    \"SERVER_PROTOCOL\": \"HTTP\\/1.1\",\n    \"REQUEST_METHOD\": \"GET\",\n    \"QUERY_STRING\":\n\"q=p\\/git-backend\\/run\\/1\\/info\\/refs&service=git-receive-pack\",\n    \"REQUEST_URI\":\n\"\\/p\\/git-backend\\/run\\/1\\/info\\/refs?service=git-receive-pack\",\n    \"SCRIPT_NAME\": \"\\/index.php\",\n    \"PHP_SELF\": \"\\/index.php\",\n    \"REQUEST_TIME_FLOAT\": 1464162575.091,\n    \"REQUEST_TIME\": 1464162575\n}\n[2016-05-25 09:49:35] Path: /core.git/info/refs?service=git-receive-pack\n[2016-05-25 09:49:35] Cleaned, result only:\n[2016-05-25 09:49:35] f4648182f5f8eee082c37a83a0072cfc4210e5c5 refs/heads/master\n8c4efcd77809bc9b94a59cf94653add8007c6b7d refs/heads/zztest\n[2016-05-25 09:49:35] ==========================\n[2016-05-25 09:49:35] REQUEST: {\n    \"q\": \"p\\/git-backend\\/run\\/1\\/HEAD\"\n}\n[2016-05-25 09:49:35] SERVER: {\n    \"REDIRECT_STATUS\": \"200\",\n    \"HTTP_HOST\": \"...\",\n    \"HTTP_USER_AGENT\": \"git\\/2.7.4\",\n    \"HTTP_ACCEPT\": \"*\\/*\",\n    \"HTTP_ACCEPT_ENCODING\": \"gzip\",\n    \"HTTP_ACCEPT_LANGUAGE\": \"en-GB, en;q=0.9, *;q=0.8\",\n    \"HTTP_PRAGMA\": \"no-cache\",\n    \"PATH\": \"...\",\n    \"SERVER_SIGNATURE\": \"<address>Apache\\/2.4.18 (Ubuntu) Server at\n... Port 80<\\/address>\\n\",\n    \"SERVER_SOFTWARE\": \"Apache\\/2.4.18 (Ubuntu)\",\n    \"SERVER_NAME\": \"...\",\n    \"SERVER_ADDR\": \"...\",\n    \"SERVER_PORT\": \"80\",\n    \"REMOTE_ADDR\": \"...\",\n    \"DOCUMENT_ROOT\": \"...\",\n    \"REQUEST_SCHEME\": \"http\",\n    \"CONTEXT_PREFIX\": \"\",\n    \"CONTEXT_DOCUMENT_ROOT\": \"...\",\n    \"SERVER_ADMIN\": \"...\",\n    \"SCRIPT_FILENAME\": \"...\",\n    \"REMOTE_PORT\": \"49630\",\n    \"REDIRECT_URL\": \"\\/p\\/git-backend\\/run\\/1\\/HEAD\",\n    \"REDIRECT_QUERY_STRING\": \"q=p\\/git-backend\\/run\\/1\\/HEAD\",\n    \"GATEWAY_INTERFACE\": \"CGI\\/1.1\",\n    \"SERVER_PROTOCOL\": \"HTTP\\/1.1\",\n    \"REQUEST_METHOD\": \"GET\",\n    \"QUERY_STRING\": \"q=p\\/git-backend\\/run\\/1\\/HEAD\",\n    \"REQUEST_URI\": \"\\/p\\/git-backend\\/run\\/1\\/HEAD\",\n    \"SCRIPT_NAME\": \"\\/index.php\",\n    \"PHP_SELF\": \"\\/index.php\",\n    \"REQUEST_TIME_FLOAT\": 1464162575.266,\n    \"REQUEST_TIME\": 1464162575\n}\n[2016-05-25 09:49:35] Path: /core.git/HEAD\n[2016-05-25 09:49:35] Cleaned, result only:\n[2016-05-25 09:49:35] ref: refs/heads/master\n[2016-05-25 09:49:35] ==========================\n[2016-05-25 09:49:35] REQUEST: {\n    \"q\": \"p\\/git-backend\\/run\\/1\\/\"\n}\n[2016-05-25 09:49:35] SERVER: {\n    \"REDIRECT_STATUS\": \"200\",\n    \"HTTP_HOST\": \"...\",\n    \"HTTP_USER_AGENT\": \"git\\/2.7.4\",\n    \"HTTP_ACCEPT\": \"*\\/*\",\n    \"HTTP_DEPTH\": \"0\",\n    \"CONTENT_TYPE\": \"text\\/xml\",\n    \"CONTENT_LENGTH\": \"167\",\n    \"HTTP_EXPECT\": \"100-continue\",\n    \"PATH\": \"...\",\n    \"SERVER_SIGNATURE\": \"<address>Apache\\/2.4.18 (Ubuntu) Server at\n... Port 80<\\/address>\\n\",\n    \"SERVER_SOFTWARE\": \"Apache\\/2.4.18 (Ubuntu)\",\n    \"SERVER_NAME\": \"...\",\n    \"SERVER_ADDR\": \"...\",\n    \"SERVER_PORT\": \"80\",\n    \"REMOTE_ADDR\": \"...\",\n    \"DOCUMENT_ROOT\": \"...\",\n    \"REQUEST_SCHEME\": \"http\",\n    \"CONTEXT_PREFIX\": \"\",\n    \"CONTEXT_DOCUMENT_ROOT\": \"...\",\n    \"SERVER_ADMIN\": \"...\",\n    \"SCRIPT_FILENAME\": \"...\",\n    \"REMOTE_PORT\": \"49632\",\n    \"REDIRECT_URL\": \"\\/p\\/git-backend\\/run\\/1\\/\",\n    \"REDIRECT_QUERY_STRING\": \"q=p\\/git-backend\\/run\\/1\\/\",\n    \"GATEWAY_INTERFACE\": \"CGI\\/1.1\",\n    \"SERVER_PROTOCOL\": \"HTTP\\/1.1\",\n    \"REQUEST_METHOD\": \"PROPFIND\",\n    \"QUERY_STRING\": \"q=p\\/git-backend\\/run\\/1\\/\",\n    \"REQUEST_URI\": \"\\/p\\/git-backend\\/run\\/1\\/\",\n    \"SCRIPT_NAME\": \"\\/index.php\",\n    \"PHP_SELF\": \"\\/index.php\",\n    \"REQUEST_TIME_FLOAT\": 1464162575.711,\n    \"REQUEST_TIME\": 1464162575\n}\n[2016-05-25 09:49:35] Path: /core.git/\n[2016-05-25 09:49:35] <?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<D:propfind xmlns:D=\"DAV:\">\n<D:prop xmlns:R=\"http://.../p/git-backend/run/1/\">\n<D:supportedlock/>\n</D:prop>\n</D:propfind>\n[2016-05-25 09:49:35] Exception: Request not supported: '/path/to/git/repo.git/'\n\nWhen run using curl verbose, the output is\n\n\n* Couldn't find host xxx in the .netrc file; using defaults\n*   Trying xxx...\n* Connected to xxx (xxx) port 80 (#0)\n> GET /p/git-backend/run/1/info/refs?service=git-receive-pack HTTP/1.1\nHost: xxx\nUser-Agent: git/2.7.4\nAccept: */*\nAccept-Encoding: gzip\nAccept-Language: en-GB, en;q=0.9, *;q=0.8\nPragma: no-cache\n\n< HTTP/1.1 200 OK\n< Date: Wed, 25 May 2016 19:00:25 GMT\n< Server: Apache/2.4.18 (Ubuntu)\n< Set-Cookie: PHPSESSID=yyy; path=/\n< Expires: Fri, 01 Jan 1980 00:00:00 GMT\n< Cache-Control: no-cache, max-age=0, must-revalidate\n< Pragma: no-cache\n< Vary: Accept-Encoding\n< Content-Encoding: gzip\n< Content-Length: 109\n< Content-Type: text/plain;charset=UTF-8\n<\n* Connection #0 to host madhan.ga left intact\n* Couldn't find host xxx in the .netrc file; using defaults\n* Found bundle for host xxx: 0x9bade0 [can pipeline]\n* Re-using existing connection! (#0) with host xxx\n* Connected to xxx (xxx) port 80 (#0)\n> GET /p/git-backend/run/1/HEAD HTTP/1.1\nHost: xxx\nUser-Agent: git/2.7.4\nAccept: */*\nAccept-Encoding: gzip\nAccept-Language: en-GB, en;q=0.9, *;q=0.8\nPragma: no-cache\n\n< HTTP/1.1 200 OK\n< Date: Wed, 25 May 2016 19:00:25 GMT\n< Server: Apache/2.4.18 (Ubuntu)\n< Set-Cookie: PHPSESSID=zzz; path=/\n< Expires: Thu, 19 Nov 1981 08:52:00 GMT\n< Cache-Control: no-store, no-cache, must-revalidate\n< Pragma: no-cache\n< Content-Length: 23\n< Content-Type: text/plain;charset=UTF-8\n<\n* Connection #0 to host xxx left intact\n* Couldn't find host xxx in the .netrc file; using defaults\n*   Trying xxx...\n* Connected to xxx (xxx) port 80 (#0)\n> PROPFIND /p/git-backend/run/1/ HTTP/1.1\nHost: xxx\nUser-Agent: git/2.7.4\nAccept: */*\nDepth: 0\nContent-Type: text/xml\nContent-Length: 167\nExpect: 100-continue\n\n< HTTP/1.1 100 Continue\n* We are completely uploaded and fine\n* HTTP 1.0, assume close after body\n< HTTP/1.0 100 Continue\n< Date: Wed, 25 May 2016 19:00:25 GMT\n< Server: Apache/2.4.18 (Ubuntu)\n< Set-Cookie: PHPSESSID=aaa; path=/\n< Expires: Thu, 19 Nov 1981 08:52:00 GMT\n< Cache-Control: no-store, no-cache, must-revalidate\n< Pragma: no-cache\n< Content-Length: 0\n< Connection: close\n< Content-Type: text/json; charset=utf-8\n* Empty reply from server\n* Closing connection 0\nerror: Cannot access URL http://xxx/p/git-backend/run/1/, return code 52\nfatal: git-http-push failed\nerror: failed to push some refs to 'http://xxx/p/git-backend/run/1'\n\n\n\n-- \nYours,\nLuke Madhanga\n"},{"id":"287511","messageId":"20160525213850.GB13776@sigill.intra.peff.net","threadId":"42449","inReplyTo":"CABwKKP958cW3a5Cjxox+1FCtNLetdufJj0rrYBouAUhJSXKKWA@mail.gmail.com","subject":"Re: Why is my git-http-backend solution using WebDAV on push?","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2016-05-25T21:38:50Z","receivedAt":"2016-05-25T21:38:50Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, May 25, 2016 at 09:28:21PM +0100, Luke Madhanga wrote:\n\n> I've implemented a PHP wrapper for git http backend which works well.\n> I've done this to give me advanced control of who has access to\n> repositories on my server. You can see the implementation on\n> http://stackoverflow.com/questions/36998492/channel-git-on-the-server-calls-through-php/37242591#37242591.\n> I can pull from the server okay and all works well. However, I cannot\n> push. When I read my trace code to see where it fails, I see that the\n> last request is a PROPFIND request. The URL for this request does not\n> have any of the usual 'info/refs' etc. that one usually gets on git\n> calls.\n\nIf the git client detects that the server doesn't implement the\nsmart-http protocol, it will automatically downgrade to the older,\n\"dumb\" protocol which is less efficient.\n\nFor fetching/cloning, this might make your test appear to work, even\nthough it is downgrading behind the scenes. You should be able to check\nGIT_CURL_VERBOSE output to tell the difference; the smart protocol will\nPOST to .../git-upload-pack, whereas the dumb protocol will download the\nindividual packfiles and objects directly.\n\nFor pushing, the dumb protocol uses WebDAV, which is what you're seeing.\n\nSo the question is: why doesn't the client think your server is a smart\nserver?\n\nJust skimming your output, I'd guess:\n\n> > GET /p/git-backend/run/1/info/refs?service=git-receive-pack HTTP/1.1\n> Host: xxx\n> User-Agent: git/2.7.4\n> Accept: */*\n> Accept-Encoding: gzip\n> Accept-Language: en-GB, en;q=0.9, *;q=0.8\n> Pragma: no-cache\n> \n> < HTTP/1.1 200 OK\n> < Date: Wed, 25 May 2016 19:00:25 GMT\n> < Server: Apache/2.4.18 (Ubuntu)\n> < Set-Cookie: PHPSESSID=yyy; path=/\n> < Expires: Fri, 01 Jan 1980 00:00:00 GMT\n> < Cache-Control: no-cache, max-age=0, must-revalidate\n> < Pragma: no-cache\n> < Vary: Accept-Encoding\n> < Content-Encoding: gzip\n> < Content-Length: 109\n> < Content-Type: text/plain;charset=UTF-8\n> <\n\nThe content-type here should be:\n\n  application/x-git-receive-pack-advertisement\n\nThe body content should also include \"# service=git-receive-pack\" on the\nfirst line, but if you are successfully calling into git-http-backend, I\nthink it should take care of that detail.\n\n-Peff\n"},{"id":"287514","messageId":"CABwKKP89Ncht0MfB7X1x15a6PB-Nm68SDGEDvX1AnQdDucXQkA@mail.gmail.com","threadId":"42449","inReplyTo":"20160525213850.GB13776@sigill.intra.peff.net","subject":"Re: Why is my git-http-backend solution using WebDAV on push?","fromName":"Luke Madhanga","fromEmail":"lmadhanga@gmail.com","sentAt":"2016-05-25T21:54:13Z","receivedAt":"2016-05-25T21:54:13Z","isPatch":false,"sender":{"key":"lmadhanga@gmail.com","avatar":"https://gravatar.com/avatar/141fddedb95625908dbda3c232ca719e0f64ab01628f1bf22d5850ba116237b1?d=mp&s=160"},"body":"Hmmmm. Interesting.\n\nWhen you look at the PHP code, you'll see the following\n\n    $res = self::proc_open(\"{$gitcoredir}/git-http-backend\", [],\n$gitdir, true, [...]);\n    ...\n    $resbits = explode(\"\\n\", $res);\n    foreach ($resbits as $index => $header) {\n        if ($header && strpos($header, ':') !== false) {\n            // Headers\n            header($header);\n            unset($resbits[$index]);\n        } else {\n            // First blank line is the space between the headers and\nthe start of the response from Git\n            break;\n        }\n    }\n    echo ltrim(implode(\"\\n\", $resbits));\n    exit;\n\n\nEverything being returned is from a direct call to the git-http-backend.\n\nA manual CLI call to git-http-backend doesn't include\n'application/x-git-receive-pack-advertisement'\n\nREQUEST_METHOD=GET GIT_PROJECT_ROOT=/path/to/core/\nPATH_INFO=/repo.git/info/refs /usr/lib/git-core/git-http-backend\n\nThe above command outputs\n\nExpires: Fri, 01 Jan 1980 00:00:00 GMT\nPragma: no-cache\nCache-Control: no-cache, max-age=0, must-revalidate\nContent-Length: 118\nContent-Type: text/plain\n\nf4648182f5f8eee082c37a83a0072cfc4210e5c5 refs/heads/master\n8c4efcd77809bc9b94a59cf94653add8007c6b7d refs/heads/zztest\n"},{"id":"287512","messageId":"CABwKKP-rKSGzdk6E78BMRCVdumtVnj7tysv90c7RL8=059PxoA@mail.gmail.com","threadId":"42449","inReplyTo":"CABwKKP89Ncht0MfB7X1x15a6PB-Nm68SDGEDvX1AnQdDucXQkA@mail.gmail.com","subject":"Re: Why is my git-http-backend solution using WebDAV on push?","fromName":"Luke Madhanga","fromEmail":"lmadhanga@gmail.com","sentAt":"2016-05-25T21:54:26Z","receivedAt":"2016-05-25T21:54:26Z","isPatch":false,"sender":{"key":"lmadhanga@gmail.com","avatar":"https://gravatar.com/avatar/141fddedb95625908dbda3c232ca719e0f64ab01628f1bf22d5850ba116237b1?d=mp&s=160"},"body":"Thanks for the response btw\n\nOn 25 May 2016 at 22:54, Luke Madhanga <lmadhanga@gmail.com> wrote:\n> Hmmmm. Interesting.\n>\n> When you look at the PHP code, you'll see the following\n>\n>     $res = self::proc_open(\"{$gitcoredir}/git-http-backend\", [],\n> $gitdir, true, [...]);\n>     ...\n>     $resbits = explode(\"\\n\", $res);\n>     foreach ($resbits as $index => $header) {\n>         if ($header && strpos($header, ':') !== false) {\n>             // Headers\n>             header($header);\n>             unset($resbits[$index]);\n>         } else {\n>             // First blank line is the space between the headers and\n> the start of the response from Git\n>             break;\n>         }\n>     }\n>     echo ltrim(implode(\"\\n\", $resbits));\n>     exit;\n>\n>\n> Everything being returned is from a direct call to the git-http-backend.\n>\n> A manual CLI call to git-http-backend doesn't include\n> 'application/x-git-receive-pack-advertisement'\n>\n> REQUEST_METHOD=GET GIT_PROJECT_ROOT=/path/to/core/\n> PATH_INFO=/repo.git/info/refs /usr/lib/git-core/git-http-backend\n>\n> The above command outputs\n>\n> Expires: Fri, 01 Jan 1980 00:00:00 GMT\n> Pragma: no-cache\n> Cache-Control: no-cache, max-age=0, must-revalidate\n> Content-Length: 118\n> Content-Type: text/plain\n>\n> f4648182f5f8eee082c37a83a0072cfc4210e5c5 refs/heads/master\n> 8c4efcd77809bc9b94a59cf94653add8007c6b7d refs/heads/zztest\n\n\n\n-- \nYours,\nLuke Madhanga\n"},{"id":"287519","messageId":"xmqqiny1zstq.fsf@gitster.mtv.corp.google.com","threadId":"42449","inReplyTo":"CABwKKP-rKSGzdk6E78BMRCVdumtVnj7tysv90c7RL8=059PxoA@mail.gmail.com","subject":"Re: Why is my git-http-backend solution using WebDAV on push?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2016-05-25T22:16:49Z","receivedAt":"2016-05-25T22:16:49Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Luke Madhanga <lmadhanga@gmail.com> writes:\n\n>> A manual CLI call to git-http-backend doesn't include\n>> 'application/x-git-receive-pack-advertisement'\n>>\n>> REQUEST_METHOD=GET GIT_PROJECT_ROOT=/path/to/core/\n>> PATH_INFO=/repo.git/info/refs /usr/lib/git-core/git-http-backend\n\nThe request client makes to probe is (taking it from Peff's message\nthat is quoting from your trace):\n\n> > GET /p/git-backend/run/1/info/refs?service=git-receive-pack HTTP/1.1\n\nYour manual CLI call seems not to have \"?service=git-receive-pack\"\nanywhere.  Where did it go?  QUERY_STRING, perhaps?\n\nHere is what I am observing:\n\n    $ GIT_HTTP_EXPORT_ALL=Yes \\\n    > REQUEST_METHOD=GET \\\n    > GIT_PROJECT_ROOT=$(pwd)/.git \\\n    > PATH_INFO='/info/refs' \\\n    > QUERY_STRING=service=git-receive-pack \\\n    > git -c http.receivepack=yes http-backend 2>&1 | sed -e '/^.$/q'\n    Expires: Fri, 01 Jan 1980 00:00:00 GMT\n    Pragma: no-cache\n    Cache-Control: no-cache, max-age=0, must-revalidate\n    Content-Type: application/x-git-receive-pack-advertisement\n\n\n>>\n>> The above command outputs\n>>\n>> Expires: Fri, 01 Jan 1980 00:00:00 GMT\n>> Pragma: no-cache\n>> Cache-Control: no-cache, max-age=0, must-revalidate\n>> Content-Length: 118\n>> Content-Type: text/plain\n>>\n>> f4648182f5f8eee082c37a83a0072cfc4210e5c5 refs/heads/master\n>> 8c4efcd77809bc9b94a59cf94653add8007c6b7d refs/heads/zztest\n"}]}