Skip to content

Commit 6fe39c8

Browse files
committed
add special case for text/html+codec+range
1 parent 37437dd commit 6fe39c8

File tree

2 files changed

+19
-7
lines changed

2 files changed

+19
-7
lines changed

gateway/handler_codec.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ func (i *handler) serveCodec(ctx context.Context, w http.ResponseWriter, r *http
7575
return false
7676
}
7777

78-
return i.renderCodec(ctx, w, r, rq, blockSize, data)
78+
return i.renderCodec(ctx, w, r, rq, blockSize, data, false)
7979
}
8080

81-
func (i *handler) renderCodec(ctx context.Context, w http.ResponseWriter, r *http.Request, rq *requestData, blockSize int64, blockData io.ReadSeekCloser) bool {
81+
func (i *handler) renderCodec(ctx context.Context, w http.ResponseWriter, r *http.Request, rq *requestData, blockSize int64, blockData io.ReadSeekCloser, isRangeRequest bool) bool {
8282
resolvedPath := rq.pathMetadata.LastSegment
8383
ctx, span := spanTrace(ctx, "Handler.RenderCodec", trace.WithAttributes(attribute.String("path", resolvedPath.String()), attribute.String("requestedContentType", rq.responseFormat)))
8484
defer span.End()
@@ -124,7 +124,7 @@ func (i *handler) renderCodec(ctx context.Context, w http.ResponseWriter, r *htt
124124
download := r.URL.Query().Get("download") == "true"
125125

126126
if isDAG && acceptsHTML && !download {
127-
return i.serveCodecHTML(ctx, w, r, blockCid, blockData, resolvedPath, rq.contentPath)
127+
return i.serveCodecHTML(ctx, w, r, blockCid, blockData, resolvedPath, rq.contentPath, isRangeRequest)
128128
} else {
129129
// This covers CIDs with codec 'json' and 'cbor' as those do not have
130130
// an explicit requested content type.
@@ -156,7 +156,7 @@ func (i *handler) renderCodec(ctx context.Context, w http.ResponseWriter, r *htt
156156
return i.serveCodecConverted(ctx, w, r, blockCid, blockData, rq.contentPath, toCodec, modtime, rq.begin)
157157
}
158158

159-
func (i *handler) serveCodecHTML(ctx context.Context, w http.ResponseWriter, r *http.Request, blockCid cid.Cid, blockData io.Reader, resolvedPath path.ImmutablePath, contentPath path.Path) bool {
159+
func (i *handler) serveCodecHTML(ctx context.Context, w http.ResponseWriter, r *http.Request, blockCid cid.Cid, blockData io.Reader, resolvedPath path.ImmutablePath, contentPath path.Path, isRangeRequest bool) bool {
160160
// WithHostname may have constructed an IPFS (or IPNS) path using the Host header.
161161
// In this case, we need the original path for constructing the redirect.
162162
requestURI, err := url.ParseRequestURI(r.RequestURI)
@@ -201,7 +201,7 @@ func (i *handler) serveCodecHTML(ctx context.Context, w http.ResponseWriter, r *
201201
CID: resolvedPath.RootCid().String(),
202202
CodecName: cidCodec.String(),
203203
CodecHex: fmt.Sprintf("0x%x", uint64(cidCodec)),
204-
Node: parseNode(blockCid, blockData),
204+
Node: i.parseNode(ctx, blockCid, blockData, isRangeRequest),
205205
})
206206
if err != nil {
207207
_, _ = w.Write([]byte(fmt.Sprintf("error during body generation: %v", err)))
@@ -213,7 +213,7 @@ func (i *handler) serveCodecHTML(ctx context.Context, w http.ResponseWriter, r *
213213
// parseNode does a best effort attempt to parse this request's block such that
214214
// a preview can be displayed in the gateway. If something fails along the way,
215215
// returns nil, therefore not displaying the preview.
216-
func parseNode(blockCid cid.Cid, blockData io.Reader) *assets.ParsedNode {
216+
func (i *handler) parseNode(ctx context.Context, blockCid cid.Cid, blockData io.Reader, tryGetBlockIfFailed bool) *assets.ParsedNode {
217217
codec := blockCid.Prefix().Codec
218218
decoder, err := multicodec.LookupDecoder(codec)
219219
if err != nil {
@@ -222,6 +222,18 @@ func parseNode(blockCid cid.Cid, blockData io.Reader) *assets.ParsedNode {
222222

223223
nodeBuilder := basicnode.Prototype.Any.NewBuilder()
224224
err = decoder(nodeBuilder, blockData)
225+
if err != nil && tryGetBlockIfFailed {
226+
// It is possible we don't have the whole data for this block, e.g.,
227+
// if range request is made from a browser where we want to display HTML.
228+
// This does one attempt of fetching the data.
229+
_, blockData, err = i.backend.GetBlock(ctx, path.FromCid(blockCid))
230+
if err != nil {
231+
return nil
232+
}
233+
234+
nodeBuilder = basicnode.Prototype.Any.NewBuilder()
235+
err = decoder(nodeBuilder, blockData)
236+
}
225237
if err != nil {
226238
return nil
227239
}

gateway/handler_defaults.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ func (i *handler) serveDefaults(ctx context.Context, w http.ResponseWriter, r *h
112112
dataToRender = dataAsReadSeekCloser
113113
}
114114

115-
return i.renderCodec(r.Context(), w, r, rq, blockSize, dataToRender)
115+
return i.renderCodec(r.Context(), w, r, rq, blockSize, dataToRender, len(ranges) > 0)
116116
default:
117117
rq.logger.Debugw("serving unixfs", "path", rq.contentPath)
118118
ctx, span := spanTrace(ctx, "Handler.ServeUnixFS", trace.WithAttributes(attribute.String("path", resolvedPath.String())))

0 commit comments

Comments
 (0)