Skip to content

Commit

Permalink
feat: bzz resource info API (#4588)
Browse files Browse the repository at this point in the history
  • Loading branch information
notanatol authored Feb 29, 2024
1 parent 4dd8371 commit 93ed7ed
Show file tree
Hide file tree
Showing 8 changed files with 93 additions and 15 deletions.
40 changes: 40 additions & 0 deletions openapi/Swarm.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,26 @@ paths:
$ref: "SwarmCommon.yaml#/components/responses/400"
default:
description: Default response
head:
summary: Requests the headers containing the content type and length for the reference
tags:
- Bytes
parameters:
- in: path
name: address
schema:
$ref: "SwarmCommon.yaml#/components/schemas/SwarmAddress"
required: true
description: Swarm address of chunk
responses:
"200":
description: Chunk exists
"400":
$ref: "SwarmCommon.yaml#/components/responses/400"
"404":
$ref: "SwarmCommon.yaml#/components/responses/404"
default:
description: Default response

"/chunks":
post:
Expand Down Expand Up @@ -332,6 +352,26 @@ paths:
$ref: "SwarmCommon.yaml#/components/responses/500"
default:
description: Default response
head:
summary: Get the headers containing the content type and length for the reference
tags:
- BZZ
parameters:
- in: path
name: address
schema:
$ref: "SwarmCommon.yaml#/components/schemas/SwarmAddress"
required: true
description: Swarm address of chunk
responses:
"200":
description: Chunk exists
"400":
$ref: "SwarmCommon.yaml#/components/responses/400"
"404":
$ref: "SwarmCommon.yaml#/components/responses/404"
default:
description: Default response

"/bzz/{reference}/{path}":
get:
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/bytes.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ func (s *Service) bytesGetHandler(w http.ResponseWriter, r *http.Request) {
ContentTypeHeader: {"application/octet-stream"},
}

s.downloadHandler(logger, w, r, paths.Address, additionalHeaders, true)
s.downloadHandler(logger, w, r, paths.Address, additionalHeaders, true, false)
}

func (s *Service) bytesHeadHandler(w http.ResponseWriter, r *http.Request) {
Expand Down
43 changes: 34 additions & 9 deletions pkg/api/bzz.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,10 +299,29 @@ func (s *Service) bzzDownloadHandler(w http.ResponseWriter, r *http.Request) {
paths.Path = strings.TrimRight(paths.Path, "/") + "/" // NOTE: leave one slash if there was some.
}

s.serveReference(logger, paths.Address, paths.Path, w, r)
s.serveReference(logger, paths.Address, paths.Path, w, r, false)
}

func (s *Service) serveReference(logger log.Logger, address swarm.Address, pathVar string, w http.ResponseWriter, r *http.Request) {
func (s *Service) bzzHeadHandler(w http.ResponseWriter, r *http.Request) {
logger := tracing.NewLoggerWithTraceID(r.Context(), s.logger.WithName("head_bzz_by_path").Build())

paths := struct {
Address swarm.Address `map:"address,resolve" validate:"required"`
Path string `map:"path"`
}{}
if response := s.mapStructure(mux.Vars(r), &paths); response != nil {
response("invalid path params", logger, w)
return
}

if strings.HasSuffix(paths.Path, "/") {
paths.Path = strings.TrimRight(paths.Path, "/") + "/" // NOTE: leave one slash if there was some.
}

s.serveReference(logger, paths.Address, paths.Path, w, r, true)
}

func (s *Service) serveReference(logger log.Logger, address swarm.Address, pathVar string, w http.ResponseWriter, r *http.Request, headerOnly bool) {
loggerV1 := logger.V(1).Build()

headers := struct {
Expand Down Expand Up @@ -404,7 +423,7 @@ FETCH:
// index document exists
logger.Debug("bzz download: serving path", "path", pathWithIndex)

s.serveManifestEntry(logger, w, r, indexDocumentManifestEntry, !feedDereferenced)
s.serveManifestEntry(logger, w, r, indexDocumentManifestEntry, !feedDereferenced, headerOnly)
return
}
}
Expand Down Expand Up @@ -447,7 +466,7 @@ FETCH:
// index document exists
logger.Debug("bzz download: serving path", "path", pathWithIndex)

s.serveManifestEntry(logger, w, r, indexDocumentManifestEntry, !feedDereferenced)
s.serveManifestEntry(logger, w, r, indexDocumentManifestEntry, !feedDereferenced, headerOnly)
return
}
}
Expand All @@ -461,7 +480,7 @@ FETCH:
// error document exists
logger.Debug("bzz download: serving path", "path", errorDocumentPath)

s.serveManifestEntry(logger, w, r, errorDocumentManifestEntry, !feedDereferenced)
s.serveManifestEntry(logger, w, r, errorDocumentManifestEntry, !feedDereferenced, headerOnly)
return
}
}
Expand All @@ -475,15 +494,15 @@ FETCH:
}

// serve requested path
s.serveManifestEntry(logger, w, r, me, !feedDereferenced)
s.serveManifestEntry(logger, w, r, me, !feedDereferenced, headerOnly)
}

