Skip to content

Commit 134f098

Browse files
authored
Merge pull request ipfs/kubo#9306 from ipfs/release-v0.16.0
release v0.16.0 This commit was moved from ipfs/kubo@38117db
2 parents d112b2e + 59b3312 commit 134f098

11 files changed

+361
-104
lines changed

gateway/core/corehttp/gateway.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
type GatewayConfig struct {
2121
Headers map[string][]string
2222
Writable bool
23-
PathPrefixes []string
2423
FastDirIndexThreshold int
2524
}
2625

@@ -86,7 +85,6 @@ func GatewayOption(writable bool, paths ...string) ServeOption {
8685
gateway := NewGatewayHandler(GatewayConfig{
8786
Headers: headers,
8887
Writable: writable,
89-
PathPrefixes: cfg.Gateway.PathPrefixes,
9088
FastDirIndexThreshold: int(cfg.Gateway.FastDirIndexThreshold.WithDefault(100)),
9189
}, api, offlineApi)
9290

@@ -148,7 +146,7 @@ func VersionOption() ServeOption {
148146
mux.HandleFunc("/version", func(w http.ResponseWriter, r *http.Request) {
149147
fmt.Fprintf(w, "Commit: %s\n", version.CurrentCommit)
150148
fmt.Fprintf(w, "Client Version: %s\n", version.GetUserAgentVersion())
151-
fmt.Fprintf(w, "Protocol Version: %s\n", id.LibP2PVersion)
149+
fmt.Fprintf(w, "Protocol Version: %s\n", id.DefaultProtocolVersion)
152150
})
153151
return mux, nil
154152
}

gateway/core/corehttp/gateway_handler.go

Lines changed: 48 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
gopath "path"
1414
"regexp"
1515
"runtime/debug"
16-
"strconv"
1716
"strings"
1817
"time"
1918

@@ -26,7 +25,7 @@ import (
2625
"github.com/ipfs/go-path/resolver"
2726
coreiface "github.com/ipfs/interface-go-ipfs-core"
2827
ipath "github.com/ipfs/interface-go-ipfs-core/path"
29-
routing "github.com/libp2p/go-libp2p-core/routing"
28+
routing "github.com/libp2p/go-libp2p/core/routing"
3029
prometheus "github.com/prometheus/client_golang/prometheus"
3130
"go.opentelemetry.io/otel/attribute"
3231
"go.opentelemetry.io/otel/trace"
@@ -378,30 +377,18 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
378377
return
379378
}
380379

381-
// Resolve path to the final DAG node for the ETag
382-
resolvedPath, err := i.api.ResolvePath(r.Context(), contentPath)
383-
switch err {
384-
case nil:
385-
case coreiface.ErrOffline:
386-
webError(w, "ipfs resolve -r "+debugStr(contentPath.String()), err, http.StatusServiceUnavailable)
387-
return
388-
default:
389-
// if Accept is text/html, see if ipfs-404.html is present
390-
if i.servePretty404IfPresent(w, r, contentPath) {
391-
logger.Debugw("serve pretty 404 if present")
392-
return
393-
}
394-
webError(w, "ipfs resolve -r "+debugStr(contentPath.String()), err, http.StatusBadRequest)
395-
return
396-
}
397-
398380
// Detect when explicit Accept header or ?format parameter are present
399381
responseFormat, formatParams, err := customResponseFormat(r)
400382
if err != nil {
401383
webError(w, "error while processing the Accept header", err, http.StatusBadRequest)
402384
return
403385
}
404386
trace.SpanFromContext(r.Context()).SetAttributes(attribute.String("ResponseFormat", responseFormat))
387+
388+
resolvedPath, contentPath, ok := i.handlePathResolution(w, r, responseFormat, contentPath, logger)
389+
if !ok {
390+
return
391+
}
405392
trace.SpanFromContext(r.Context()).SetAttributes(attribute.String("ResolvedPath", resolvedPath.String()))
406393

407394
// Detect when If-None-Match HTTP header allows returning HTTP 304 Not Modified
@@ -450,36 +437,6 @@ func (i *gatewayHandler) getOrHeadHandler(w http.ResponseWriter, r *http.Request
450437
}
451438
}
452439

