Add canonicalizer #121

Merged
alexvanin merged 1 commit from alexvanin/frostfs-http-gw:fix/canonicalizing into master 2024-06-27 13:10:58 +00:00

View file

@ -1,6 +1,7 @@
package main
import (
"bytes"
"context"
"errors"
"fmt"
@ -534,15 +535,15 @@ func (a *app) configureRouter(handler *handler.Handler) {
response.Error(r, "Method Not Allowed", fasthttp.StatusMethodNotAllowed)
}
r.POST("/upload/{cid}", a.logger(a.tokenizer(a.tracer(a.reqNamespace(handler.Upload)))))
r.POST("/upload/{cid}", a.logger(a.canonicalizer(a.tokenizer(a.tracer(a.reqNamespace(handler.Upload))))))
a.log.Info(logs.AddedPathUploadCid)
r.GET("/get/{cid}/{oid:*}", a.logger(a.tokenizer(a.tracer(a.reqNamespace(handler.DownloadByAddressOrBucketName)))))
r.HEAD("/get/{cid}/{oid:*}", a.logger(a.tokenizer(a.tracer(a.reqNamespace(handler.HeadByAddressOrBucketName)))))
r.GET("/get/{cid}/{oid:*}", a.logger(a.canonicalizer(a.tokenizer(a.tracer(a.reqNamespace(handler.DownloadByAddressOrBucketName))))))
r.HEAD("/get/{cid}/{oid:*}", a.logger(a.canonicalizer(a.tokenizer(a.tracer(a.reqNamespace(handler.HeadByAddressOrBucketName))))))
a.log.Info(logs.AddedPathGetCidOid)
r.GET("/get_by_attribute/{cid}/{attr_key}/{attr_val:*}", a.logger(a.tokenizer(a.tracer(a.reqNamespace(handler.DownloadByAttribute)))))
r.HEAD("/get_by_attribute/{cid}/{attr_key}/{attr_val:*}", a.logger(a.tokenizer(a.tracer(a.reqNamespace(handler.HeadByAttribute)))))
r.GET("/get_by_attribute/{cid}/{attr_key}/{attr_val:*}", a.logger(a.canonicalizer(a.tokenizer(a.tracer(a.reqNamespace(handler.DownloadByAttribute))))))
r.HEAD("/get_by_attribute/{cid}/{attr_key}/{attr_val:*}", a.logger(a.canonicalizer(a.tokenizer(a.tracer(a.reqNamespace(handler.HeadByAttribute))))))
a.log.Info(logs.AddedPathGetByAttributeCidAttrKeyAttrVal)
r.GET("/zip/{cid}/{prefix:*}", a.logger(a.tokenizer(a.tracer(a.reqNamespace(handler.DownloadZipped)))))
r.GET("/zip/{cid}/{prefix:*}", a.logger(a.canonicalizer(a.tokenizer(a.tracer(a.reqNamespace(handler.DownloadZipped))))))
a.log.Info(logs.AddedPathZipCidPrefix)
a.webServer.Handler = r.Handler
@ -559,6 +560,38 @@ func (a *app) logger(h fasthttp.RequestHandler) fasthttp.RequestHandler {
}
}
func (a *app) canonicalizer(h fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(req *fasthttp.RequestCtx) {
// regardless of DisableHeaderNamesNormalizing setting, some headers
// MUST be normalized in order to process execution. They are normalized
// here.
toAddKeys := make([][]byte, 0, 10)
toAddValues := make([][]byte, 0, 10)
prefix := []byte(utils.UserAttributeHeaderPrefix)
dkirillov marked this conversation as resolved
Review

I suppose we also must exclude system attributes

Lines 31 to 34 in 1737f1d
systemAttributePrefix = "__SYSTEM__"
// deprecated: use systemAttributePrefix
systemAttributePrefixNeoFS = "__NEOFS__"

I suppose we also must exclude `system` attributes https://git.frostfs.info/TrueCloudLab/frostfs-http-gw/src/commit/1737f1d95fdc918ef1d7c8a91075fa9f978c37f6/utils/attributes.go#L31-L34
Review

Those attributes are object attributes. They are used during X-Attribute-* header processing such as X-Attribute-System-Expiration-Epoch. It's all done here: https://git.frostfs.info/TrueCloudLab/frostfs-http-gw/src/branch/master/internal/handler/filter.go#L25-L32

Therefore HTTP headers with system object attributes are also excluded.

Those attributes are object attributes. They are used during `X-Attribute-*` header processing such as `X-Attribute-System-Expiration-Epoch`. It's all done here: https://git.frostfs.info/TrueCloudLab/frostfs-http-gw/src/branch/master/internal/handler/filter.go#L25-L32 Therefore HTTP headers with system object attributes are also excluded.
req.Request.Header.VisitAll(func(k, v []byte) {
if bytes.HasPrefix(k, prefix) {
return
}
toAddKeys = append(toAddKeys, k)
toAddValues = append(toAddValues, v)
})
// this is safe to do after all headers were read into header structure
req.Request.Header.EnableNormalizing()
for i := range toAddKeys {
req.Request.Header.SetBytesKV(toAddKeys[i], toAddValues[i])
}
// return normalization setting back
req.Request.Header.DisableNormalizing()
h(req)
}
}
func (a *app) tokenizer(h fasthttp.RequestHandler) fasthttp.RequestHandler {
return func(req *fasthttp.RequestCtx) {
appCtx, err := tokens.StoreBearerTokenAppCtx(a.ctx, req)