package corehttp import ( "bytes" "context" "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(ctx context.Context, w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, begin time.Time) { ctx, span := tracing.Span(ctx, "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()) } }