feat(tvix/nar-bridge): support HTTP HEAD for narinfo

Change-Id: I4ec8e9108f52d0a84bc1af01a27bd51de4ab493f
Reviewed-on: https://cl.tvl.fyi/c/depot/+/11456
Reviewed-by: flokli <flokli@flokli.de>
Tested-by: BuildkiteCI
This commit is contained in:
Edwin Mackenzie-Owen 2024-04-14 21:17:11 +02:00
parent d84fd49169
commit 465370c11f

View file

@ -96,37 +96,42 @@ func renderNarinfo(
} }
func registerNarinfoGet(s *Server) { func registerNarinfoGet(s *Server) {
// GET $outHash.narinfo looks up the PathInfo from the tvix-store, // GET/HEAD $outHash.narinfo looks up the PathInfo from the tvix-store,
// and then render a .narinfo file to the client. // and, if it's a GET request, render a .narinfo file to the client.
// It will keep the PathInfo in the lookup map, // In both cases it will keep the PathInfo in the lookup map,
// so a subsequent GET /nar/ $narhash.nar request can find it. // so a subsequent GET/HEAD /nar/ $narhash.nar request can find it.
s.handler.Get("/{outputhash:^["+nixbase32.Alphabet+"]{32}}.narinfo", func(w http.ResponseWriter, r *http.Request) { genNarinfoHandler := func(isHead bool) func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close() return func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
ctx := r.Context() ctx := r.Context()
log := log.WithField("outputhash", chi.URLParamFromCtx(ctx, "outputhash")) log := log.WithField("outputhash", chi.URLParamFromCtx(ctx, "outputhash"))
// parse the output hash sent in the request URL // parse the output hash sent in the request URL
outputHash, err := nixbase32.DecodeString(chi.URLParamFromCtx(ctx, "outputhash")) outputHash, err := nixbase32.DecodeString(chi.URLParamFromCtx(ctx, "outputhash"))
if err != nil {
log.WithError(err).Error("unable to decode output hash from url")
w.WriteHeader(http.StatusBadRequest)
_, err := w.Write([]byte("unable to decode output hash from url"))
if err != nil { if err != nil {
log.WithError(err).Errorf("unable to write error message to client") log.WithError(err).Error("unable to decode output hash from url")
w.WriteHeader(http.StatusBadRequest)
_, err := w.Write([]byte("unable to decode output hash from url"))
if err != nil {
log.WithError(err).Errorf("unable to write error message to client")
}
return
} }
return err = renderNarinfo(ctx, log, s.pathInfoServiceClient, &s.narDbMu, s.narDb, outputHash, w, isHead)
} if err != nil {
if errors.Is(err, fs.ErrNotExist) {
err = renderNarinfo(ctx, log, s.pathInfoServiceClient, &s.narDbMu, s.narDb, outputHash, w, false) w.WriteHeader(http.StatusNotFound)
if err != nil { } else {
if errors.Is(err, fs.ErrNotExist) { log.WithError(err).Warn("unable to render narinfo")
w.WriteHeader(http.StatusNotFound) w.WriteHeader(http.StatusInternalServerError)
} else { }
log.WithError(err).Warn("unable to render narinfo")
w.WriteHeader(http.StatusInternalServerError)
} }
} }
}) }
s.handler.Get("/{outputhash:^["+nixbase32.Alphabet+"]{32}}.narinfo", genNarinfoHandler(false))
s.handler.Head("/{outputhash:^["+nixbase32.Alphabet+"]{32}}.narinfo", genNarinfoHandler(true))
} }