diff options
author | Vincent Ambo <tazjin@google.com> | 2019-07-31T20·36+0100 |
---|---|---|
committer | Vincent Ambo <github@tazj.in> | 2019-08-02T00·08+0100 |
commit | 119af77b43775999e39b6e88911d46b5cc60b93d (patch) | |
tree | ddfbd43a734ba5d9f3fc931118fbb71accfaceec /tools/nixery/main.go | |
parent | 2f1bc55597c382496930f4ba8f4ef25914fb9748 (diff) |
feat(go): Return errors with correct status codes to clients
Uses the structured errors feature introduced in the Nix code to return more sensible errors to clients. For now this is quite limited, but already a lot better than before: * packages that could not be found result in 404s * all other errors result in 500s This way the registry clients will not attempt to interpret the returned garbage data/empty response as something useful.
Diffstat (limited to 'tools/nixery/main.go')
-rw-r--r-- | tools/nixery/main.go | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/tools/nixery/main.go b/tools/nixery/main.go index a4e0b9a80a16..91a9e6d4943f 100644 --- a/tools/nixery/main.go +++ b/tools/nixery/main.go @@ -138,6 +138,9 @@ type image struct { // // The later field is simply treated as opaque JSON and passed through. type BuildResult struct { + Error string `json:"error` + Pkgs []string `json:"pkgs"` + Manifest json.RawMessage `json:"manifest"` LayerLocations map[string]struct { Path string `json:"path"` @@ -183,7 +186,7 @@ func convenienceNames(packages []string) []string { // Call out to Nix and request that an image be built. Nix will, upon success, // return a manifest for the container image. -func buildImage(ctx *context.Context, cfg *config, image *image, bucket *storage.BucketHandle) ([]byte, error) { +func buildImage(ctx *context.Context, cfg *config, image *image, bucket *storage.BucketHandle) (*BuildResult, error) { packages, err := json.Marshal(image.packages) if err != nil { return nil, err @@ -249,7 +252,7 @@ func buildImage(ctx *context.Context, cfg *config, image *image, bucket *storage } } - return json.Marshal(result.Manifest) + return &result, nil } // uploadLayer uploads a single layer to Cloud Storage bucket. Before writing @@ -358,7 +361,7 @@ func (h *registryHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { imageTag := manifestMatches[2] log.Printf("Requesting manifest for image %q at tag %q", imageName, imageTag) image := imageFromName(imageName, imageTag) - manifest, err := buildImage(h.ctx, h.cfg, &image, h.bucket) + buildResult, err := buildImage(h.ctx, h.cfg, &image, h.bucket) if err != nil { log.Println("Failed to build image manifest", err) @@ -366,6 +369,17 @@ func (h *registryHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } + // Some error types have special handling, which is applied + // here. + if buildResult.Error == "not_found" { + log.Printf("Could not find packages: %v\n", buildResult.Pkgs) + w.WriteHeader(404) + return + } + + // This marshaling error is ignored because we know that this + // field represents valid JSON data. + manifest, _ := json.Marshal(buildResult.Manifest) w.Header().Add("Content-Type", manifestMediaType) w.Write(manifest) return |