Skip to content

Commit

Permalink
Separate encrypted and non-encrypted paths
Browse files Browse the repository at this point in the history
Do not rely on dbl-sha2-256 codec to determine if querying for encrypted or non-encrypted multihash. Use URL path instead.

Fixes #127

Requires ipni/dhstore#84
  • Loading branch information
gammazero committed Aug 29, 2023
1 parent d27c5a6 commit 0013039
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 57 deletions.
29 changes: 12 additions & 17 deletions delegated_translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"io"
"net/http"
"net/url"
"path"
"strings"

"github.com/filecoin-project/index-provider/metadata"
Expand All @@ -27,13 +26,15 @@ const (
unknownSchema = unknownProtocol
)

type findFunc func(ctx context.Context, method, source string, req *url.URL, body []byte, mh multihash.Multihash) (int, []byte)
type findFunc func(ctx context.Context, method, source string, req *url.URL, body []byte, mh multihash.Multihash, encrypted bool) (int, []byte)

func NewDelegatedTranslator(backend findFunc) (http.Handler, error) {
finder := delegatedTranslator{backend}
m := http.NewServeMux()
m.HandleFunc("/providers", finder.provide)
m.HandleFunc("/providers/", finder.find)
m.HandleFunc("/encrypted/providers", finder.provide)
m.HandleFunc("/providers/", func(w http.ResponseWriter, r *http.Request) { finder.find(w, r, false) })
m.HandleFunc("/encrypted/providers/", func(w http.ResponseWriter, r *http.Request) { finder.find(w, r, true) })
return m, nil
}

Expand All @@ -60,7 +61,7 @@ func (dt *delegatedTranslator) provide(w http.ResponseWriter, r *http.Request) {
}
}

