kubo/core/corehttp/gateway_handler_block.go
Ian Davis fbf76663f4
fix(gw): update metrics only when payload data sent (#8827)
* fix: report gateway http metrics only when response is successful
* fix(gw): 304 Not Modified as no-op

This fix ensures we don't do any additional work when Etag match
what user already has in their own cache.

Co-authored-by: Marcin Rataj <lidel@lidel.org>
2022-04-08 22:07:44 +02:00

50 lines
1.6 KiB
Go

package corehttp
import (
"bytes"
"io/ioutil"
"net/http"
"time"
"github.com/ipfs/go-ipfs/tracing"
ipath "github.com/ipfs/interface-go-ipfs-core/path"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)
// serveRawBlock returns bytes behind a raw block
func (i *gatewayHandler) serveRawBlock(w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, begin time.Time) {
ctx, span := tracing.Span(r.Context(), "Gateway", "ServeRawBlock", trace.WithAttributes(attribute.String("path", resolvedPath.String())))
defer span.End()
blockCid := resolvedPath.Cid()
blockReader, err := i.api.Block().Get(ctx, resolvedPath)
if err != nil {
webError(w, "ipfs block get "+blockCid.String(), err, http.StatusInternalServerError)
return
}
block, err := ioutil.ReadAll(blockReader)
if err != nil {
webError(w, "ipfs block get "+blockCid.String(), err, http.StatusInternalServerError)
return
}
content := bytes.NewReader(block)
// Set Content-Disposition
name := blockCid.String() + ".bin"
setContentDispositionHeader(w, name, "attachment")
// Set remaining headers
modtime := addCacheControlHeaders(w, r, contentPath, blockCid)
w.Header().Set("Content-Type", "application/vnd.ipld.raw")
w.Header().Set("X-Content-Type-Options", "nosniff") // no funny business in the browsers :^)
// ServeContent will take care of
// If-None-Match+Etag, Content-Length and range requests
_, dataSent, _ := ServeContent(w, r, name, modtime, content)
if dataSent {
// Update metrics
i.rawBlockGetMetric.WithLabelValues(contentPath.Namespace()).Observe(time.Since(begin).Seconds())
}
}