MCPcopy Index your code
hub / github.com/coder/coder / ServeHTTP

Method ServeHTTP

site/bin.go:52–108  ·  view source on GitHub ↗
(rw http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

50}
51
52func (h *binHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
53 if !strings.HasPrefix(r.URL.Path, "/bin/") {
54 rw.WriteHeader(http.StatusNotFound)
55 _, _ = rw.Write([]byte("not found"))
56 return
57 }
58 r.URL.Path = strings.TrimPrefix(r.URL.Path, "/bin")
59 // Convert underscores in the filename to hyphens. We eventually want to
60 // change our hyphen-based filenames to underscores, but we need to
61 // support both for now.
62 r.URL.Path = strings.ReplaceAll(r.URL.Path, "_", "-")
63
64 // Set ETag header to the SHA1 hash of the file contents.
65 name := filePath(r.URL.Path)
66 if name == "" || name == "/" {
67 // Serve the directory listing. This intentionally allows directory listings to
68 // be served. This file system should not contain anything sensitive.
69 h.handler.ServeHTTP(rw, r)
70 return
71 }
72 if strings.Contains(name, "/") {
73 // We only serve files from the root of this directory, so avoid any
74 // shenanigans by blocking slashes in the URL path.
75 http.NotFound(rw, r)
76 return
77 }
78
79 metadata, err := h.metadataCache.getMetadata(name)
80 if xerrors.Is(err, os.ErrNotExist) {
81 http.NotFound(rw, r)
82 return
83 }
84 if err != nil {
85 http.Error(rw, err.Error(), http.StatusInternalServerError)
86 return
87 }
88
89 // http.FileServer will not set Content-Length when performing chunked
90 // transport encoding, which is used for large files like our binaries
91 // so stream compression can be used.
92 //
93 // Clients like IDE extensions and the desktop apps can compare the
94 // value of this header with the amount of bytes written to disk after
95 // decompression to show progress. Without this, they cannot show
96 // progress without disabling compression.
97 //
98 // There isn't really a spec for a length header for the "inner" content
99 // size, but some nginx modules use this header.
100 rw.Header().Set("X-Original-Content-Length", fmt.Sprintf("%d", metadata.sizeBytes))
101
102 // Get and set ETag header. Must be quoted.
103 rw.Header().Set("ETag", fmt.Sprintf(`%q`, metadata.sha1Hash))
104
105 // http.FileServer will see the ETag header and automatically handle
106 // If-Match and If-None-Match headers on the request properly.
107 h.handler.ServeHTTP(rw, r)
108}
109

Callers

nothing calls this directly

Calls 9

filePathFunction · 0.85
getMetadataMethod · 0.80
WriteMethod · 0.65
SetMethod · 0.65
WriteHeaderMethod · 0.45
ContainsMethod · 0.45
IsMethod · 0.45
ErrorMethod · 0.45
HeaderMethod · 0.45

Tested by

no test coverage detected