453-
func (i *gatewayHandler) servePretty404IfPresent(w http.ResponseWriter, r *http.Request, contentPath ipath.Path) bool {
454-
resolved404Path, ctype, err := i.searchUpTreeFor404(r, contentPath)
455-
if err != nil {
456-
return false
457-
}
458-
459-
dr, err := i.api.Unixfs().Get(r.Context(), resolved404Path)
460-
if err != nil {
461-
return false
462-
}
463-
defer dr.Close()
464-
465-
f, ok := dr.(files.File)
466-
if !ok {
467-
return false
468-
}
469-
470-
size, err := f.Size()
471-
if err != nil {
472-
return false
473-
}
474-
475-
log.Debugw("using pretty 404 file", "path", contentPath)
476-
w.Header().Set("Content-Type", ctype)
477-
w.Header().Set("Content-Length", strconv.FormatInt(size, 10))
478-
w.WriteHeader(http.StatusNotFound)
479-
_, err = io.CopyN(w, f, size)
480-
return err == nil
481-
}
482-
483440
func (i *gatewayHandler) postHandler(w http.ResponseWriter, r *http.Request) {
484441
p, err := i.api.Unixfs().Add(r.Context(), files.NewReaderFile(r.Body))
485442
if err != nil {
@@ -920,55 +877,56 @@ func customResponseFormat(r *http.Request) (mediaType string, params map[string]
920877
return "", nil, nil
921878
}
922879

923-
func (i *gatewayHandler) searchUpTreeFor404(r *http.Request, contentPath ipath.Path) (ipath.Resolved, string, error) {
924-
filename404, ctype, err := preferred404Filename(r.Header.Values("Accept"))
925-
if err != nil {
926-
return nil, "", err
880+
// returns unquoted path with all special characters revealed as \u codes
881+
func debugStr(path string) string {
882+
q := fmt.Sprintf("%+q", path)
883+
if len(q) >= 3 {
884+
q = q[1 : len(q)-1]
927885
}
886+
return q
887+
}
928888

929-
pathComponents := strings.Split(contentPath.String(), "/")
930-
931-
for idx := len(pathComponents); idx >= 3; idx-- {
932-
pretty404 := gopath.Join(append(pathComponents[0:idx], filename404)...)
933-
parsed404Path := ipath.New("/" + pretty404)
934-
if parsed404Path.IsValid() != nil {
935-
break
936-
}
937-
resolvedPath, err := i.api.ResolvePath(r.Context(), parsed404Path)
938-
if err != nil {
939-
continue
940-
}
941-
return resolvedPath, ctype, nil
942-
}
889+
// Resolve the provided contentPath including any special handling related to
890+
// the requested responseFormat. Returned ok flag indicates if gateway handler
891+
// should continue processing the request.
892+
func (i *gatewayHandler) handlePathResolution(w http.ResponseWriter, r *http.Request, responseFormat string, contentPath ipath.Path, logger *zap.SugaredLogger) (resolvedPath ipath.Resolved, newContentPath ipath.Path, ok bool) {
893+
// Attempt to resolve the provided path.
894+
resolvedPath, err := i.api.ResolvePath(r.Context(), contentPath)
943895

944-
return nil, "", fmt.Errorf("no pretty 404 in any parent folder")
945-
}
896+
switch err {
897+
case nil:
898+
return resolvedPath, contentPath, true
899+
case coreiface.ErrOffline:
900+
webError(w, "ipfs resolve -r "+debugStr(contentPath.String()), err, http.StatusServiceUnavailable)
901+
return nil, nil, false
902+
default:
903+
// The path can't be resolved.
904+
if isUnixfsResponseFormat(responseFormat) {
905+
// If we have origin isolation (subdomain gw, DNSLink website),
906+
// and response type is UnixFS (default for website hosting)
907+
// check for presence of _redirects file and apply rules defined there.
908+
// See: https://github.com/ipfs/specs/pull/290
909+
if hasOriginIsolation(r) {
910+
resolvedPath, newContentPath, ok, hadMatchingRule := i.serveRedirectsIfPresent(w, r, resolvedPath, contentPath, logger)
911+
if hadMatchingRule {
912+
logger.Debugw("applied a rule from _redirects file")
913+
return resolvedPath, newContentPath, ok
914+
}
915+
}
946916

947-
func preferred404Filename(acceptHeaders []string) (string, string, error) {
948-
// If we ever want to offer a 404 file for a different content type
949-
// then this function will need to parse q weightings, but for now
950-
// the presence of anything matching HTML is enough.
951-
for _, acceptHeader := range acceptHeaders {
952-
accepted := strings.Split(acceptHeader, ",")
953-
for _, spec := range accepted {
954-
contentType := strings.SplitN(spec, ";", 1)[0]
955-
switch contentType {
956-
case "*/*", "text/*", "text/html":
957-
return "ipfs-404.html", "text/html", nil
917+
// if Accept is text/html, see if ipfs-404.html is present
918+
// This logic isn't documented and will likely be removed at some point.
919+
// Any 404 logic in _redirects above will have already run by this time, so it's really an extra fall back
920+
if i.serveLegacy404IfPresent(w, r, contentPath) {
921+
logger.Debugw("served legacy 404")
922+
return nil, nil, false
958923
}
959924
}
960-
}
961925

962-
return "", "", fmt.Errorf("there is no 404 file for the requested content types")
963-
}
964-
965-
// returns unquoted path with all special characters revealed as \u codes
966-
func debugStr(path string) string {
967-
q := fmt.Sprintf("%+q", path)
968-
if len(q) >= 3 {
969-
q = q[1 : len(q)-1]
926+
// Note: webError will replace http.StatusBadRequest with StatusNotFound if necessary
927+
webError(w, "ipfs resolve -r "+debugStr(contentPath.String()), err, http.StatusBadRequest)
928+
return nil, nil, false
970929
}
971-
return q
972930
}
973931

974932
// Detect 'Cache-Control: only-if-cached' in request and return data if it is already in the local datastore.

0 commit comments

Comments
 (0)