@cryptotaxi247 / kubo / commits / 8db6f86de

gateway: use CID as an ETag strong validator

* Always use the fully resolved CID from api.ResolveNode as the ETag (also for IPNS). * Format the result as a valid "Strong Validator" (double quotes around the encoded CID). Fixes #3868 License: MIT Signed-off-by: Remco Bloemen <remco@2π.com>

Remco Bloemen committed Apr 18, 2017 at 16:22 UTC 8db6f86de6085b78bc03bccdc26d11a7350058d4
1 file changed +11 -2
core/corehttp/gateway_handler.go
+11 -2
@@ -183,7 +183,16 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
183 return
184 }
185
186 - etag := gopath.Base(urlPath)
186 + // Resolve path to the final DAG node for the ETag
187 + dagnode, err := i.api.ResolveNode(ctx, parsedPath)
188 + if err != nil {
189 + // Unixfs().Cat() also calls ResolveNode, so it should not fail here.
190 + webError(w, "could not resolve ipfs path", err, http.StatusBadRequest)
191 + return
192 + }
193 +
194 + // Check etag send back to us
195 + etag := "\"" + dagnode.Cid().String() + "\""
196 if r.Header.Get("If-None-Match") == etag {
197 w.WriteHeader(http.StatusNotModified)
198 return
@@ -191,6 +200,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
200
201 i.addUserHeaders(w) // ok, _now_ write user's headers.
202 w.Header().Set("X-IPFS-Path", urlPath)
203 + w.Header().Set("Etag", etag)
204
205 // set 'allowed' headers
206 w.Header().Set("Access-Control-Allow-Headers", "X-Stream-Output, X-Chunked-Output")
@@ -203,7 +213,6 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
213 // TODO: break this out when we split /ipfs /ipns routes.
214 modtime := time.Now()
215 if strings.HasPrefix(urlPath, ipfsPathPrefix) {
206 - w.Header().Set("Etag", etag)
216 w.Header().Set("Cache-Control", "public, max-age=29030400, immutable")
217
218 // set modtime to a really long time ago, since files are immutable and should stay cached