[#221] add error response on key duplicates

Signed-off-by: Artem Tataurov <a.tataurov@yadro.com>
This commit is contained in:
Artem Tataurov 2022-11-17 18:01:38 +03:00 committed by Alex Vanin
parent 8f1d84ba8d
commit 278376643a
5 changed files with 81 additions and 9 deletions

View file

@ -26,7 +26,8 @@ func systemTranslator(key, prefix []byte) []byte {
return bytes.ToUpper(key)
}
func filterHeaders(l *zap.Logger, header *fasthttp.RequestHeader) map[string]string {
func filterHeaders(l *zap.Logger, header *fasthttp.RequestHeader) (map[string]string, error) {
var err error
result := make(map[string]string)
prefix := []byte(utils.UserAttributeHeaderPrefix)
@ -42,23 +43,30 @@ func filterHeaders(l *zap.Logger, header *fasthttp.RequestHeader) map[string]str
}
// removing attribute prefix
key = bytes.TrimPrefix(key, prefix)
clearKey := bytes.TrimPrefix(key, prefix)
// checks that it's a system NeoFS header
for _, system := range neofsAttributeHeaderPrefixes {
if bytes.HasPrefix(key, system) {
key = systemTranslator(key, system)
if bytes.HasPrefix(clearKey, system) {
clearKey = systemTranslator(clearKey, system)
break
}
}
// checks that the attribute key is not empty
if len(key) == 0 {
if len(clearKey) == 0 {
return
}
// check if key gets duplicated
// return error containing full key name (with prefix)
if _, ok := result[string(clearKey)]; ok {
err = fmt.Errorf("key duplication error: %s", string(key))
return
}
// make string representation of key / val
k, v := string(key), string(val)
k, v := string(clearKey), string(val)
result[k] = v
@ -67,7 +75,7 @@ func filterHeaders(l *zap.Logger, header *fasthttp.RequestHeader) map[string]str
zap.String("val", v))
})
return result
return result, err
}
func prepareExpirationHeader(headers map[string]string, epochDurations *epochDurations, now time.Time) error {

View file

@ -16,8 +16,27 @@ import (
func TestFilter(t *testing.T) {
log := zap.NewNop()
t.Run("duplicate keys error", func(t *testing.T) {
req := &fasthttp.RequestHeader{}
req.DisableNormalizing()
req.Add("X-Attribute-DupKey", "first-value")
req.Add("X-Attribute-DupKey", "second-value")
_, err := filterHeaders(log, req)
require.Error(t, err)
})
t.Run("duplicate system keys error", func(t *testing.T) {
req := &fasthttp.RequestHeader{}
req.DisableNormalizing()
req.Add("X-Attribute-Neofs-DupKey", "first-value")
req.Add("X-Attribute-Neofs-DupKey", "second-value")
_, err := filterHeaders(log, req)
require.Error(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")
@ -30,7 +49,8 @@ func TestFilter(t *testing.T) {
"__NEOFS__EXPIRATION_EPOCH2": "102",
}
result := filterHeaders(log, req)
result, err := filterHeaders(log, req)
require.NoError(t, err)
require.Equal(t, expected, result)
}

View file

@ -114,7 +114,12 @@ func (u *Uploader) Upload(c *fasthttp.RequestCtx) {
response.Error(c, "could not receive multipart/form: "+err.Error(), fasthttp.StatusBadRequest)
return
}
filtered := filterHeaders(u.log, &c.Request.Header)
filtered, err := filterHeaders(u.log, &c.Request.Header)
if err != nil {
log.Error("could not process headers", zap.Error(err))
response.Error(c, err.Error(), fasthttp.StatusBadRequest)
return
}
if needParseExpiration(filtered) {
epochDuration, err := getEpochDurations(c, u.pool)
if err != nil {