Skip to content

Commit

Permalink
feat(gw): set Last-Modified to value from dag-pb
Browse files Browse the repository at this point in the history
(if present)
  • Loading branch information
lidel committed Aug 21, 2024
1 parent 3cd3857 commit 0617d60
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The following emojis are used to highlight certain changes:
### Changed

- `chunker` refactored to reduce overall memory use by reducing heap fragmentation [#649](https://github.com/ipfs/boxo/pull/649)
- `gateway` deserialized responses will have `Last-Modified` set to value from optional UnixFS 1.5 modification time field (if present in DAG)

### Removed

Expand Down
12 changes: 12 additions & 0 deletions gateway/backend_blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ func (bb *BlocksBackend) Get(ctx context.Context, path path.ImmutablePath, range
return md, nil, err
}

// Set modification time in ContentPathMetadata if found in dag-pb's optional mtime field (UnixFS 1.5)
mtime := f.ModTime()
if !mtime.IsZero() {
md.ModTime = mtime
}

Check warning on line 163 in gateway/backend_blocks.go

View check run for this annotation

Codecov / codecov/patch

gateway/backend_blocks.go#L162-L163

Added lines #L162 - L163 were not covered by tests

if d, ok := f.(files.Directory); ok {
dir, err := uio.NewDirectoryFromNode(bb.dagService, nd)
if err != nil {
Expand Down Expand Up @@ -231,6 +237,12 @@ func (bb *BlocksBackend) Head(ctx context.Context, path path.ImmutablePath) (Con
return ContentPathMetadata{}, nil, err
}

// Set modification time in ContentPathMetadata if found in dag-pb's optional mtime field (UnixFS 1.5)
mtime := fileNode.ModTime()
if !mtime.IsZero() {
md.ModTime = mtime
}

Check warning on line 244 in gateway/backend_blocks.go

View check run for this annotation

Codecov / codecov/patch

gateway/backend_blocks.go#L241-L244

Added lines #L241 - L244 were not covered by tests

sz, err := fileNode.Size()
if err != nil {
return ContentPathMetadata{}, nil, err
Expand Down
3 changes: 2 additions & 1 deletion gateway/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,8 @@ type ContentPathMetadata struct {
PathSegmentRoots []cid.Cid
LastSegment path.ImmutablePath
LastSegmentRemainder []string
ContentType string // Only used for UnixFS requests
ContentType string // Only used for UnixFS requests
ModTime time.Time // Optional, non-zero values may be present in UnixFS 1.5 DAGs
}

// ByteRange describes a range request within a UnixFS file. "From" and "To" mostly
Expand Down
15 changes: 11 additions & 4 deletions gateway/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,18 +410,25 @@ func addCacheControlHeaders(w http.ResponseWriter, r *http.Request, contentPath
}

if lastMod.IsZero() {
// Otherwise, we set Last-Modified to the current time to leverage caching heuristics
// If no lastMod, set Last-Modified to the current time to leverage caching heuristics
// built into modern browsers: https://github.com/ipfs/kubo/pull/8074#pullrequestreview-645196768
modtime = time.Now()
} else {
// set Last-Modified to a meaningful value e.g. one read from dag-pb (UnixFS 1.5, mtime field)
// or the last time DNSLink / IPNS Record was modified / resoved or cache

Check warning on line 418 in gateway/handler.go

View check run for this annotation

Codecov / codecov/patch

gateway/handler.go#L417-L418

Added lines #L417 - L418 were not covered by tests
modtime = lastMod
}

} else {
w.Header().Set("Cache-Control", immutableCacheControl)
modtime = noModtime // disable Last-Modified

// TODO: consider setting Last-Modified if UnixFS V1.5 ever gets released
// with metadata: https://github.com/ipfs/kubo/issues/6920
if lastMod.IsZero() {
// (noop) skip Last-Modified on immutable response
modtime = noModtime
} else {
// set Last-Modified to value read from dag-pb (UnixFS 1.5, mtime field)
modtime = lastMod
}

Check warning on line 431 in gateway/handler.go

View check run for this annotation

Codecov / codecov/patch

gateway/handler.go#L429-L431

Added lines #L429 - L431 were not covered by tests
}

return modtime
Expand Down
8 changes: 8 additions & 0 deletions gateway/handler_defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ func (i *handler) serveDefaults(ctx context.Context, w http.ResponseWriter, r *h

setIpfsRootsHeader(w, rq, &pathMetadata)

// On deserialized responses, we prefer Last-Modified from pathMetadata
// (mtime in UnixFS 1.5 DAG). This also applies to /ipns/, because value
// from dag-pb, if present, is more meaningful than lastMod inferred from
// namesys.
if !pathMetadata.ModTime.IsZero() {
rq.lastMod = pathMetadata.ModTime
}

Check warning on line 103 in gateway/handler_defaults.go

View check run for this annotation

Codecov / codecov/patch

gateway/handler_defaults.go#L102-L103

Added lines #L102 - L103 were not covered by tests

resolvedPath := pathMetadata.LastSegment
switch mc.Code(resolvedPath.RootCid().Prefix().Codec) {
case mc.Json, mc.DagJson, mc.Cbor, mc.DagCbor:
Expand Down

0 comments on commit 0617d60

Please sign in to comment.