gateway: fix seeker can't seek on specific files
License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>
Łukasz Magiera committed
Oct 18, 2017 at 20:10 UTC
e71dce5dfba3616e5ade4abf0844925389497a56
5 files changed
+37
-4
core/corehttp/gateway_handler.go
+12
-1
@@ -268,7 +268,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
268
269
if !dir {
270
name := gopath.Base(urlPath)
271
- http.ServeContent(w, r, name, modtime, dr)
271
+ i.serverFile(w, r, name, modtime, dr)
272
return
273
}
274
@@ -372,6 +372,17 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
372
}
373
}
374
375
+func (i *gatewayHandler) serverFile(w http.ResponseWriter, req *http.Request, name string, modtime time.Time, content io.ReadSeeker) {
376
+ http.ServeContent(w, req, name, modtime, content)
377
+ //TODO: check for errors in ServeContent.. somehow
378
+
379
+ // If http.ServeContent can't figure out content size it won't write it to the
380
+ // responseWriter, Content-Length not being set is a good indicator of this
381
+ if req.Method != "HEAD" && w.Header().Get("Content-Length") == "" {
382
+ io.Copy(w, content)
383
+ }
384
+}
385
+
386
func (i *gatewayHandler) postHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
387
p, err := i.api.Unixfs().Add(ctx, r.Body)
388
if err != nil {
test/sharness/t0110-gateway-data/foo.block
new
+2
@@ -0,0 +1,2 @@
1
+
2
+ foo
\ No newline at end of file
test/sharness/t0110-gateway-data/foofoo.block
Binary files /dev/null and b/test/sharness/t0110-gateway-data/foofoo.block differ
test/sharness/t0110-gateway.sh
+13
-2
@@ -124,7 +124,7 @@ test_expect_success "HEAD 'index.html' has no content" '
124
# test ipfs readonly api
125
126
test_curl_gateway_api() {
127
- curl -sfo actual "http://127.0.0.1:$port/api/v0/$1"
127
+ curl -sfo actual "http://127.0.0.1:$port/api/v0/$1"
128
}
129
130
test_expect_success "get IPFS directory file through readonly API succeeds" '
@@ -140,7 +140,7 @@ test_expect_success "refs IPFS directory file through readonly API succeeds" '
140
'
141
142
test_expect_success "test gateway api is sanitized" '
143
-for cmd in "add" "block/put" "bootstrap" "config" "dht" "diag" "dns" "get" "id" "mount" "name/publish" "object/put" "object/new" "object/patch" "pin" "ping" "refs/local" "repo" "resolve" "stats" "swarm" "file" "update" "version" "bitswap"; do
143
+ for cmd in "add" "block/put" "bootstrap" "config" "dht" "diag" "dns" "get" "id" "mount" "name/publish" "object/put" "object/new" "object/patch" "pin" "ping" "refs/local" "repo" "resolve" "stats" "swarm" "file" "update" "version" "bitswap"; do
144
test_curl_resp_http_code "http://127.0.0.1:$port/api/v0/$cmd" "HTTP/1.1 404 Not Found"
145
done
146
'
@@ -155,6 +155,17 @@ test_expect_success "try fetching it from gateway" '
155
test_cmp rfile ffile
156
'
157
158
+test_expect_success "Add compact blocks" '
159
+ ipfs block put ../t0110-gateway-data/foo.block &&
160
+ FOO2_HASH=$(ipfs block put ../t0110-gateway-data/foofoo.block) &&
161
+ printf "foofoo" > expected
162
+'
163
+
164
+test_expect_success "GET compact blocks succeeds" '
165
+ curl -o actual "http://127.0.0.1:$port/ipfs/$FOO2_HASH" &&
166
+ test_cmp expected actual
167
+'
168
+
169
test_kill_ipfs_daemon
170
171
test_done
unixfs/io/pbdagreader.go
+10
-1
@@ -243,7 +243,16 @@ func (dr *pbDagReader) Seek(offset int64, whence int) (int64, error) {
243
return dr.Seek(noffset, io.SeekStart)
244
case io.SeekEnd:
245
noffset := int64(dr.pbdata.GetFilesize()) - offset
246
- return dr.Seek(noffset, io.SeekStart)
246
+ n, err := dr.Seek(noffset, io.SeekStart)
247
+
248
+ // Return negative number if we can't figure out the file size. Using io.EOF
249
+ // for this seems to be good(-enough) solution as it's only returned by
250
+ // precalcNextBuf when we step out of file range.
251
+ // This is needed for gateway to function properly
252
+ if err == io.EOF && *dr.pbdata.Type == ftpb.Data_File {
253
+ return -1, nil
254
+ }
255
+ return n, err
256
default:
257
return 0, errors.New("invalid whence")
258
}