[#87] Allow canonical X-Attribute-Neofs-* headers
Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
parent
d2b0532929
commit
0597c0c143
3 changed files with 46 additions and 11 deletions
|
@ -357,7 +357,8 @@ You can also add some attributes to your file using the following rules:
|
||||||
"X-Attribute-" prefix stripped, that is if you add "X-Attribute-Ololo:
|
"X-Attribute-" prefix stripped, that is if you add "X-Attribute-Ololo:
|
||||||
100500" header to your request the resulting object will get "Ololo:
|
100500" header to your request the resulting object will get "Ololo:
|
||||||
100500" attribute
|
100500" attribute
|
||||||
* "X-Attribute-NEOFS-*" headers are special, they're used to set internal
|
* "X-Attribute-NEOFS-*" headers are special
|
||||||
|
(`-NEOFS-` part can also be `-neofs-` or`-Neofs-`), they're used to set internal
|
||||||
NeoFS attributes starting with `__NEOFS__` prefix, for these attributes all
|
NeoFS attributes starting with `__NEOFS__` prefix, for these attributes all
|
||||||
dashes get converted to underscores and all letters are capitalized. For
|
dashes get converted to underscores and all letters are capitalized. For
|
||||||
example, you can use "X-Attribute-NEOFS-Expiration-Epoch" header to set
|
example, you can use "X-Attribute-NEOFS-Expiration-Epoch" header to set
|
||||||
|
|
|
@ -9,14 +9,14 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
userAttributeHeaderPrefix = "X-Attribute-"
|
userAttributeHeaderPrefix = "X-Attribute-"
|
||||||
neofsAttributeHeaderPrefix = "NEOFS-"
|
|
||||||
|
|
||||||
systemAttributePrefix = "__NEOFS__"
|
systemAttributePrefix = "__NEOFS__"
|
||||||
)
|
)
|
||||||
|
|
||||||
func systemTranslator(key []byte) []byte {
|
var neofsAttributeHeaderPrefixes = [...][]byte{[]byte("Neofs-"), []byte("NEOFS-"), []byte("neofs-")}
|
||||||
// replace `NEOFS-` with `__NEOFS__`
|
|
||||||
key = bytes.Replace(key, []byte(neofsAttributeHeaderPrefix), []byte(systemAttributePrefix), 1)
|
func systemTranslator(key, prefix []byte) []byte {
|
||||||
|
// replace specified prefix with `__NEOFS__`
|
||||||
|
key = bytes.Replace(key, prefix, []byte(systemAttributePrefix), 1)
|
||||||
|
|
||||||
// replace `-` with `_`
|
// replace `-` with `_`
|
||||||
key = bytes.ReplaceAll(key, []byte("-"), []byte("_"))
|
key = bytes.ReplaceAll(key, []byte("-"), []byte("_"))
|
||||||
|
@ -28,7 +28,6 @@ func systemTranslator(key []byte) []byte {
|
||||||
func filterHeaders(l *zap.Logger, header *fasthttp.RequestHeader) map[string]string {
|
func filterHeaders(l *zap.Logger, header *fasthttp.RequestHeader) map[string]string {
|
||||||
result := make(map[string]string)
|
result := make(map[string]string)
|
||||||
prefix := []byte(userAttributeHeaderPrefix)
|
prefix := []byte(userAttributeHeaderPrefix)
|
||||||
system := []byte(neofsAttributeHeaderPrefix)
|
|
||||||
|
|
||||||
header.VisitAll(func(key, val []byte) {
|
header.VisitAll(func(key, val []byte) {
|
||||||
// checks that key and val not empty
|
// checks that key and val not empty
|
||||||
|
@ -45,8 +44,11 @@ func filterHeaders(l *zap.Logger, header *fasthttp.RequestHeader) map[string]str
|
||||||
key = bytes.TrimPrefix(key, prefix)
|
key = bytes.TrimPrefix(key, prefix)
|
||||||
|
|
||||||
// checks that it's a system NeoFS header
|
// checks that it's a system NeoFS header
|
||||||
|
for _, system := range neofsAttributeHeaderPrefixes {
|
||||||
if bytes.HasPrefix(key, system) {
|
if bytes.HasPrefix(key, system) {
|
||||||
key = systemTranslator(key)
|
key = systemTranslator(key, system)
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks that attribute key not empty
|
// checks that attribute key not empty
|
||||||
|
|
32
uploader/filter_test.go
Normal file
32
uploader/filter_test.go
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package uploader
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neofs-sdk-go/pkg/logger"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/valyala/fasthttp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestFilter(t *testing.T) {
|
||||||
|
log, err := logger.New()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
req := &fasthttp.RequestHeader{}
|
||||||
|
req.DisableNormalizing()
|
||||||
|
req.Set("X-Attribute-Neofs-Expiration-Epoch1", "101")
|
||||||
|
req.Set("X-Attribute-NEOFS-Expiration-Epoch2", "102")
|
||||||
|
req.Set("X-Attribute-neofs-Expiration-Epoch3", "103")
|
||||||
|
req.Set("X-Attribute-MyAttribute", "value")
|
||||||
|
|
||||||
|
expected := map[string]string{
|
||||||
|
"__NEOFS__EXPIRATION_EPOCH1": "101",
|
||||||
|
"MyAttribute": "value",
|
||||||
|
"__NEOFS__EXPIRATION_EPOCH3": "103",
|
||||||
|
"__NEOFS__EXPIRATION_EPOCH2": "102",
|
||||||
|
}
|
||||||
|
|
||||||
|
result := filterHeaders(log, req)
|
||||||
|
|
||||||
|
require.Equal(t, expected, result)
|
||||||
|
}
|
Loading…
Reference in a new issue