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_header5 and add_header6 directives, I can rewrite the headers emitted by cgit. The map7 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;
  }
}