func (s *Service) serveManifestEntry(
logger log.Logger,
w http.ResponseWriter,
r *http.Request,
manifestEntry manifest.Entry,
etag bool,
etag, headersOnly bool,
) {
additionalHeaders := http.Header{}
mtdt := manifestEntry.Metadata()
Expand All @@ -496,11 +515,11 @@ func (s *Service) serveManifestEntry(
additionalHeaders[ContentTypeHeader] = []string{mimeType}
}

s.downloadHandler(logger, w, r, manifestEntry.Reference(), additionalHeaders, etag)
s.downloadHandler(logger, w, r, manifestEntry.Reference(), additionalHeaders, etag, headersOnly)
}

// downloadHandler contains common logic for dowloading Swarm file from API
func (s *Service) downloadHandler(logger log.Logger, w http.ResponseWriter, r *http.Request, reference swarm.Address, additionalHeaders http.Header, etag bool) {
func (s *Service) downloadHandler(logger log.Logger, w http.ResponseWriter, r *http.Request, reference swarm.Address, additionalHeaders http.Header, etag, headersOnly bool) {
headers := struct {
Strategy *getter.Strategy `map:"Swarm-Redundancy-Strategy"`
FallbackMode *bool `map:"Swarm-Redundancy-Fallback-Mode"`
Expand Down Expand Up @@ -551,6 +570,12 @@ func (s *Service) downloadHandler(logger log.Logger, w http.ResponseWriter, r *h
}
w.Header().Set(ContentLengthHeader, strconv.FormatInt(l, 10))
w.Header().Set("Access-Control-Expose-Headers", ContentDispositionHeader)

if headersOnly {
w.WriteHeader(http.StatusOK)
return
}

bufSize := lookaheadBufferSize(l)
if headers.LookaheadBufferSize != nil {
bufSize = *(headers.LookaheadBufferSize)
Expand Down
12 changes: 11 additions & 1 deletion pkg/api/bzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,8 +521,18 @@ func TestBzzFiles(t *testing.T) {
jsonhttptest.WithRequestHeader(api.ContentTypeHeader, "text/html; charset=utf-8"),
jsonhttptest.WithNonEmptyResponseHeader(api.SwarmTagHeader),
)
})

t.Run("head", func(t *testing.T) {
rootHash := "65148cd89b58e91616773f5acea433f7b5a6274f2259e25f4893a332b74a7e28"

jsonhttptest.Request(t, client, http.MethodHead, fileDownloadResource(rootHash), http.StatusOK,
jsonhttptest.WithRequestHeader(api.SwarmPostageBatchIdHeader, batchOkStr),
jsonhttptest.WithRequestBody(bytes.NewReader(simpleData)),
jsonhttptest.WithRequestHeader(api.ContentTypeHeader, "text/html; charset=utf-8"),
jsonhttptest.WithExpectedContentLength(21),
)
})
})
}

// TestRangeRequests validates that all endpoints are serving content with
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/cors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func TestCors(t *testing.T) {
expectedMethods: "POST",
}, {
endpoint: "bzz/0101011",
expectedMethods: "GET",
expectedMethods: "GET, HEAD",
},
{
endpoint: "chunks",
Expand Down
3 changes: 3 additions & 0 deletions pkg/api/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ func (s *Service) mountAPI() {
s.newTracingHandler("bzz-download"),
web.FinalHandlerFunc(s.bzzDownloadHandler),
),
"HEAD": web.ChainHandlers(
web.FinalHandlerFunc(s.bzzHeadHandler),
),
})

handle("/pss/send/{topic}/{targets}", web.ChainHandlers(
Expand Down
2 changes: 1 addition & 1 deletion pkg/api/subdomain.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ func (s *Service) subdomainHandler(w http.ResponseWriter, r *http.Request) {
paths.Path = strings.TrimRight(paths.Path, "/") + "/" // NOTE: leave one slash if there was some.
}

s.serveReference(logger, paths.Subdomain, paths.Path, w, r)
s.serveReference(logger, paths.Subdomain, paths.Path, w, r, false)
}
4 changes: 2 additions & 2 deletions pkg/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,15 +242,15 @@ func (e encrypter) decrypt(data []byte) ([]byte, error) {

func applyPolicies(e *casbin.Enforcer) error {
_, err := e.AddPolicies([][]string{
{"consumer", "/bytes/*", "GET"},
{"consumer", "/bytes/*", "(GET)|(HEAD)"},
{"creator", "/bytes", "POST"},
{"consumer", "/chunks/*", "GET"},
{"creator", "/chunks", "POST"},
{"consumer", "/bzz/*", "GET"},
{"creator", "/bzz/*", "PATCH"},
{"creator", "/bzz", "POST"},
{"creator", "/bzz?*", "POST"},
{"consumer", "/bzz/*/*", "GET"},
{"consumer", "/bzz/*/*", "(GET)|(HEAD)"},
{"creator", "/tags", "GET"},
{"creator", "/tags?*", "GET"},
{"creator", "/tags", "POST"},
Expand Down

0 comments on commit 93ed7ed

Please sign in to comment.