func (dt *delegatedTranslator) find(w http.ResponseWriter, r *http.Request) {
func (dt *delegatedTranslator) find(w http.ResponseWriter, r *http.Request, encrypted bool) {
_ = stats.RecordWithOptions(context.Background(),
stats.WithTags(tag.Insert(metrics.Method, r.Method)),
stats.WithMeasurements(metrics.HttpDelegatedRoutingMethod.M(1)))
Expand Down Expand Up @@ -88,17 +89,11 @@ func (dt *delegatedTranslator) find(w http.ResponseWriter, r *http.Request) {
}

// Translate URL by mapping `/providers/{CID}` to `/cid/{CID}`.
cidUrlParam := strings.TrimPrefix(r.URL.Path, "/providers/")
// TODO: replace with URL.JoinPath once upgraded to go 1.19
findByCid := path.Join("/cid", cidUrlParam)
if err != nil {
http.Error(w, "", http.StatusBadRequest)
return
}
uri, err := url.ParseRequestURI(findByCid)
if err != nil {
http.Error(w, "", http.StatusInternalServerError)
return
var cidUrlParam string
if encrypted {
cidUrlParam = strings.TrimPrefix(r.URL.Path, "/encrypted/providers/")
} else {
cidUrlParam = strings.TrimPrefix(r.URL.Path, "/providers/")
}

c, err := cid.Decode(cidUrlParam)
Expand All @@ -107,8 +102,8 @@ func (dt *delegatedTranslator) find(w http.ResponseWriter, r *http.Request) {
return
}

rcode, resp := dt.be(r.Context(), http.MethodGet, findMethodDelegated, uri, []byte{}, c.Hash())

uri := r.URL.JoinPath("../cid", cidUrlParam)
rcode, resp := dt.be(r.Context(), http.MethodGet, findMethodDelegated, uri, []byte{}, c.Hash(), encrypted)
if rcode != http.StatusOK {
http.Error(w, "", rcode)
return
Expand Down
38 changes: 14 additions & 24 deletions find.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const (
findMethodDelegated = "delegated-v1"
)

func (s *server) findCid(w http.ResponseWriter, r *http.Request) {
func (s *server) findCid(w http.ResponseWriter, r *http.Request, encrypted bool) {
switch r.Method {
case http.MethodOptions:
discardBody(r)
Expand All @@ -39,41 +39,39 @@ func (s *server) findCid(w http.ResponseWriter, r *http.Request) {
discardBody(r)
http.Error(w, "invalid cid: "+err.Error(), http.StatusBadRequest)
}
s.find(w, r, c.Hash())
s.find(w, r, c.Hash(), encrypted)
default:
discardBody(r)
http.Error(w, "", http.StatusNotFound)
}
}

func (s *server) findMultihash(w http.ResponseWriter, r *http.Request) {
func (s *server) findMultihash(w http.ResponseWriter, r *http.Request, encrypted bool) {
switch r.Method {
case http.MethodOptions:
discardBody(r)
handleIPNIOptions(w, true)
case http.MethodPost:
s.find(w, r, nil)
s.find(w, r, nil, encrypted)
default:
discardBody(r)
http.Error(w, "", http.StatusNotFound)
}
}

func (s *server) findMultihashSubtree(w http.ResponseWriter, r *http.Request) {
func (s *server) findMultihashSubtree(w http.ResponseWriter, r *http.Request, encrypted bool) {
switch r.Method {
case http.MethodOptions:
discardBody(r)
handleIPNIOptions(w, false)
case http.MethodGet:

smh := strings.TrimPrefix(path.Base(r.URL.Path), "multihash/")
smh := path.Base(r.URL.Path)
mh, err := multihash.FromB58String(smh)
if err != nil {
discardBody(r)
http.Error(w, "invalid multihash: "+err.Error(), http.StatusBadRequest)
}

s.find(w, r, mh)
s.find(w, r, mh, encrypted)
default:
discardBody(r)
http.Error(w, "", http.StatusNotFound)
Expand Down Expand Up @@ -167,7 +165,7 @@ func (s *server) findMetadataSubtree(w http.ResponseWriter, r *http.Request) {
http.Error(w, "", http.StatusNotFound)
}

func (s *server) find(w http.ResponseWriter, r *http.Request, mh multihash.Multihash) {
func (s *server) find(w http.ResponseWriter, r *http.Request, mh multihash.Multihash, encrypted bool) {
acc, err := getAccepts(r)
if err != nil {
discardBody(r)
Expand All @@ -193,7 +191,7 @@ func (s *server) find(w http.ResponseWriter, r *http.Request, mh multihash.Multi
http.Error(w, "", http.StatusBadRequest)
return
}
rcode, resp := s.doFind(r.Context(), r.Method, findMethodOrig, r.URL, rb, mh)
rcode, resp := s.doFind(r.Context(), r.Method, findMethodOrig, r.URL, rb, mh, encrypted)
if rcode != http.StatusOK {
http.Error(w, "", rcode)
return
Expand All @@ -211,15 +209,15 @@ func (s *server) find(w http.ResponseWriter, r *http.Request, mh multihash.Multi
// JSON unless only unsupported media types are specified.
switch {
case acc.ndjson:
s.doFindNDJson(ctx, w, findMethodOrig, r.URL, false, mh)
s.doFindNDJson(ctx, w, findMethodOrig, r.URL, false, mh, encrypted)
case acc.json || acc.any || !acc.acceptHeaderFound:
if s.translateNonStreaming {
s.doFindNDJson(ctx, w, findMethodOrig, r.URL, true, mh)
s.doFindNDJson(ctx, w, findMethodOrig, r.URL, true, mh, encrypted)
return
}
// In a case where the request has no `Accept` header at all, be forgiving and respond with
// JSON.
rcode, resp := s.doFind(ctx, r.Method, findMethodOrig, r.URL, rb, mh)
rcode, resp := s.doFind(ctx, r.Method, findMethodOrig, r.URL, rb, mh, encrypted)
if rcode != http.StatusOK {
http.Error(w, "", rcode)
return
Expand All @@ -231,7 +229,7 @@ func (s *server) find(w http.ResponseWriter, r *http.Request, mh multihash.Multi
}
}

func (s *server) doFind(ctx context.Context, method, source string, req *url.URL, body []byte, mh multihash.Multihash) (int, []byte) {
func (s *server) doFind(ctx context.Context, method, source string, req *url.URL, body []byte, mh multihash.Multihash, encrypted bool) (int, []byte) {
start := time.Now()
latencyTags := []tag.Mutator{tag.Insert(metrics.Method, method)}
loadTags := []tag.Mutator{tag.Insert(metrics.Method, source)}
Expand All @@ -244,12 +242,6 @@ func (s *server) doFind(ctx context.Context, method, source string, req *url.URL
stats.WithMeasurements(metrics.FindLoad.M(1)))
}()

dmh, err := multihash.Decode(mh)
if err != nil {
log.Warnw("failed to decode multihash", "err", err)
return http.StatusInternalServerError, nil
}

// sgResponse is a struct that exists to capture the backend that the response has been received from
type sgResponse struct {
rsp *model.FindResponse
Expand All @@ -269,9 +261,7 @@ func (s *server) doFind(ctx context.Context, method, source string, req *url.URL
// forward double hashed requests to double hashed backends only and regular requests to regular backends
_, isDhBackend := b.(dhBackend)
_, isProvidersBackend := b.(providersBackend)
if (dmh.Code == multihash.DBL_SHA2_256 && !isDhBackend) ||
(dmh.Code != multihash.DBL_SHA2_256 && isDhBackend) ||
isProvidersBackend {
if (encrypted != isDhBackend) || isProvidersBackend {
return nil, nil
}

Expand Down
14 changes: 3 additions & 11 deletions find_ndjson.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (rs *resultStats) reportMetrics(method string) {
}
}

func (s *server) doFindNDJson(ctx context.Context, w http.ResponseWriter, source string, req *url.URL, translateNonStreaming bool, mh multihash.Multihash) {
func (s *server) doFindNDJson(ctx context.Context, w http.ResponseWriter, source string, req *url.URL, translateNonStreaming bool, mh multihash.Multihash, encrypted bool) {
start := time.Now()
latencyTags := []tag.Mutator{tag.Insert(metrics.Method, http.MethodGet)}
loadTags := []tag.Mutator{tag.Insert(metrics.Method, source)}
Expand All @@ -146,13 +146,7 @@ func (s *server) doFindNDJson(ctx context.Context, w http.ResponseWriter, source
stats.WithTags(loadTags...),
stats.WithMeasurements(metrics.FindLoad.M(1)))
}()
dmh, err := multihash.Decode(mh)
if err != nil {
msg := "Cannot decode multihash"
log.Errorw(msg, "err", err)
http.Error(w, msg, http.StatusBadRequest)
return
}

var maxWait time.Duration
if translateNonStreaming {
maxWait = config.Server.ResultMaxWait
Expand All @@ -179,9 +173,7 @@ func (s *server) doFindNDJson(ctx context.Context, w http.ResponseWriter, source
// forward double hashed requests to double hashed backends only and regular requests to regular backends
_, isDhBackend := b.(dhBackend)
_, isProvidersBackend := b.(providersBackend)
if (dmh.Code == multihash.DBL_SHA2_256 && !isDhBackend) ||
(dmh.Code != multihash.DBL_SHA2_256 && isDhBackend) ||
isProvidersBackend {
if (encrypted != isDhBackend) || isProvidersBackend {
return nil, nil
}

Expand Down
12 changes: 7 additions & 5 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,17 +236,19 @@ func (s *server) Reload(cctx *cli.Context) error {
}

func (s *server) Serve() chan error {
ec := make(chan error)

mux := http.NewServeMux()
mux.HandleFunc("/cid/", s.findCid)
mux.HandleFunc("/multihash", s.findMultihash)
mux.HandleFunc("/multihash/", s.findMultihashSubtree)
mux.HandleFunc("/cid/", func(w http.ResponseWriter, r *http.Request) { s.findCid(w, r, false) })
mux.HandleFunc("/encrypted/cid/", func(w http.ResponseWriter, r *http.Request) { s.findCid(w, r, true) })
mux.HandleFunc("/multihash", func(w http.ResponseWriter, r *http.Request) { s.findMultihash(w, r, false) })
mux.HandleFunc("/encrypted/multihash", func(w http.ResponseWriter, r *http.Request) { s.findMultihash(w, r, true) })
mux.HandleFunc("/multihash/", func(w http.ResponseWriter, r *http.Request) { s.findMultihashSubtree(w, r, false) })
mux.HandleFunc("/encrypted/multihash/", func(w http.ResponseWriter, r *http.Request) { s.findMultihashSubtree(w, r, true) })
mux.HandleFunc("/metadata/", s.findMetadataSubtree)
mux.HandleFunc("/providers", s.providers)
mux.HandleFunc("/providers/", s.provider)
mux.HandleFunc("/health", s.health)

ec := make(chan error)
delegated, err := NewDelegatedTranslator(s.doFind)
if err != nil {
ec <- err
Expand Down

0 comments on commit 0013039

Please sign in to comment.