Skip to content

Commit

Permalink
wip: add application/json and application/cbor
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias committed Oct 7, 2022
1 parent 3a25b14 commit 482e385
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 47 deletions.
14 changes: 11 additions & 3 deletions core/corehttp/gateway_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -432,12 +432,14 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
i.serveCAR(r.Context(), w, r, resolvedPath, contentPath, carVersion, begin)
return
case "application/vnd.ipld.dag-json":
case "application/json":
logger.Debugw("serving dag-json", "path", contentPath)
i.serveJSON(r.Context(), w, r, resolvedPath, begin, "application/vnd.ipld.dag-json", uint64(mc.DagJson))
i.serveCodec(r.Context(), w, r, resolvedPath, contentPath, begin, responseFormat, uint64(mc.DagJson))
return
case "application/vnd.ipld.dag-cbor":
case "application/cbor":
logger.Debugw("serving dag-cbor", "path", contentPath)
i.serveJSON(r.Context(), w, r, resolvedPath, begin, "application/vnd.ipld.dag-cbor", uint64(mc.DagCbor))
i.serveCodec(r.Context(), w, r, resolvedPath, contentPath, begin, responseFormat, uint64(mc.DagCbor))
return
default: // catch-all for unsuported application/vnd.*
err := fmt.Errorf("unsupported format %q", responseFormat)
Expand Down Expand Up @@ -870,16 +872,22 @@ func customResponseFormat(r *http.Request) (mediaType string, params map[string]
return "application/vnd.ipld.car", nil, nil
case "dag-json":
return "application/vnd.ipld.dag-json", nil, nil
case "json":
return "application/json", nil, nil
case "dag-cbor":
return "application/vnd.ipld.dag-cbor", nil, nil
case "cbor":
return "application/cbor", nil, nil
}
}
// Browsers and other user agents will send Accept header with generic types like:
// Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
// We only care about explciit, vendor-specific content-types.
for _, accept := range r.Header.Values("Accept") {
// respond to the very first ipld content type
if strings.HasPrefix(accept, "application/vnd.ipld") {
if strings.HasPrefix(accept, "application/vnd.ipld") ||
strings.HasPrefix(accept, "application/json") ||
strings.HasPrefix(accept, "application/cbor") {
mediatype, params, err := mime.ParseMediaType(accept)
if err != nil {
return "", nil, err
Expand Down
58 changes: 58 additions & 0 deletions core/corehttp/gateway_handler_codec.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package corehttp

import (
"context"
"fmt"
"html"
"net/http"
"time"

ipldlegacy "github.com/ipfs/go-ipld-legacy"
ipath "github.com/ipfs/interface-go-ipfs-core/path"
"github.com/ipfs/kubo/tracing"
"github.com/ipld/go-ipld-prime"
"github.com/ipld/go-ipld-prime/multicodec"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)

var unixEpochTime = time.Unix(0, 0)

func (i *gatewayHandler) serveCodec(ctx context.Context, w http.ResponseWriter, r *http.Request, resolvedPath ipath.Resolved, contentPath ipath.Path, begin time.Time, ctype string, codec uint64) {
ctx, span := tracing.Span(ctx, "Gateway", "ServeCodec", trace.WithAttributes(attribute.String("path", resolvedPath.String()), attribute.String("ctype", ctype)))
defer span.End()

// Set Cache-Control and read optional Last-Modified time
modtime := addCacheControlHeaders(w, r, contentPath, resolvedPath.Cid())

// Sets correct Last-Modified header. This code is borrowed from the standard
// library (net/http/server.go) as we cannot use serveFile.
if !(modtime.IsZero() || modtime.Equal(unixEpochTime)) {
w.Header().Set("Last-Modified", modtime.UTC().Format(http.TimeFormat))
}

addContentDispositionHeader(w, r, contentPath)
w.Header().Set("Content-Type", ctype)
w.Header().Set("X-Content-Type-Options", "nosniff")

obj, err := i.api.Dag().Get(ctx, resolvedPath.Cid())
if err != nil {
webError(w, "ipfs dag get "+html.EscapeString(resolvedPath.String()), err, http.StatusInternalServerError)
return
}

universal, ok := obj.(ipldlegacy.UniversalNode)
if !ok {
webError(w, "todo", fmt.Errorf("%T is not a valid IPLD node", obj), http.StatusInternalServerError)
return
}
finalNode := universal.(ipld.Node)

encoder, err := multicodec.LookupEncoder(codec)
if err != nil {
webError(w, "todo", err, http.StatusInternalServerError)
return
}

_ = encoder(finalNode, w)
}
44 changes: 0 additions & 44 deletions core/corehttp/gateway_handler_json.go

This file was deleted.

0 comments on commit 482e385

Please sign in to comment.