Workaround for hosting Zig packages with cgit
I have been tinkering with Zig for awhile now, and so far been in the habit of simply copying code around between projects as I need to reuse it. Now I know what a library is, but I also tend to err on the side of code duplication over building the wrong abstraction. In practical terms, I find that I often write a better library if I first copy code around, edit it to each project’s needs, and eventually design the library code that fits all my uses.
Ok with that aside, I finally bothered to check out the package management1 feature that shipped in Zig 0.11.0. I host my code using a cgit2 instance at git.0x1b.me. After creating a new repo and tidying up the code, I tried to use it in a different project:
$ zig build
Fetch Packages [1/1] trunk... build.zig.zon:6:14: error: Unsupported 'Content-Type' header value: 'application/x-gzip; charset=UTF-8'
.url = "https://git.0x1b.me/zig-trunk/snapshot/zig-trunk-b7e91fb060b3e5ff774d2c7e1ff9a5df9ea1d3a4.tar.gz",
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It might be unsupported from Zig’s perspective, but that is a valid
Content-Type
header value. I have found Zig’s http stack to be a bit
immature; no surprise (and no criticism) for a pre-1.0 language. That certainly
has not deterred me from continuing to use the language.
Some other cgit user already filed an issue3, created a PR, and even submitted a patch to cgit4. Serious kudos to them for going the full distance.
With that already handled, I just want a quick fix. In a past life I spent ample time learning nginx, and it’s what I run to host this blog and front any other http service I run. So somehow my first instinct is to rewrite the header via nginx to a value that Zig can understand.
Using a combination of the fastcgi_hide_header
5 and add_header
6
directives, I can rewrite the headers emitted by cgit. The map
7
directive essentially lets me write an if/else condition to only rewrite the
specific gzip header, leaving other responses untouched.
I won’t print the entire config for sake of brevity, but this should be enough to go on for anyone else in a similar situation:
map $upstream_http_content_type $res_content_type {
default $upstream_http_content_type;
"application/x-gzip; charset=UTF-8" "application/x-gzip";
}
server {
listen 8080;
server_name git.0x1b.me;
location @cgit {
fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
fastcgi_param PATH_INFO $uri;
fastcgi_param QUERY_STRING $args;
fastcgi_param HTTP_HOST $server_name;
fastcgi_pass unix:/run/fcgiwrap.socket;
fastcgi_hide_header Content-Type;
add_header Content-Type $res_content_type always;
}
}
-
https://ziglang.org/download/0.11.0/release-notes.html#Package-Management ↩︎
-
https://lists.zx2c4.com/pipermail/cgit/2023-August/004855.html ↩︎
-
https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_hide_header ↩︎
-
https://nginx.org/en/docs/http/ngx_http_headers_module.html#add_header ↩︎
-
https://nginx.org/en/docs/http/ngx_http_map_module.html#map ↩︎