Skip to content

Commit

Permalink
feat: use last segment cid as root
Browse files Browse the repository at this point in the history
- this also allows to return the PathMetadata, which also
allows to set the correct X-Ipfs-Root header.
  • Loading branch information
hacdias committed Jun 8, 2023
1 parent ffcdaa1 commit 7be4474
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 24 deletions.
18 changes: 9 additions & 9 deletions gateway/blocks_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,20 +232,20 @@ func (bb *BlocksBackend) Head(ctx context.Context, path ImmutablePath) (ContentP
return md, fileNode, nil
}

func (bb *BlocksBackend) GetCAR(ctx context.Context, p ImmutablePath, params CarParams) (io.ReadCloser, error) {
func (bb *BlocksBackend) GetCAR(ctx context.Context, p ImmutablePath, params CarParams) (ContentPathMetadata, io.ReadCloser, error) {
pathMetadata, err := bb.ResolvePath(ctx, p)
if err != nil {
return ContentPathMetadata{}, nil, err
}

contentPathStr := p.String()
if !strings.HasPrefix(contentPathStr, "/ipfs/") {
return nil, fmt.Errorf("path does not have /ipfs/ prefix")
}
firstSegment, _, _ := strings.Cut(contentPathStr[6:], "/")
rootCid, err := cid.Decode(firstSegment)
if err != nil {
return nil, err
return ContentPathMetadata{}, nil, fmt.Errorf("path does not have /ipfs/ prefix")
}

r, w := io.Pipe()
go func() {
cw, err := storage.NewWritable(w, []cid.Cid{rootCid}, car.WriteAsCarV1(true))
cw, err := storage.NewWritable(w, []cid.Cid{pathMetadata.LastSegment.Cid()}, car.WriteAsCarV1(true))
if err != nil {
// io.PipeWriter.CloseWithError always returns nil.
_ = w.CloseWithError(err)
Expand Down Expand Up @@ -275,7 +275,7 @@ func (bb *BlocksBackend) GetCAR(ctx context.Context, p ImmutablePath, params Car
_ = w.CloseWithError(carWriteErr)
}()

return r, nil
return pathMetadata, r, nil
}

// walkGatewaySimpleSelector walks the subgraph described by the path and terminal element parameters
Expand Down
2 changes: 1 addition & 1 deletion gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ type IPFSBackend interface {

// GetCAR returns a CAR file for the given immutable path. It returns an error
// if there was an issue before the CAR streaming begins.
GetCAR(context.Context, ImmutablePath, CarParams) (io.ReadCloser, error)
GetCAR(context.Context, ImmutablePath, CarParams) (ContentPathMetadata, io.ReadCloser, error)

// IsCached returns whether or not the path exists locally.
IsCached(context.Context, path.Path) bool
Expand Down
2 changes: 1 addition & 1 deletion gateway/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func (mb *mockBackend) Head(ctx context.Context, immutablePath ImmutablePath) (C
return mb.gw.Head(ctx, immutablePath)
}

func (mb *mockBackend) GetCAR(ctx context.Context, immutablePath ImmutablePath, params CarParams) (io.ReadCloser, error) {
func (mb *mockBackend) GetCAR(ctx context.Context, immutablePath ImmutablePath, params CarParams) (ContentPathMetadata, io.ReadCloser, error) {
return mb.gw.GetCAR(ctx, immutablePath, params)
}

Expand Down
7 changes: 2 additions & 5 deletions gateway/handler_car.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,6 @@ func (i *handler) serveCAR(ctx context.Context, w http.ResponseWriter, r *http.R
return false
}

// TODO(hacdias): this is incorrect and should have the full list of CIDs.
// https://github.com/ipfs/boxo/issues/221
w.Header().Set("X-Ipfs-Roots", rootCid.String())

// Set Content-Disposition
var name string
if urlFilename := r.URL.Query().Get("filename"); urlFilename != "" {
Expand Down Expand Up @@ -83,11 +79,12 @@ func (i *handler) serveCAR(ctx context.Context, w http.ResponseWriter, r *http.R
return false
}

carFile, err := i.backend.GetCAR(ctx, imPath, params)
md, carFile, err := i.backend.GetCAR(ctx, imPath, params)
if !i.handleRequestErrors(w, r, contentPath, err) {
return false
}
defer carFile.Close()
setIpfsRootsHeader(w, md)

// Make it clear we don't support range-requests over a car stream
// Partial downloads and resumes should be handled using requests for
Expand Down
6 changes: 3 additions & 3 deletions gateway/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ func (mb *errorMockBackend) Head(ctx context.Context, path ImmutablePath) (Conte
return ContentPathMetadata{}, nil, mb.err
}

func (mb *errorMockBackend) GetCAR(ctx context.Context, path ImmutablePath, params CarParams) (io.ReadCloser, error) {
return nil, mb.err
func (mb *errorMockBackend) GetCAR(ctx context.Context, path ImmutablePath, params CarParams) (ContentPathMetadata, io.ReadCloser, error) {
return ContentPathMetadata{}, nil, mb.err
}

func (mb *errorMockBackend) ResolveMutable(ctx context.Context, path ipath.Path) (ImmutablePath, error) {
Expand Down Expand Up @@ -173,7 +173,7 @@ func (mb *panicMockBackend) Head(ctx context.Context, immutablePath ImmutablePat
panic("i am panicking")
}

func (mb *panicMockBackend) GetCAR(ctx context.Context, immutablePath ImmutablePath, params CarParams) (io.ReadCloser, error) {
func (mb *panicMockBackend) GetCAR(ctx context.Context, immutablePath ImmutablePath, params CarParams) (ContentPathMetadata, io.ReadCloser, error) {
panic("i am panicking")
}

Expand Down
8 changes: 3 additions & 5 deletions gateway/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,15 @@ func (b *ipfsBackendWithMetrics) ResolvePath(ctx context.Context, path Immutable
return md, err
}

func (b *ipfsBackendWithMetrics) GetCAR(ctx context.Context, path ImmutablePath, params CarParams) (io.ReadCloser, error) {
func (b *ipfsBackendWithMetrics) GetCAR(ctx context.Context, path ImmutablePath, params CarParams) (ContentPathMetadata, io.ReadCloser, error) {
begin := time.Now()
name := "IPFSBackend.GetCAR"
ctx, span := spanTrace(ctx, name, trace.WithAttributes(attribute.String("path", path.String())))
defer span.End()

rc, err := b.backend.GetCAR(ctx, path, params)

// TODO: handle errCh
md, rc, err := b.backend.GetCAR(ctx, path, params)
b.updateBackendCallMetric(name, err, begin)
return rc, err
return md, rc, err
}

func (b *ipfsBackendWithMetrics) IsCached(ctx context.Context, path path.Path) bool {
Expand Down

0 comments on commit 7be4474

Please sign in to comment.