mirror of
https://github.com/ipfs/kubo.git
synced 2025-07-01 02:30:39 +08:00
Merge pull request #4320 from ipfs/fix/gateway-seeker
gateway: fix seeker can't seek on specific files
This commit is contained in:
@ -268,7 +268,7 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
|
|||||||
|
|
||||||
if !dir {
|
if !dir {
|
||||||
name := gopath.Base(urlPath)
|
name := gopath.Base(urlPath)
|
||||||
http.ServeContent(w, r, name, modtime, dr)
|
i.serveFile(w, r, name, modtime, dr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,6 +372,34 @@ func (i *gatewayHandler) getOrHeadHandler(ctx context.Context, w http.ResponseWr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type sizeReadSeeker interface {
|
||||||
|
Size() uint64
|
||||||
|
|
||||||
|
io.ReadSeeker
|
||||||
|
}
|
||||||
|
|
||||||
|
type sizeSeeker struct {
|
||||||
|
sizeReadSeeker
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sizeSeeker) Seek(offset int64, whence int) (int64, error) {
|
||||||
|
if whence == io.SeekEnd && offset == 0 {
|
||||||
|
return int64(s.Size()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.sizeReadSeeker.Seek(offset, whence)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *gatewayHandler) serveFile(w http.ResponseWriter, req *http.Request, name string, modtime time.Time, content io.ReadSeeker) {
|
||||||
|
if sp, ok := content.(sizeReadSeeker); ok {
|
||||||
|
content = &sizeSeeker{
|
||||||
|
sizeReadSeeker: sp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
http.ServeContent(w, req, name, modtime, content)
|
||||||
|
}
|
||||||
|
|
||||||
func (i *gatewayHandler) postHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
func (i *gatewayHandler) postHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
|
||||||
p, err := i.api.Unixfs().Add(ctx, r.Body)
|
p, err := i.api.Unixfs().Add(ctx, r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -307,11 +307,14 @@ func GetNodes(ctx context.Context, ds DAGService, keys []*cid.Cid) []NodeGetter
|
|||||||
|
|
||||||
// Remove duplicates from a list of keys
|
// Remove duplicates from a list of keys
|
||||||
func dedupeKeys(cids []*cid.Cid) []*cid.Cid {
|
func dedupeKeys(cids []*cid.Cid) []*cid.Cid {
|
||||||
|
out := make([]*cid.Cid, 0, len(cids))
|
||||||
set := cid.NewSet()
|
set := cid.NewSet()
|
||||||
for _, c := range cids {
|
for _, c := range cids {
|
||||||
set.Add(c)
|
if set.Visit(c) {
|
||||||
|
out = append(out, c)
|
||||||
}
|
}
|
||||||
return set.Keys()
|
}
|
||||||
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNodePromise(ctx context.Context) NodeGetter {
|
func newNodePromise(ctx context.Context) NodeGetter {
|
||||||
|
2
test/sharness/t0110-gateway-data/foo.block
Normal file
2
test/sharness/t0110-gateway-data/foo.block
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
foo
|
BIN
test/sharness/t0110-gateway-data/foofoo.block
Normal file
BIN
test/sharness/t0110-gateway-data/foofoo.block
Normal file
Binary file not shown.
@ -155,6 +155,17 @@ test_expect_success "try fetching it from gateway" '
|
|||||||
test_cmp rfile ffile
|
test_cmp rfile ffile
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success "Add compact blocks" '
|
||||||
|
ipfs block put ../t0110-gateway-data/foo.block &&
|
||||||
|
FOO2_HASH=$(ipfs block put ../t0110-gateway-data/foofoo.block) &&
|
||||||
|
printf "foofoo" > expected
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success "GET compact blocks succeeds" '
|
||||||
|
curl -o actual "http://127.0.0.1:$port/ipfs/$FOO2_HASH" &&
|
||||||
|
test_cmp expected actual
|
||||||
|
'
|
||||||
|
|
||||||
test_kill_ipfs_daemon
|
test_kill_ipfs_daemon
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -188,6 +188,9 @@ func (dr *pbDagReader) Seek(offset int64, whence int) (int64, error) {
|
|||||||
if offset < 0 {
|
if offset < 0 {
|
||||||
return -1, errors.New("Invalid offset")
|
return -1, errors.New("Invalid offset")
|
||||||
}
|
}
|
||||||
|
if offset == dr.offset {
|
||||||
|
return offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Grab cached protobuf object (solely to make code look cleaner)
|
// Grab cached protobuf object (solely to make code look cleaner)
|
||||||
pb := dr.pbdata
|
pb := dr.pbdata
|
||||||
@ -239,11 +242,24 @@ func (dr *pbDagReader) Seek(offset int64, whence int) (int64, error) {
|
|||||||
return offset, nil
|
return offset, nil
|
||||||
case io.SeekCurrent:
|
case io.SeekCurrent:
|
||||||
// TODO: be smarter here
|
// TODO: be smarter here
|
||||||
|
if offset == 0 {
|
||||||
|
return dr.offset, nil
|
||||||
|
}
|
||||||
|
|
||||||
noffset := dr.offset + offset
|
noffset := dr.offset + offset
|
||||||
return dr.Seek(noffset, io.SeekStart)
|
return dr.Seek(noffset, io.SeekStart)
|
||||||
case io.SeekEnd:
|
case io.SeekEnd:
|
||||||
noffset := int64(dr.pbdata.GetFilesize()) - offset
|
noffset := int64(dr.pbdata.GetFilesize()) - offset
|
||||||
return dr.Seek(noffset, io.SeekStart)
|
n, err := dr.Seek(noffset, io.SeekStart)
|
||||||
|
|
||||||
|
// Return negative number if we can't figure out the file size. Using io.EOF
|
||||||
|
// for this seems to be good(-enough) solution as it's only returned by
|
||||||
|
// precalcNextBuf when we step out of file range.
|
||||||
|
// This is needed for gateway to function properly
|
||||||
|
if err == io.EOF && *dr.pbdata.Type == ftpb.Data_File {
|
||||||
|
return -1, nil
|
||||||
|
}
|
||||||
|
return n, err
|
||||||
default:
|
default:
|
||||||
return 0, errors.New("invalid whence")
|
return 0, errors.New("invalid whence")
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user