Subject: bug#68610: URI path in git-http-nginx-location-configuration doesn't accept / properly

From: Richard Sent <[email-masked]>
Date: Sat, 20 Jan 2024 12:18:47 -0500

Hi all,

In the documentation for Version Control Services, there is example code
for sharing Git repos through Nginx, posted below. The line
(git-http-configuration (uri-path "/")) implies that git repositories
can be reached at "git.my-host.org/repo.git". However, this doesn't work.

--8<---------------cut here---------------start------------->8---
(service nginx-service-type
         (nginx-configuration
          (server-blocks
           (list
            (nginx-server-configuration
             (listen '("443 ssl"))
             (server-name "git.my-host.org")
             (ssl-certificate
              "/etc/letsencrypt/live/git.my-host.org/fullchain.pem")
             (ssl-certificate-key
              "/etc/letsencrypt/live/git.my-host.org/privkey.pem")
             (locations
              (list
               (git-http-nginx-location-configuration
                (git-http-configuration (uri-path "/"))))))))))
--8<---------------cut here---------------end--------------->8---

Nginx's location information is generated by
git-http-nginx-location-configuration, which runs

--8<---------------cut here---------------start------------->8---
(uri (string-append "~ /" (string-trim-both uri-path #\/) "(/.*)"))
--8<---------------cut here---------------end--------------->8---

If uri-path is "/" (or "", or "\"), this entry will be created in nginx.conf:

--8<---------------cut here---------------start------------->8---
location ~ /(/.*) {
   ....
}
--8<---------------cut here---------------end--------------->8---

This location regex pattern will match git.my-host.org//, but not
git.my-host.org/. However, Nginx merges slashes by default, so you
cannot access the repo with 'http://git.my-host.org//repo.git' because
Nginx collapses that to http://git.my-host.org/repo.git before matching
the URI against the location pattern. Which, as mentioned, does not
match.

I did find that (uri-path "*") does work, but I've not tested it
extensively. I also found that I can add `(raw-content (list
"merge_slashes off;"))` to nginx-server-configuration, then use `$ git
clone http://git.my-host.org//repo.git`, but that's not ideal.

At minimum, the documentation should be updated to reflect this
(uri-path "/" vs "\" vs "" are identical). I don't know what the future
plans are for git-http-service, but I can think of two possible solutions:

1. git-http-nginx-location-configuration no longer modifies uri-path and
instead pastes it literally in nginx.conf. To my understanding "/git"
would work identically without the regex match currently used, exposing
repos at "host.domain/git/path/to/repo.git", but I've not tested this.

2. git-http-nginx-location-configuration takes an optional Nginx-style
URI pattern argument that, if passed, replaces the URI generated from
git-http-configuration.

-- 
Take it easy,
Richard Sent
Making my computer weirder one commit at a time.