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