gateway: re-use resolved path
Instead of resolving a node, we resolve a path. This resolved path is then re-used for Cat and Ls. This way, a resolve operation is only done once. The error messages for a failed resolve is changed from `ipfs cat …` to `ipfs resolve …` to better reflect the API calls. The test is updated accordingly. License: MIT Signed-off-by: Remco Bloemen <remco@2π.com>
Remco Bloemen committed
Apr 18, 2017 at 17:22 UTC
a90f4967e30fc5f16d362f1b9844196e1bd24101
2 files changed
+17
-16
core/corehttp/gateway_handler.go
+16
-15
@@ -164,35 +164,36 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
164
return
165
}
166
167
- dr, err := i.api.Unixfs().Cat(ctx, parsedPath)
168
- dir := false
167
+ // Resolve path to the final DAG node for the ETag
168
+ resolvedPath, err := i.api.ResolvePath(ctx, parsedPath)
169
switch err {
170
case nil:
171
- // Cat() worked
172
- defer dr.Close()
173
- case coreiface.ErrIsDir:
174
- dir = true
171
case coreiface.ErrOffline:
172
if !i.node.OnlineMode() {
177
- webError(w, "ipfs cat "+urlPath, err, http.StatusServiceUnavailable)
173
+ webError(w, "ipfs resolve -r "+urlPath, err, http.StatusServiceUnavailable)
174
return
175
}
176
fallthrough
177
default:
182
- webError(w, "ipfs cat "+urlPath, err, http.StatusNotFound)
178
+ webError(w, "ipfs resolve -r "+urlPath, err, http.StatusNotFound)
179
return
180
}
181
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)
182
+ dr, err := i.api.Unixfs().Cat(ctx, resolvedPath)
183
+ dir := false
184
+ switch err {
185
+ case nil:
186
+ // Cat() worked
187
+ defer dr.Close()
188
+ case coreiface.ErrIsDir:
189
+ dir = true
190
+ default:
191
+ webError(w, "ipfs cat "+urlPath, err, http.StatusNotFound)
192
return
193
}
194
195
// Check etag send back to us
195
- etag := "\"" + dagnode.Cid().String() + "\""
196
+ etag := "\"" + resolvedPath.Cid().String() + "\""
197
if r.Header.Get("If-None-Match") == etag {
198
w.WriteHeader(http.StatusNotModified)
199
return
@@ -225,7 +226,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
226
return
227
}
228
228
- links, err := i.api.Unixfs().Ls(ctx, parsedPath)
229
+ links, err := i.api.Unixfs().Ls(ctx, resolvedPath)
230
if err != nil {
231
internalWebError(w, err)
232
return
core/corehttp/gateway_test.go
+1
-1
@@ -136,7 +136,7 @@ func TestGatewayGet(t *testing.T) {
136
{"localhost:5001", "/", http.StatusNotFound, "404 page not found\n"},
137
{"localhost:5001", "/" + k, http.StatusNotFound, "404 page not found\n"},
138
{"localhost:5001", "/ipfs/" + k, http.StatusOK, "fnord"},
139
- {"localhost:5001", "/ipns/nxdomain.example.com", http.StatusNotFound, "ipfs cat /ipns/nxdomain.example.com: " + namesys.ErrResolveFailed.Error() + "\n"},
139
+ {"localhost:5001", "/ipns/nxdomain.example.com", http.StatusNotFound, "ipfs resolve -r /ipns/nxdomain.example.com: " + namesys.ErrResolveFailed.Error() + "\n"},
140
{"localhost:5001", "/ipns/example.com", http.StatusOK, "fnord"},
141
{"example.com", "/", http.StatusOK, "fnord"},
142
} {