[OBJECT-8668] Add fuzzing tests for handlers
Some checks reported warnings
/ Builds (1.21) (pull_request) Has been cancelled
/ Builds (1.22) (pull_request) Has been cancelled
/ DCO (pull_request) Has been cancelled
/ Lint (pull_request) Has been cancelled
/ Tests (1.21) (pull_request) Has been cancelled
/ Tests (1.22) (pull_request) Has been cancelled
/ Vulncheck (pull_request) Has been cancelled
Some checks reported warnings
/ Builds (1.21) (pull_request) Has been cancelled
/ Builds (1.22) (pull_request) Has been cancelled
/ DCO (pull_request) Has been cancelled
/ Lint (pull_request) Has been cancelled
/ Tests (1.21) (pull_request) Has been cancelled
/ Tests (1.22) (pull_request) Has been cancelled
/ Vulncheck (pull_request) Has been cancelled
Signed-off-by: Roman Ognev <r.ognev@yadro.com>
This commit is contained in:
parent
5ee09790f0
commit
be79849ae8
6 changed files with 1419 additions and 39 deletions
42
Makefile
42
Makefile
|
@ -30,6 +30,15 @@ PKG_VERSION ?= $(shell echo $(VERSION) | sed "s/^v//" | \
|
|||
sed "s/-/~/")-${OS_RELEASE}
|
||||
.PHONY: debpackage debclean
|
||||
|
||||
FUZZING_DIR = $(shell pwd)/tests/fuzzing/files
|
||||
NGFUZZ_REPO = https://b.yadro.com/scm/sdl/ngfuzz.git
|
||||
NGFUZZ_BRANCH = feature/go-118-fuzz-build
|
||||
GO_118_FUZZ_BUILD_REPO = b.yadro.com/obj/go-118-fuzz-build
|
||||
|
||||
FUZZ_TIMEOUT ?= 30
|
||||
FUZZ_FUNCTIONS ?= "all"
|
||||
FUZZ_AUX ?= ""
|
||||
|
||||
# Make all binaries
|
||||
all: $(BINS)
|
||||
$(BINS): $(DIRS) dep
|
||||
|
@ -78,6 +87,36 @@ cover:
|
|||
@go test -v -race ./... -coverprofile=coverage.txt -covermode=atomic
|
||||
@go tool cover -html=coverage.txt -o coverage.html
|
||||
|
||||
CLANG := $(shell which clang-17 2>/dev/null)
|
||||
|
||||
# Run fuzzing tests
|
||||
.PHONY: check-clang all
|
||||
check-clang:
|
||||
ifeq ($(CLANG),)
|
||||
@echo "clang-17 is not installed. Please install it before proceeding - https://apt.llvm.org/llvm.sh "
|
||||
@exit 1
|
||||
endif
|
||||
|
||||
.PHONY: install-ngfuzz
|
||||
install-ngfuzz:
|
||||
ifeq (,$(wildcard $(FUZZING_DIR)/ngfuzz))
|
||||
@rm -rf $(FUZZING_DIR)/ngfuzz
|
||||
@git clone -b $(NGFUZZ_BRANCH) $(NGFUZZ_REPO) $(FUZZING_DIR)/ngfuzz
|
||||
@cd $(FUZZING_DIR)/ngfuzz && make
|
||||
endif
|
||||
|
||||
.PHONY: install-fuzzing-deps
|
||||
install-fuzzing-deps: check-clang install-ngfuzz
|
||||
ifeq (,$(wildcard $(FUZZING_DIR)/go-118-fuzz-build))
|
||||
GOBIN=$(FUZZING_DIR) go install $(GO_118_FUZZ_BUILD_REPO)
|
||||
endif
|
||||
|
||||
.PHONY: fuzz
|
||||
fuzz: install-fuzzing-deps
|
||||
cd $(FUZZING_DIR)/ngfuzz && \
|
||||
./ngfuzz -fuzz $(FUZZ_FUNCTIONS) -rootdir ../../../.. -timeout $(FUZZ_TIMEOUT) $(FUZZ_AUX) && \
|
||||
./ngfuzz -report
|
||||
|
||||
# Reformat code
|
||||
fmt:
|
||||
@echo "⇒ Processing gofmt check"
|
||||
|
@ -149,7 +188,8 @@ version:
|
|||
# Clean up
|
||||
clean:
|
||||
rm -rf vendor
|
||||
rm -rf $(BINDIR)
|
||||
rm -rf $(BINDIR)
|
||||
rm -rf $(FUZZING_DIR)
|
||||
|
||||
# Package for Debian
|
||||
debpackage:
|
||||
|
|
130
README.md
130
README.md
|
@ -6,6 +6,7 @@
|
|||
</p>
|
||||
|
||||
---
|
||||
|
||||
[![Report](https://goreportcard.com/badge/git.frostfs.info/TrueCloudLab/frostfs-http-gw)](https://goreportcard.com/report/git.frostfs.info/TrueCloudLab/frostfs-http-gw)
|
||||
![Release](https://img.shields.io/badge/dynamic/json.svg?label=release&url=https://git.frostfs.info/api/v1/repos/TrueCloudLab/frostfs-http-gw/releases&query=$[0].tag_name&color=orange)
|
||||
![License](https://img.shields.io/badge/license-GPL--3.0-orange.svg)
|
||||
|
@ -13,6 +14,7 @@
|
|||
# FrostFS HTTP Gateway
|
||||
|
||||
FrostFS HTTP Gateway bridges FrostFS internal protocol and HTTP standard.
|
||||
|
||||
- you can download one file per request from the FrostFS Network
|
||||
- you can upload one file per request into the FrostFS Network
|
||||
|
||||
|
@ -56,11 +58,14 @@ you can get the IP address of the node in the output of `make hosts` command
|
|||
|
||||
These two commands are functionally equivalent, they run the gate with one
|
||||
backend node (and otherwise default settings):
|
||||
|
||||
```
|
||||
$ frostfs-http-gw -p 192.168.130.72:8080
|
||||
$ HTTP_GW_PEERS_0_ADDRESS=192.168.130.72:8080 frostfs-http-gw
|
||||
```
|
||||
|
||||
It's also possible to specify uri scheme (grpc or grpcs) when using `-p`:
|
||||
|
||||
```
|
||||
$ frostfs-http-gw -p grpc://192.168.130.72:8080
|
||||
$ HTTP_GW_PEERS_0_ADDRESS=grpcs://192.168.130.72:8080 frostfs-http-gw
|
||||
|
@ -80,6 +85,7 @@ gateway spread requests equally among them (using weight 1 and priority 1 for ev
|
|||
```
|
||||
$ frostfs-http-gw -p 192.168.130.72:8080 -p 192.168.130.71:8080
|
||||
```
|
||||
|
||||
If you want some specific load distribution proportions, use weights and priorities:
|
||||
|
||||
```
|
||||
|
@ -88,17 +94,22 @@ $ HTTP_GW_PEERS_0_ADDRESS=192.168.130.71:8080 HTTP_GW_PEERS_0_WEIGHT=1 HTTP_GW_P
|
|||
HTTP_GW_PEERS_2_ADDRESS=192.168.130.73:8080 HTTP_GW_PEERS_2_WEIGHT=1 HTTP_GW_PEERS_2_PRIORITY=2 \
|
||||
frostfs-http-gw
|
||||
```
|
||||
|
||||
This command will make gateway use 192.168.130.71 while it is healthy. Otherwise, it will make the gateway use
|
||||
192.168.130.72 for 90% of requests and 192.168.130.73 for remaining 10%.
|
||||
|
||||
### Keys
|
||||
|
||||
You can provide a wallet via `--wallet` or `-w` flag. You can also specify the account address using `--address`
|
||||
(if no address provided default one will be used). If wallet is used, you need to set `HTTP_GW_WALLET_PASSPHRASE` variable to decrypt the wallet.
|
||||
If no wallet provided, the gateway autogenerates a key pair it will use for FrostFS requests.
|
||||
|
||||
```
|
||||
$ frostfs-http-gw -p $FROSTFS_NODE -w $WALLET_PATH --address $ACCOUNT_ADDRESS
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
$ frostfs-http-gw -p 192.168.130.72:8080 -w wallet.json --address NfgHwwTi3wHAS8aFAN243C5vGbkYDpqLHP
|
||||
```
|
||||
|
@ -164,18 +175,23 @@ All timing options accept values with suffixes, so "15s" is 15 seconds and
|
|||
"2m" is 2 minutes.
|
||||
|
||||
### Zip streaming
|
||||
|
||||
The gateway supports downloading files by common prefix (like dir) in zip format. You can enable compression
|
||||
using config or `HTTP_GW_ZIP_COMPRESSION=true` environment variable.
|
||||
|
||||
### Logging
|
||||
|
||||
You can specify logging level using variable:
|
||||
|
||||
```
|
||||
HTTP_GW_LOGGER_LEVEL=debug
|
||||
```
|
||||
|
||||
### Yaml file
|
||||
|
||||
Configuration file is optional and can be used instead of environment variables/other parameters.
|
||||
It can be specified with `--config` parameter:
|
||||
|
||||
```
|
||||
$ frostfs-http-gw --config your-config.yaml
|
||||
```
|
||||
|
@ -229,7 +245,7 @@ resolve_order:
|
|||
```
|
||||
|
||||
2. Make sure your container is registered in NNS contract. If you use [frostfs-dev-env](https://git.frostfs.info/TrueCloudLab/frostfs-dev-env)
|
||||
you can check if your container (e.g. with `container-name` name) is registered in NNS:
|
||||
you can check if your container (e.g. with `container-name` name) is registered in NNS:
|
||||
|
||||
```shell
|
||||
$ curl -s --data '{"id":1,"jsonrpc":"2.0","method":"getcontractstate","params":[1]}' \
|
||||
|
@ -256,14 +272,17 @@ $ curl http://localhost:8082/get_by_attribute/container-name/FileName/object-nam
|
|||
#### Create a container
|
||||
|
||||
You can create a container via [frostfs-cli](https://git.frostfs.info/TrueCloudLab/frostfs-node/releases):
|
||||
|
||||
```
|
||||
$ frostfs-cli -r $FROSTFS_NODE -w $WALLET container create --policy $POLICY --basic-acl $ACL
|
||||
```
|
||||
where `$WALLET` is a path to user wallet,
|
||||
`$ACL` -- hex encoded basic ACL value or keywords 'private, 'public-read', 'public-read-write' and
|
||||
|
||||
where `$WALLET` is a path to user wallet,
|
||||
`$ACL` -- hex encoded basic ACL value or keywords 'private, 'public-read', 'public-read-write' and
|
||||
`$POLICY` -- QL-encoded or JSON-encoded placement policy or path to file with it
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
$ frostfs-cli -r 192.168.130.72:8080 -w ./wallet.json container create --policy "REP 3" --basic-acl public --await
|
||||
```
|
||||
|
@ -275,19 +294,21 @@ the file `wallets/wallet.key`.
|
|||
#### Prepare a file in a container
|
||||
|
||||
To create a file via [frostfs-cli](https://git.frostfs.info/TrueCloudLab/frostfs-node/releases), run a command below:
|
||||
|
||||
```
|
||||
$ frostfs-cli -r $FROSTFS_NODE -k $KEY object put --file $FILENAME --cid $CID
|
||||
```
|
||||
|
||||
where
|
||||
`$KEY` -- the key, please read the information [above](#create-a-container),
|
||||
`$CID` -- container ID.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
$ frostfs-cli -r 192.168.130.72:8080 -w ./wallet.json object put --file cat.png --cid Dxhf4PNprrJHWWTG5RGLdfLkJiSQ3AQqit1MSnEPRkDZ --attributes img_type=cat,my_attr=cute
|
||||
```
|
||||
|
||||
|
||||
### Downloading
|
||||
|
||||
#### Requests
|
||||
|
@ -313,6 +334,7 @@ $ wget http://localhost:8082/get/container-name/2m8PtaoricLouCn5zE8hAFr3gZEBDCZF
|
|||
```
|
||||
|
||||
##### By attributes
|
||||
|
||||
There is also more complex interface provided for attribute-based downloads,
|
||||
it's usually used to retrieve files by their names, but any other attribute
|
||||
can be used as well. The generic syntax for it looks like this:
|
||||
|
@ -326,7 +348,7 @@ where
|
|||
|
||||
**NB!** The attribute key and value should be url encoded, i.e., if you want to download an object with the attribute value
|
||||
`a cat`, the value in the request must be `a+cat`. In the same way with the attribute key. If you don't escape such values
|
||||
everything can still work (for example you can use `d@ta` without encoding) but it's HIGHLY RECOMMENDED to encode all your attributes.
|
||||
everything can still work (for example you can use `d@ta` without encoding) but it's HIGHLY RECOMMENDED to encode all your attributes.
|
||||
|
||||
If multiple objects have specified attribute with specified value, then the
|
||||
first one of them is returned (and you can't get others via this interface).
|
||||
|
@ -336,7 +358,9 @@ Example for file name attribute:
|
|||
```
|
||||
$ wget http://localhost:8082/get_by_attribute/88GdaZFTcYJn1dqiSECss8kKPmmun6d6BfvC4zhwfLYM/FileName/cat.jpeg
|
||||
```
|
||||
|
||||
Or when the filename includes special symbols:
|
||||
|
||||
```
|
||||
$ wget http://localhost:8082/get_by_attribute/88GdaZFTcYJn1dqiSECss8kKPmmun6d6BfvC4zhwfLYM/FileName/cat+jpeg # means 'cat jpeg'
|
||||
$ wget http://localhost:8082/get_by_attribute/88GdaZFTcYJn1dqiSECss8kKPmmun6d6BfvC4zhwfLYM/FileName/cat%25jpeg # means 'cat%jpeg'
|
||||
|
@ -349,6 +373,7 @@ $ wget http://localhost:8082/get_by_attribute/Dxhf4PNprrJHWWTG5RGLdfLkJiSQ3AQqit
|
|||
```
|
||||
|
||||
Or when the attribute includes special symbols:
|
||||
|
||||
```
|
||||
$ wget http://localhost:8082/get_by_attribute/Dxhf4PNprrJHWWTG5RGLdfLkJiSQ3AQqit1MSnEPRkDZ/Olo%2Blo/100500 # means Olo+lo
|
||||
```
|
||||
|
@ -362,7 +387,9 @@ $ wget http://localhost:8082/get/Dxhf4PNprrJHWWTG5RGLdfLkJiSQ3AQqit1MSnEPRkDZ/2m
|
|||
```
|
||||
|
||||
##### Zip
|
||||
|
||||
You can download some dir (files with the same prefix) in zip (it will be compressed if config contains appropriate param):
|
||||
|
||||
```
|
||||
$ wget http://localhost:8082/zip/Dxhf4PNprrJHWWTG5RGLdfLkJiSQ3AQqit1MSnEPRkDZ/common/prefix
|
||||
```
|
||||
|
@ -374,24 +401,24 @@ otherwise they will not be in the zip archive. You can upload file with this att
|
|||
$ curl -F 'file=@cat.jpeg;filename=cat.jpeg' -H 'X-Attribute-FilePath: common/prefix/cat.jpeg' http://localhost:8082/upload/Dxhf4PNprrJHWWTG5RGLdfLkJiSQ3AQqit1MSnEPRkDZ
|
||||
```
|
||||
|
||||
|
||||
#### Replies
|
||||
|
||||
You get object contents in the reply body (if GET method was used), but at the same time you also get a
|
||||
set of reply headers generated using the following rules:
|
||||
* `Content-Length` is set to the length of the object
|
||||
* `Content-Type` is autodetected dynamically by gateway
|
||||
* `Content-Disposition` is `inline` for regular requests and `attachment` for
|
||||
requests with `download=true` argument, `filename` is also added if there
|
||||
is `FileName` attribute set for this object
|
||||
* `Last-Modified` header is set to `Timestamp` attribute value if it's
|
||||
present for the object
|
||||
* `x-container-id` contains container ID
|
||||
* `x-object-id` contains object ID
|
||||
* `x-owner-id` contains owner address
|
||||
* all the other FrostFS attributes are converted to `X-Attribute-*` headers (but only
|
||||
if they can be safely represented in HTTP header), for example `FileName`
|
||||
attribute becomes `X-Attribute-FileName` header
|
||||
|
||||
* `Content-Length` is set to the length of the object
|
||||
* `Content-Type` is autodetected dynamically by gateway
|
||||
* `Content-Disposition` is `inline` for regular requests and `attachment` for
|
||||
requests with `download=true` argument, `filename` is also added if there
|
||||
is `FileName` attribute set for this object
|
||||
* `Last-Modified` header is set to `Timestamp` attribute value if it's
|
||||
present for the object
|
||||
* `x-container-id` contains container ID
|
||||
* `x-object-id` contains object ID
|
||||
* `x-owner-id` contains owner address
|
||||
* all the other FrostFS attributes are converted to `X-Attribute-*` headers (but only
|
||||
if they can be safely represented in HTTP header), for example `FileName`
|
||||
attribute becomes `X-Attribute-FileName` header
|
||||
|
||||
##### Caching strategy
|
||||
|
||||
|
@ -422,26 +449,29 @@ $ curl --no-buffer -F 'file=@pipe;filename=catvideo.mp4' http://localhost:8082/u
|
|||
```
|
||||
|
||||
You can also add some attributes to your file using the following rules:
|
||||
* all "X-Attribute-*" headers get converted to object attributes with
|
||||
"X-Attribute-" prefix stripped, that is if you add "X-Attribute-Ololo:
|
||||
100500" header to your request the resulting object will get "Ololo:
|
||||
100500" attribute
|
||||
* "X-Attribute-SYSTEM-*" headers are special
|
||||
(`-SYSTEM-` part can also be `-system-` or`-System-` (and even legacy `-Neofs-` for some next releases)), they're used to set internal
|
||||
FrostFS attributes starting with `__SYSTEM__` prefix, for these attributes all
|
||||
dashes get converted to underscores and all letters are capitalized. For
|
||||
example, you can use "X-Attribute-SYSTEM-Expiration-Epoch" header to set
|
||||
`__SYSTEM__EXPIRATION_EPOCH` attribute
|
||||
* `FileName` attribute is set from multipart's `filename` if not set
|
||||
explicitly via `X-Attribute-FileName` header
|
||||
* `Timestamp` attribute can be set using gateway local time if using
|
||||
HTTP_GW_UPLOAD_HEADER_USE_DEFAULT_TIMESTAMP option and if request doesn't
|
||||
provide `X-Attribute-Timestamp` header of its own
|
||||
|
||||
* all "X-Attribute-*" headers get converted to object attributes with
|
||||
"X-Attribute-" prefix stripped, that is if you add "X-Attribute-Ololo:
|
||||
100500" header to your request the resulting object will get "Ololo:
|
||||
100500" attribute
|
||||
* "X-Attribute-SYSTEM-*" headers are special
|
||||
(`-SYSTEM-` part can also be `-system-` or`-System-` (and even legacy `-Neofs-` for some next releases)), they're used to set internal
|
||||
FrostFS attributes starting with `__SYSTEM__` prefix, for these attributes all
|
||||
dashes get converted to underscores and all letters are capitalized. For
|
||||
example, you can use "X-Attribute-SYSTEM-Expiration-Epoch" header to set
|
||||
`__SYSTEM__EXPIRATION_EPOCH` attribute
|
||||
* `FileName` attribute is set from multipart's `filename` if not set
|
||||
explicitly via `X-Attribute-FileName` header
|
||||
* `Timestamp` attribute can be set using gateway local time if using
|
||||
HTTP_GW_UPLOAD_HEADER_USE_DEFAULT_TIMESTAMP option and if request doesn't
|
||||
provide `X-Attribute-Timestamp` header of its own
|
||||
|
||||
---
|
||||
|
||||
**NOTE**
|
||||
|
||||
There are some reserved headers type of `X-Attribute-SYSTEM-*` (headers are arranged in descending order of priority):
|
||||
|
||||
1. `X-Attribute-System-Expiration-Epoch: 100`
|
||||
2. `X-Attribute-System-Expiration-Duration: 24h30m`
|
||||
3. `X-Attribute-System-Expiration-Timestamp: 1637574797`
|
||||
|
@ -453,6 +483,7 @@ which transforms to `X-Attribute-System-Expiration-Epoch`. So you can provide ex
|
|||
|
||||
For successful uploads you get JSON data in reply body with a container and
|
||||
object ID, like this:
|
||||
|
||||
```
|
||||
{
|
||||
"object_id": "9ANhbry2ryjJY1NZbcjryJMRXG5uGNKd73kD3V1sVFsX",
|
||||
|
@ -474,9 +505,10 @@ to grant access.
|
|||
|
||||
FrostFS Bearer Token basically is a container owner-signed policy (refer to FrostFS
|
||||
documentation for more details). There are two options to pass them to gateway:
|
||||
* "Authorization" header with "Bearer" type and base64-encoded token in
|
||||
credentials field
|
||||
* "Bearer" cookie with base64-encoded token contents
|
||||
|
||||
* "Authorization" header with "Bearer" type and base64-encoded token in
|
||||
credentials field
|
||||
* "Bearer" cookie with base64-encoded token contents
|
||||
|
||||
For example, you have a mobile application frontend with a backend part storing
|
||||
data in FrostFS. When a user authorizes in the mobile app, the backend issues a FrostFS
|
||||
|
@ -486,6 +518,7 @@ the corresponding header to the upload request. Accessing policy protected data
|
|||
works the same way.
|
||||
|
||||
##### Example
|
||||
|
||||
In order to generate a bearer token, you need to have wallet (which will be used to sign the token)
|
||||
|
||||
1. Suppose you have a container with private policy for wallet key
|
||||
|
@ -500,9 +533,9 @@ $ frostfs-cli ape-manager add -r <endpoint> --wallet <wallet> \
|
|||
--chain-id <chainID>
|
||||
```
|
||||
|
||||
|
||||
2. Form a Bearer token (10000 is lifetime expiration in epoch) to impersonate
|
||||
HTTP Gateway request as wallet signed request and save it to **bearer.json**:
|
||||
|
||||
```
|
||||
{
|
||||
"body": {
|
||||
|
@ -518,11 +551,13 @@ $ frostfs-cli ape-manager add -r <endpoint> --wallet <wallet> \
|
|||
```
|
||||
|
||||
3. Sign it with the wallet:
|
||||
|
||||
```
|
||||
$ frostfs-cli util sign bearer-token --from bearer.json --to signed.json -w <wallet>
|
||||
```
|
||||
|
||||
4. Encode to base64 to use in header:
|
||||
|
||||
```
|
||||
$ base64 -w 0 signed.json
|
||||
# output: Ck4KKgoECAIQBhIiCiCZGdlbN7DPGPMg9rsWqV+p2XdMzUqknRiexewSFp8kmBIbChk17MUri6OJ0X5ftsHzy7NERDNFB4C92PcaGgMIkE4SZgohAxpsb7vfAso1F0X6hrm6WpRS14WsT3/Ct1SMoqRsT89KEkEEGxKi8GjKSf52YqhppgaOTQHbUsL3jn7SHLqS3ndAQ7NtAATnmRHleZw2V2xRRSRBQdjDC05KK83LhdSax72Fsw==
|
||||
|
@ -551,6 +586,7 @@ $ echo 'NhVtreTTCoqsMQV5Wp55fqnriiUCpEaKm3' | base58 --decode | base64
|
|||
```
|
||||
|
||||
Then specify this value in Bearer Token Json
|
||||
|
||||
```
|
||||
{
|
||||
"body": {
|
||||
|
@ -572,6 +608,24 @@ If enabled, Prometheus metrics are available at `localhost:8084` endpoint
|
|||
and Pprof at `localhost:8083/debug/pprof` by default. Host and port can be configured.
|
||||
See [configuration](./docs/gate-configuration.md).
|
||||
|
||||
## Fuzzing
|
||||
|
||||
To run fuzzing tests use the following command:
|
||||
|
||||
```shell
|
||||
$ make fuzz
|
||||
```
|
||||
|
||||
This command will install dependencies for the fuzzing process and run existing fuzzing tests.
|
||||
|
||||
You can also use the following arguments:
|
||||
|
||||
```
|
||||
FUZZ_TIMEOUT - time to run each fuzzing test (default 30)
|
||||
FUZZ_FUNCTIONS - fuzzing tests that will be started (default "all")
|
||||
FUZZ_AUX - additional parameters for the fuzzer (for example, "-debug")
|
||||
````
|
||||
|
||||
## Credits
|
||||
|
||||
Please see [CREDITS](CREDITS.md) for details.
|
||||
|
|
1
go.mod
1
go.mod
|
@ -17,6 +17,7 @@ require (
|
|||
github.com/ssgreg/journald v1.0.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
github.com/testcontainers/testcontainers-go v0.13.0
|
||||
github.com/trailofbits/go-fuzz-utils v0.0.0-20230413173806-58c38daa3cb4
|
||||
github.com/valyala/fasthttp v1.34.0
|
||||
go.opentelemetry.io/otel v1.16.0
|
||||
go.opentelemetry.io/otel/trace v1.16.0
|
||||
|
|
2
go.sum
2
go.sum
|
@ -820,6 +820,8 @@ github.com/testcontainers/testcontainers-go v0.13.0 h1:OUujSlEGsXVo/ykPVZk3KanBN
|
|||
github.com/testcontainers/testcontainers-go v0.13.0/go.mod h1:z1abufU633Eb/FmSBTzV6ntZAC1eZBYPtaFsn4nPuDk=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/trailofbits/go-fuzz-utils v0.0.0-20230413173806-58c38daa3cb4 h1:GpfJ7OdNjS7BFTVwNCUI9L4aCJOFRbr5fdHqjdhoYE8=
|
||||
github.com/trailofbits/go-fuzz-utils v0.0.0-20230413173806-58c38daa3cb4/go.mod h1:f3jBhpWvuZmue0HZK52GzRHJOYHYSILs/c8+K2S/J+o=
|
||||
github.com/twmb/murmur3 v1.1.8 h1:8Yt9taO/WN3l08xErzjeschgZU2QSrwm1kclYq+0aRg=
|
||||
github.com/twmb/murmur3 v1.1.8/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
|
|
574
internal/handler/handler_fuzz_test.go
Normal file
574
internal/handler/handler_fuzz_test.go
Normal file
|
@ -0,0 +1,574 @@
|
|||
//go:build gofuzz
|
||||
// +build gofuzz
|
||||
|
||||
package handler
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
syserrors "errors"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/handler/middleware"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/tokens"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/utils"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
|
||||
cid "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
go_fuzz_utils "github.com/trailofbits/go-fuzz-utils"
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
var (
|
||||
fuzzSuccessExitCode = 0
|
||||
fuzzFailExitCode = 1
|
||||
)
|
||||
|
||||
func prepareStrings(tp *go_fuzz_utils.TypeProvider, count int) ([]string, error) {
|
||||
array := make([]string, count)
|
||||
var err error
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
err = tp.Reset()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
array[i], err = tp.GetString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return array, nil
|
||||
}
|
||||
|
||||
func prepareBools(tp *go_fuzz_utils.TypeProvider, count int) ([]bool, error) {
|
||||
array := make([]bool, count)
|
||||
var err error
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
err = tp.Reset()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
array[i], err = tp.GetBool()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return array, nil
|
||||
}
|
||||
|
||||
func getRandomDeterministicPositiveIntInRange(tp *go_fuzz_utils.TypeProvider, max int) (int, error) {
|
||||
count, err := tp.GetInt()
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
count = count % max
|
||||
if count < 0 {
|
||||
count += max
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func generateHeaders(tp *go_fuzz_utils.TypeProvider, r *fasthttp.Request, params []string) error {
|
||||
count, err := tp.GetInt()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
count = count % len(params)
|
||||
if count < 0 {
|
||||
count += len(params)
|
||||
}
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
position, err := tp.GetInt()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
position = position % len(params)
|
||||
if position < 0 {
|
||||
position += len(params)
|
||||
}
|
||||
|
||||
v, err := tp.GetString()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.Header.Set(params[position], v)
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func maybeFillRandom(tp *go_fuzz_utils.TypeProvider, initValue string) (error, string) {
|
||||
rnd, err := tp.GetBool()
|
||||
if err != nil {
|
||||
return err, ""
|
||||
}
|
||||
if rnd == true {
|
||||
initValue, err = tp.GetString()
|
||||
if err != nil {
|
||||
return err, ""
|
||||
}
|
||||
}
|
||||
return nil, initValue
|
||||
}
|
||||
|
||||
func upload(tp *go_fuzz_utils.TypeProvider) (error, context.Context, *handlerContext, cid.ID, *fasthttp.RequestCtx, string, string, string) {
|
||||
hc, err := prepareHandlerContext()
|
||||
if err != nil {
|
||||
return err, nil, nil, cid.ID{}, nil, "", "", ""
|
||||
}
|
||||
|
||||
aclList := []acl.Basic{
|
||||
acl.Private,
|
||||
acl.PrivateExtended,
|
||||
acl.PublicRO,
|
||||
acl.PublicROExtended,
|
||||
acl.PublicRW,
|
||||
acl.PublicRWExtended,
|
||||
acl.PublicAppend,
|
||||
acl.PublicAppendExtended,
|
||||
}
|
||||
|
||||
pos, err := getRandomDeterministicPositiveIntInRange(tp, len(aclList))
|
||||
if err != nil {
|
||||
return err, nil, nil, cid.ID{}, nil, "", "", ""
|
||||
}
|
||||
acl := aclList[pos]
|
||||
|
||||
strings, err := prepareStrings(tp, 6)
|
||||
if err != nil {
|
||||
return err, nil, nil, cid.ID{}, nil, "", "", ""
|
||||
}
|
||||
bktName := strings[0]
|
||||
objFileName := strings[1]
|
||||
valAttr := strings[2]
|
||||
keyAttr := strings[3]
|
||||
|
||||
if len(bktName) == 0 {
|
||||
return syserrors.New("not enought buckets"), nil, nil, cid.ID{}, nil, "", "", ""
|
||||
}
|
||||
|
||||
cnrID, cnr, err := hc.prepareContainer(bktName, acl)
|
||||
if err != nil {
|
||||
return err, nil, nil, cid.ID{}, nil, "", "", ""
|
||||
}
|
||||
|
||||
hc.frostfs.SetContainer(cnrID, cnr)
|
||||
|
||||
ctx := context.Background()
|
||||
ctx = middleware.SetNamespace(ctx, "")
|
||||
|
||||
r := new(fasthttp.RequestCtx)
|
||||
utils.SetContextToRequest(ctx, r)
|
||||
r.SetUserValue("cid", cnrID.EncodeToString())
|
||||
|
||||
attributes := map[string]string{
|
||||
object.AttributeFileName: objFileName,
|
||||
keyAttr: valAttr,
|
||||
}
|
||||
|
||||
var buff bytes.Buffer
|
||||
w := multipart.NewWriter(&buff)
|
||||
fw, err := w.CreateFormFile("file", attributes[object.AttributeFileName])
|
||||
if err != nil {
|
||||
return err, nil, nil, cid.ID{}, nil, "", "", ""
|
||||
}
|
||||
|
||||
content, err := tp.GetBytes()
|
||||
if err != nil {
|
||||
return err, nil, nil, cid.ID{}, nil, "", "", ""
|
||||
}
|
||||
|
||||
if _, err = io.Copy(fw, bytes.NewReader(content)); err != nil {
|
||||
return err, nil, nil, cid.ID{}, nil, "", "", ""
|
||||
}
|
||||
|
||||
if err = w.Close(); err != nil {
|
||||
return err, nil, nil, cid.ID{}, nil, "", "", ""
|
||||
}
|
||||
|
||||
r.Request.SetBodyStream(&buff, buff.Len())
|
||||
r.Request.Header.Set("Content-Type", w.FormDataContentType())
|
||||
r.Request.Header.Set("X-Attribute-"+keyAttr, valAttr)
|
||||
|
||||
err = generateHeaders(tp, &r.Request, []string{"X-Attribute-", "X-Attribute-DupKey", "X-Attribute-MyAttribute", "X-Attribute-System-DupKey", "X-Attribute-System-Expiration-Epoch1", "X-Attribute-SYSTEM-Expiration-Epoch2", "X-Attribute-system-Expiration-Epoch3", "X-Attribute-User-Attribute", "X-Attribute-", "X-Attribute-FileName", "X-Attribute-FROSTFS", "X-Attribute-neofs", "X-Attribute-SYSTEM", "X-Attribute-System-Expiration-Duration", "X-Attribute-System-Expiration-Epoch", "X-Attribute-System-Expiration-RFC3339", "X-Attribute-System-Expiration-Timestamp", "X-Attribute-Timestamp", "X-Attribute-" + strings[4], "X-Attribute-System-" + strings[5]})
|
||||
if err != nil {
|
||||
return err, nil, nil, cid.ID{}, nil, "", "", ""
|
||||
}
|
||||
|
||||
hc.Handler().Upload(r)
|
||||
|
||||
if r.Response.StatusCode() != http.StatusOK {
|
||||
return syserrors.New("error on upload"), nil, nil, cid.ID{}, nil, "", "", ""
|
||||
}
|
||||
|
||||
return nil, ctx, hc, cnrID, r, objFileName, keyAttr, valAttr
|
||||
}
|
||||
|
||||
func InitFuzzUpload() {
|
||||
|
||||
}
|
||||
|
||||
func DoFuzzUpload(input []byte) int {
|
||||
// FUZZER INIT
|
||||
if len(input) < 100 {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
tp, err := go_fuzz_utils.NewTypeProvider(input)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
err, _, _, _, _, _, _, _ = upload(tp)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
return fuzzSuccessExitCode
|
||||
}
|
||||
|
||||
func FuzzUpload(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
DoFuzzUpload(data)
|
||||
})
|
||||
}
|
||||
|
||||
func downloadOrHead(tp *go_fuzz_utils.TypeProvider, ctx context.Context, hc *handlerContext, cnrID cid.ID, resp *fasthttp.RequestCtx, filename string) (error, *fasthttp.RequestCtx) {
|
||||
|
||||
var putRes putResponse
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
panic(resp)
|
||||
}
|
||||
}()
|
||||
|
||||
data := resp.Response.Body()
|
||||
err := json.Unmarshal(data, &putRes)
|
||||
|
||||
if err != nil {
|
||||
return err, nil
|
||||
}
|
||||
|
||||
obj := hc.frostfs.objects[putRes.ContainerID+"/"+putRes.ObjectID]
|
||||
attr := object.NewAttribute()
|
||||
attr.SetKey(object.AttributeFilePath)
|
||||
|
||||
err, filename = maybeFillRandom(tp, filename)
|
||||
if err != nil {
|
||||
return err, nil
|
||||
}
|
||||
|
||||
attr.SetValue(filename)
|
||||
obj.SetAttributes(append(obj.Attributes(), *attr)...)
|
||||
|
||||
r := new(fasthttp.RequestCtx)
|
||||
utils.SetContextToRequest(ctx, r)
|
||||
|
||||
cid := cnrID.EncodeToString()
|
||||
err, cid = maybeFillRandom(tp, cid)
|
||||
if err != nil {
|
||||
return err, nil
|
||||
}
|
||||
oid := putRes.ObjectID
|
||||
err, oid = maybeFillRandom(tp, oid)
|
||||
if err != nil {
|
||||
return err, nil
|
||||
}
|
||||
r.SetUserValue("cid", cid)
|
||||
r.SetUserValue("oid", oid)
|
||||
|
||||
rnd, err := tp.GetBool()
|
||||
if err != nil {
|
||||
return err, nil
|
||||
}
|
||||
if rnd == true {
|
||||
r.SetUserValue("download", "true")
|
||||
}
|
||||
|
||||
return nil, r
|
||||
}
|
||||
|
||||
func InitFuzzGet() {
|
||||
}
|
||||
|
||||
func DoFuzzGet(input []byte) int {
|
||||
// FUZZER INIT
|
||||
if len(input) < 100 {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
tp, err := go_fuzz_utils.NewTypeProvider(input)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
err, ctx, hc, cnrID, resp, filename, _, _ := upload(tp)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
err, r := downloadOrHead(tp, ctx, hc, cnrID, resp, filename)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
hc.Handler().DownloadByAddressOrBucketName(r)
|
||||
|
||||
return fuzzSuccessExitCode
|
||||
}
|
||||
|
||||
func FuzzGet(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
DoFuzzUpload(data)
|
||||
})
|
||||
}
|
||||
|
||||
func InitFuzzHead() {
|
||||
}
|
||||
|
||||
func DoFuzzHead(input []byte) int {
|
||||
// FUZZER INIT
|
||||
if len(input) < 100 {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
tp, err := go_fuzz_utils.NewTypeProvider(input)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
err, ctx, hc, cnrID, resp, filename, _, _ := upload(tp)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
err, r := downloadOrHead(tp, ctx, hc, cnrID, resp, filename)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
hc.Handler().HeadByAddressOrBucketName(r)
|
||||
|
||||
return fuzzSuccessExitCode
|
||||
}
|
||||
|
||||
func FuzzHead(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
DoFuzzHead(data)
|
||||
})
|
||||
}
|
||||
|
||||
func InitFuzzDownloadByAttribute() {
|
||||
}
|
||||
|
||||
func DoFuzzDownloadByAttribute(input []byte) int {
|
||||
// FUZZER INIT
|
||||
if len(input) < 100 {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
tp, err := go_fuzz_utils.NewTypeProvider(input)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
err, ctx, hc, cnrID, _, _, attrKey, attrVal := upload(tp)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
cid := cnrID.EncodeToString()
|
||||
err, cid = maybeFillRandom(tp, cid)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
err, attrKey = maybeFillRandom(tp, attrKey)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
err, attrVal = maybeFillRandom(tp, attrVal)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
r := new(fasthttp.RequestCtx)
|
||||
utils.SetContextToRequest(ctx, r)
|
||||
r.SetUserValue("cid", cid)
|
||||
r.SetUserValue("attr_key", attrKey)
|
||||
r.SetUserValue("attr_val", attrVal)
|
||||
|
||||
hc.Handler().DownloadByAttribute(r)
|
||||
|
||||
return fuzzSuccessExitCode
|
||||
}
|
||||
|
||||
func FuzzDownloadByAttribute(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
DoFuzzDownloadByAttribute(data)
|
||||
})
|
||||
}
|
||||
|
||||
func InitFuzzHeadByAttribute() {
|
||||
}
|
||||
|
||||
func DoFuzzHeadByAttribute(input []byte) int {
|
||||
// FUZZER INIT
|
||||
if len(input) < 100 {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
tp, err := go_fuzz_utils.NewTypeProvider(input)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
err, ctx, hc, cnrID, _, _, attrKey, attrVal := upload(tp)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
cid := cnrID.EncodeToString()
|
||||
err, cid = maybeFillRandom(tp, cid)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
err, attrKey = maybeFillRandom(tp, attrKey)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
err, attrVal = maybeFillRandom(tp, attrVal)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
r := new(fasthttp.RequestCtx)
|
||||
utils.SetContextToRequest(ctx, r)
|
||||
r.SetUserValue("cid", cid)
|
||||
r.SetUserValue("attr_key", attrKey)
|
||||
r.SetUserValue("attr_val", attrVal)
|
||||
|
||||
hc.Handler().HeadByAttribute(r)
|
||||
|
||||
return fuzzSuccessExitCode
|
||||
}
|
||||
|
||||
func FuzzHeadByAttribute(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
DoFuzzHeadByAttribute(data)
|
||||
})
|
||||
}
|
||||
|
||||
func InitFuzzDownloadZipped() {
|
||||
}
|
||||
|
||||
func DoFuzzDownloadZipped(input []byte) int {
|
||||
// FUZZER INIT
|
||||
if len(input) < 100 {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
tp, err := go_fuzz_utils.NewTypeProvider(input)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
err, ctx, hc, cnrID, _, _, _, _ := upload(tp)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
cid := cnrID.EncodeToString()
|
||||
err, cid = maybeFillRandom(tp, cid)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
prefix := ""
|
||||
err, prefix = maybeFillRandom(tp, prefix)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
r := new(fasthttp.RequestCtx)
|
||||
utils.SetContextToRequest(ctx, r)
|
||||
r.SetUserValue("cid", cid)
|
||||
r.SetUserValue("prefix", prefix)
|
||||
|
||||
hc.Handler().DownloadZipped(r)
|
||||
|
||||
return fuzzSuccessExitCode
|
||||
}
|
||||
|
||||
func FuzzDownloadZipped(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
DoFuzzDownloadZipped(data)
|
||||
})
|
||||
}
|
||||
|
||||
func InitFuzzStoreBearerTokenAppCtx() {
|
||||
}
|
||||
|
||||
func DoFuzzStoreBearerTokenAppCtx(input []byte) int {
|
||||
// FUZZER INIT
|
||||
if len(input) < 100 {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
tp, err := go_fuzz_utils.NewTypeProvider(input)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
prefix := ""
|
||||
err, prefix = maybeFillRandom(tp, prefix)
|
||||
if err != nil {
|
||||
return fuzzFailExitCode
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx = middleware.SetNamespace(ctx, "")
|
||||
|
||||
r := new(fasthttp.RequestCtx)
|
||||
utils.SetContextToRequest(ctx, r)
|
||||
|
||||
strings, err := prepareStrings(tp, 3)
|
||||
|
||||
rand, err := prepareBools(tp, 2)
|
||||
|
||||
if rand[0] == true {
|
||||
r.Request.Header.Set(fasthttp.HeaderAuthorization, "Bearer"+strings[0])
|
||||
} else if rand[1] == true {
|
||||
r.Request.Header.SetCookie(fasthttp.HeaderAuthorization, "Bearer"+strings[1])
|
||||
} else {
|
||||
r.Request.Header.Set(fasthttp.HeaderAuthorization, "Bearer"+strings[0])
|
||||
r.Request.Header.SetCookie(fasthttp.HeaderAuthorization, "Bearer"+strings[1])
|
||||
}
|
||||
|
||||
tokens.StoreBearerTokenAppCtx(ctx, r)
|
||||
|
||||
return fuzzSuccessExitCode
|
||||
}
|
||||
|
||||
func FuzzStoreBearerTokenAppCtx(f *testing.F) {
|
||||
f.Fuzz(func(t *testing.T, data []byte) {
|
||||
DoFuzzStoreBearerTokenAppCtx(data)
|
||||
})
|
||||
}
|
709
tests/fuzzing/dict.txt
Normal file
709
tests/fuzzing/dict.txt
Normal file
|
@ -0,0 +1,709 @@
|
|||
" "
|
||||
"()<>@,;:\\\\\\"
|
||||
"-"
|
||||
"--"
|
||||
"."
|
||||
"/"
|
||||
"\\"
|
||||
"_"
|
||||
".0."
|
||||
":0"
|
||||
"0"
|
||||
"0.0.0.0:8080"
|
||||
".0.address"
|
||||
".0.priority"
|
||||
".0.weight"
|
||||
"100"
|
||||
"101"
|
||||
"102"
|
||||
"103"
|
||||
"1.2.7"
|
||||
"1.3.0"
|
||||
"1d"
|
||||
"1dd37fba80fec4e6a6f13fd708d8dcb3b29def768017052f6c930fa1c5d90bbb"
|
||||
"24h"
|
||||
"-5h"
|
||||
"abc"
|
||||
"access denied"
|
||||
"Access Denied"
|
||||
"actual"
|
||||
"add attribute to result object"
|
||||
"added path /get_by_attribute/{cid}/{attr_key}/{attr_val:*}"
|
||||
"added path /get/{cid}/{oid}"
|
||||
"added path /upload/{cid}"
|
||||
"added path /zip/{cid}/{prefix}"
|
||||
"added storage peer"
|
||||
".address"
|
||||
"address"
|
||||
"addresses to listen"
|
||||
"add server"
|
||||
"aio"
|
||||
"aio container started"
|
||||
"all nodes represent a secondary object"
|
||||
"allocs"
|
||||
"application/json; charset=UTF-8"
|
||||
"application/zip"
|
||||
"app_name"
|
||||
"archive/zip"
|
||||
"attachment"
|
||||
"attachment; filename=\\"
|
||||
"attr_key"
|
||||
"attr_val"
|
||||
"Authorization"
|
||||
"Average request duration (in milliseconds) for specific method on node in pool"
|
||||
"avg_request_duration"
|
||||
"bad base64 cookie"
|
||||
"bad base64 header"
|
||||
"bad cookie, but good header"
|
||||
"bad header and cookie"
|
||||
"bad header, but good cookie"
|
||||
"Bar"
|
||||
"bare"
|
||||
"Bearer "
|
||||
"Bearer"
|
||||
"block"
|
||||
"both deprecated and new system attributes formats are used, please use only one"
|
||||
"--boundary"
|
||||
"--boundary--"
|
||||
"boundary"
|
||||
"bucket"
|
||||
"bucket cid"
|
||||
"bucket name"
|
||||
"bucketname"
|
||||
"bufio"
|
||||
"build zap logger instance: %v"
|
||||
"b.yadro.com/obj/go-118-fuzz-build/testing"
|
||||
"bytes"
|
||||
"cache.buckets.lifetime"
|
||||
"cache.buckets.size"
|
||||
"cannot load TLS key pair from certFile '%s' and keyFile '%s': %w"
|
||||
"can't base64-decode bearer token"
|
||||
"can't base64-decode bearer token: %w"
|
||||
"can't gracefully shut down service, force stop"
|
||||
"can't shut down service"
|
||||
"can't unmarshal bearer token"
|
||||
"can't unmarshal bearer token: %w"
|
||||
"CERTIFICATE"
|
||||
"cert.pem"
|
||||
"cert provider: disabled"
|
||||
"cid"
|
||||
"close temporary multipart/form file"
|
||||
"close zip writer"
|
||||
"commandline"
|
||||
"config"
|
||||
"config-dir"
|
||||
"config dir path"
|
||||
"config paths"
|
||||
"connect_timeout"
|
||||
"console"
|
||||
"constant_labels,omitempty"
|
||||
"container_id"
|
||||
"container not found %s"
|
||||
"container resolver will be disabled because of resolvers 'resolver_order' is empty"
|
||||
"Content-Disposition"
|
||||
"content of file"
|
||||
"content of file1"
|
||||
"content of file2"
|
||||
"Content-Transfer-Encoding"
|
||||
"Content-Transfer-Encoding: quoted-printable"
|
||||
"Content-Type"
|
||||
"context"
|
||||
"__context_bearer_token_key"
|
||||
"cookie token unmarshal error"
|
||||
"copy object payload to zip file: %v"
|
||||
"could not detect Content-Type from payload"
|
||||
"could not detect Content-Type from payload: "
|
||||
"could not dial nns: %w"
|
||||
"could not encode response"
|
||||
"could not fetch and store bearer token"
|
||||
"could not fetch and store bearer token: "
|
||||
"could not fetch bearer token"
|
||||
"could not get bucket"
|
||||
"could not get bucket: "
|
||||
"could not load FrostFS private key"
|
||||
"could not parse client time"
|
||||
"could not prepare expiration header"
|
||||
"could not prepare expiration header: "
|
||||
"could not prepare listener: %w"
|
||||
"could not process headers"
|
||||
"could not receive multipart/form"
|
||||
"could not receive multipart/form: "
|
||||
"could not receive object"
|
||||
"could not search for objects"
|
||||
"could not search for objects: "
|
||||
"could not store file in frostfs"
|
||||
"could not unescape attr_key: "
|
||||
"could not unescape attr_val: "
|
||||
"could not unescape prefix: "
|
||||
"couldn't decrypt account: %w"
|
||||
"couldn't find wallet account for %s"
|
||||
"couldn't get epoch durations from network info: %w"
|
||||
"couldn't get namespace from context"
|
||||
"couldn't parse creation date"
|
||||
"couldn't parse value %s of header %s"
|
||||
"couldn't put bucket info into cache"
|
||||
"couldn't read password"
|
||||
"couldn't resolve container '%s' as '%s': %w"
|
||||
"couldn't resolve container '%s': %w"
|
||||
"create_session"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"current_errors"
|
||||
"Current HTTP gateway state"
|
||||
"custom"
|
||||
"data"
|
||||
"data to return"
|
||||
"Date header"
|
||||
"debug"
|
||||
"/debug/pprof/"
|
||||
"/debug/pprof/cmdline"
|
||||
"/debug/pprof/profile"
|
||||
"/debug/pprof/symbol"
|
||||
"/debug/pprof/trace"
|
||||
"default"
|
||||
"Default environments:"
|
||||
"delete_container"
|
||||
"delete_object"
|
||||
"dev"
|
||||
"dGVzdAo="
|
||||
"dns"
|
||||
"download"
|
||||
"duplicate address"
|
||||
"duplicate keys error"
|
||||
"duplicate system keys error"
|
||||
"elapsed"
|
||||
"empty"
|
||||
"enable pprof"
|
||||
"enable prometheus"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"endpoint"
|
||||
"endpoint_info"
|
||||
"Enter password > "
|
||||
"EpochDuration is empty"
|
||||
"error_detail"
|
||||
"errors"
|
||||
"expected"
|
||||
"EXPIRATION_DURATION"
|
||||
"EXPIRATION_EPOCH"
|
||||
"expiration epoch '%d' must be greater than current epoch '%d'"
|
||||
"EXPIRATION_RFC3339"
|
||||
"EXPIRATION_TIMESTAMP"
|
||||
"failed to add object to archive"
|
||||
"failed to add server"
|
||||
"failed to create connection pool"
|
||||
"failed to create resolver"
|
||||
"failed to create tree pool"
|
||||
"failed to dial connection pool"
|
||||
"failed to dial tree pool"
|
||||
"failed to initialize tracing"
|
||||
"failed to reconnect server"
|
||||
"failed to reload config"
|
||||
"failed to reload config because it's missed"
|
||||
"failed to reload server parameters"
|
||||
"failed to shutdown tracing"
|
||||
"failed to unescape query"
|
||||
"failed to update cert (listener close: %v): %w"
|
||||
"failed to update resolvers"
|
||||
"failed to update tls certs: %w"
|
||||
"file"
|
||||
"; filename="
|
||||
"filename"
|
||||
"FileName"
|
||||
"File to export http gateway metrics to."
|
||||
"first-value"
|
||||
"first_value"
|
||||
"flag"
|
||||
"flag 'out' must be provided to dump metrics description"
|
||||
"flush zip writer: %v"
|
||||
"fmt"
|
||||
"--foo"
|
||||
"Foo"
|
||||
"--foobar"
|
||||
"foo-bar"
|
||||
"Foo-Bar"
|
||||
"foo.txt"
|
||||
"form"
|
||||
"form-data"
|
||||
"found empty bearer token"
|
||||
"friendly"
|
||||
"FrostFS"
|
||||
"frostfs.buffer_max_size_for_put"
|
||||
"frostfs.client_cut"
|
||||
"FrostFS HTTP Gateway\\nVersion: %s\\nGoVersion: %s\\n"
|
||||
"FrostFS HTTP Gateway %s\\n"
|
||||
"frostfs-http-gw"
|
||||
"frostfs_http_gw"
|
||||
"FrostFS nodes"
|
||||
"frostfs.tree_pool_max_attempts"
|
||||
"frost-http-gw"
|
||||
"gateway timeout"
|
||||
"/get/"
|
||||
"get"
|
||||
"GET"
|
||||
"get_balance"
|
||||
"/get_by_attribute/"
|
||||
"get by attribute "
|
||||
"get by attribute"
|
||||
"/get_by_attribute/{cid}/{attr_key}/{attr_val:*}"
|
||||
"/get/{cid}/{oid:*}"
|
||||
"get_container"
|
||||
"get_container_eacl"
|
||||
"get frostfs container '%s': %w"
|
||||
"get FrostFS object: %v"
|
||||
"get latest object version"
|
||||
"get_object"
|
||||
"get zip "
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/api"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/api/layer"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/cache"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/data"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/frostfs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/frostfs/services"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/handler"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/handler/middleware"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/handler/multipart"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/internal/logs"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/metrics"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/resolver"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/response"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/tokens"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/tree"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-http-gw/utils"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-observability/tracing/grpc"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-s3-gw/api"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/bearer"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/checksum"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/acl"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/container/id/test"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/eacl"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/netmap"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ns"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/object/id"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool/tree"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/pool/tree/service"
|
||||
"git.frostfs.info/TrueCloudLab/frostfs-sdk-go/user"
|
||||
"git.frostfs.info/TrueCloudLab/zapjournald"
|
||||
"github.com/bluele/gcache"
|
||||
"github.com/fasthttp/router"
|
||||
"github.com/nspcc-dev/neo-go/cli/flags"
|
||||
"github.com/nspcc-dev/neo-go/cli/input"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/prometheus/client_model/go"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/ssgreg/journald"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
"github.com/testcontainers/testcontainers-go/wait"
|
||||
"github.com/trailofbits/go-fuzz-utils"
|
||||
"github.com/valyala/fasthttp"
|
||||
"golang.org/x/exp/slices"
|
||||
"golang.org/x/net/http2"
|
||||
"GOMEMLIMIT"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/semconv/v1.17.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"goroutine"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"gRPC connection rebalance timer"
|
||||
"gRPC connect timeout"
|
||||
"gRPC individual message timeout"
|
||||
"gRPC request timeout"
|
||||
"h"
|
||||
"h2"
|
||||
"head"
|
||||
"head by attribute"
|
||||
"header token unmarshal error"
|
||||
"head_object"
|
||||
"health"
|
||||
"heap"
|
||||
"hello"
|
||||
"help"
|
||||
"host"
|
||||
"http://"
|
||||
"http.client_address"
|
||||
"HTTP_GW"
|
||||
"http://localhost:30333"
|
||||
"http.path"
|
||||
"http.query"
|
||||
"HTTP Server endpoint health"
|
||||
"https://localhost:%d"
|
||||
"id"
|
||||
"ignore part, empty filename"
|
||||
"ignore part, empty form name"
|
||||
"incorrect logger level configuration %s (%v), "
|
||||
"init full object reading via connection pool"
|
||||
"init full payload range reading via connection pool"
|
||||
"init object search via connection pool"
|
||||
"init payload range reading via connection pool"
|
||||
"inline"
|
||||
"invalid address"
|
||||
"invalid cache entry type"
|
||||
"invalid cache size, using default value"
|
||||
"invalid duration"
|
||||
"invalid duration negative"
|
||||
"invalid filepath '%s'"
|
||||
"invalid lifetime, using default value (in seconds)"
|
||||
"invalid metric type"
|
||||
"invalid rfc3339"
|
||||
"invalid rfc3339 zero"
|
||||
"invalid servers configuration: no known server found"
|
||||
"invalid timestamp sec"
|
||||
"invalid timestamp sec zero"
|
||||
"invalid token"
|
||||
"invalid-token"
|
||||
"invalid tree node: %w"
|
||||
"io"
|
||||
"IsDeleteMarker"
|
||||
"iterating over selected objects failed"
|
||||
"journald"
|
||||
"key"
|
||||
"key duplication error: "
|
||||
"key duplication error: %s"
|
||||
"key.pem"
|
||||
"less than 512b"
|
||||
"list_container"
|
||||
"listen_address"
|
||||
"listen and serve"
|
||||
"localhost"
|
||||
"localhost:8080"
|
||||
"localhost:8082"
|
||||
"localhost:8083"
|
||||
"localhost:8084"
|
||||
"logger.destination"
|
||||
"logger.level"
|
||||
"log level won't be updated"
|
||||
"math"
|
||||
"math/big"
|
||||
"method"
|
||||
"Method Not Allowed"
|
||||
"metrics"
|
||||
"metrics are disabled"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
"mime/quotedprintable"
|
||||
"more than 512b"
|
||||
"multipart: boundary is empty"
|
||||
"multipart: expecting a new Part; got line %q"
|
||||
"multipart: NextPart: %v"
|
||||
"multipart: unexpected line in Next(): %q"
|
||||
"mutex"
|
||||
"MyAttribute"
|
||||
"myFile"
|
||||
"\\n"
|
||||
"name"
|
||||
"namespace"
|
||||
"\\n--boundary"
|
||||
"neofs-"
|
||||
"Neofs-"
|
||||
"__NEOFS__"
|
||||
"NEOFS-"
|
||||
"Neofs-Expiration-Epoch"
|
||||
"__NEOFS__EXPIRATION_EPOCH"
|
||||
"Neofs-Random-Attr"
|
||||
"__NEOFS__RANDOM_ATTR"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/pprof"
|
||||
"net/textproto"
|
||||
"net/url"
|
||||
"network_info"
|
||||
"newFile.txt"
|
||||
"new_value"
|
||||
"nil context"
|
||||
"nns"
|
||||
"node"
|
||||
"no healthy servers"
|
||||
"no resolvers"
|
||||
"normal"
|
||||
"not found"
|
||||
"Not found"
|
||||
"Not Found"
|
||||
"no wallet path specified, creating ephemeral key automatically for this run"
|
||||
".ns"
|
||||
"Number of errors on current connections that will be reset after the threshold"
|
||||
"object body close error: %w"
|
||||
"object deleted"
|
||||
"object_id"
|
||||
"object not found"
|
||||
"objects not found"
|
||||
"object was deleted"
|
||||
"object wasn't found"
|
||||
"oid"
|
||||
"OID"
|
||||
"oid1"
|
||||
"oid2"
|
||||
"ok for cookie"
|
||||
"ok for header"
|
||||
"old_value"
|
||||
"one node of the object version"
|
||||
"one node of the object version and one node of the secondary object"
|
||||
"os"
|
||||
"os/signal"
|
||||
"out"
|
||||
"overall_errors"
|
||||
"overall_node_errors"
|
||||
"overall_node_requests"
|
||||
"p"
|
||||
"parameter"
|
||||
"parse expiration epoch '%s': %w"
|
||||
"path"
|
||||
"peers"
|
||||
"Peers preset:"
|
||||
"pool"
|
||||
"pool_error_threshold"
|
||||
"pool must not be nil for DNS resolver"
|
||||
"pprof"
|
||||
"Pprof"
|
||||
"pprof.address"
|
||||
"pprof.enabled"
|
||||
"prefix"
|
||||
".priority"
|
||||
"priority"
|
||||
"Prometheus"
|
||||
"prometheus.address"
|
||||
"prometheus.enabled"
|
||||
"put_container"
|
||||
"put_object"
|
||||
"put with bearer token in cookie"
|
||||
"put with bearer token in header"
|
||||
"put with duplicate keys "
|
||||
"query"
|
||||
"quoted-printable"
|
||||
"range_object"
|
||||
"read container via connection pool"
|
||||
"read full object payload"
|
||||
"read network info via client"
|
||||
"read network info via client: %w"
|
||||
"read object header via connection pool"
|
||||
"read object list failed"
|
||||
"read object list failed: "
|
||||
"read payload"
|
||||
"read system DNS parameter of the FrostFS: %w"
|
||||
"rebalance_timer"
|
||||
"reconnecting server..."
|
||||
"reconnect_interval"
|
||||
"remote"
|
||||
"REP 1"
|
||||
"request"
|
||||
"REQUEST"
|
||||
"request_timeout"
|
||||
"resolve_bucket.default_namespaces"
|
||||
"resolve_bucket.namespace_header"
|
||||
"resolve_order"
|
||||
"resolver nns won't be used since rpc_endpoint isn't provided"
|
||||
"resolver settings must not be nil for DNS resolver"
|
||||
"resolver settings must not be nil for NNS resolver"
|
||||
"\\r\\n"
|
||||
"\\r\\n--"
|
||||
"\\r\\n--boundary"
|
||||
"root"
|
||||
"root2"
|
||||
"rpc address must not be empty for NNS resolver"
|
||||
"rpc_endpoint"
|
||||
"RSA PRIVATE KEY"
|
||||
"runtime"
|
||||
"runtime/debug"
|
||||
"runtime.soft_memory_limit"
|
||||
"s3-client-cut"
|
||||
"save object via connection pool"
|
||||
"second-value"
|
||||
"second_value"
|
||||
"server"
|
||||
"server.0.address"
|
||||
"server reconnected successfully"
|
||||
"service"
|
||||
"service couldn't start on configured port"
|
||||
"service hasn't started since it's disabled"
|
||||
"service is running"
|
||||
"set_container_eacl"
|
||||
"set container name resolve order"
|
||||
"several nodes of different types and with different timestamp"
|
||||
"show help"
|
||||
"show version"
|
||||
"shutting down service"
|
||||
"shutting down web server"
|
||||
"SIGHUP config reload completed"
|
||||
"SIGHUP config reload started"
|
||||
"simple get "
|
||||
"simple put "
|
||||
"soft runtime memory defined with GOMEMLIMIT environment variable, config value skipped"
|
||||
"soft runtime memory limit value updated"
|
||||
"some-attr"
|
||||
"some-get-by-attr-value"
|
||||
"some-get-value"
|
||||
"Some txt content. Content-Type must be detected properly by detector."
|
||||
"sort"
|
||||
"%s_%s_[N]_ADDRESS = string\\n"
|
||||
"%s_%s_[N]_WEIGHT = float\\n"
|
||||
"%s_%s = %s\\n"
|
||||
"%s/%s/%s/%s"
|
||||
"starting application"
|
||||
"starting server"
|
||||
"state"
|
||||
"stdout"
|
||||
"strconv"
|
||||
"stream_timeout"
|
||||
"strings"
|
||||
"%s: %v"
|
||||
"%s: %v: %s"
|
||||
"%s: %w"
|
||||
"%s: %w: %s"
|
||||
"sync"
|
||||
"syscall"
|
||||
"system"
|
||||
"system-"
|
||||
"System-"
|
||||
"__SYSTEM__"
|
||||
"SYSTEM-"
|
||||
"SystemDNS"
|
||||
"system DNS parameter not found or empty"
|
||||
"System-Expiration-Epoch"
|
||||
"__SYSTEM__EXPIRATION_EPOCH"
|
||||
"__SYSTEM__EXPIRATION_EPOCH1"
|
||||
"__SYSTEM__EXPIRATION_EPOCH2"
|
||||
"__SYSTEM__EXPIRATION_EPOCH3"
|
||||
"System-Random-Attr"
|
||||
"__SYSTEM__RANDOM_ATTR"
|
||||
"\\t"
|
||||
"%T"
|
||||
"tcp"
|
||||
"testing"
|
||||
"test namespaces "
|
||||
"test_resolver"
|
||||
"text/plain; charset=utf-8"
|
||||
"threadcreate"
|
||||
"time"
|
||||
"timeout"
|
||||
"tls cert"
|
||||
"tls.cert_file"
|
||||
"TLS certificate path"
|
||||
"tls disabled"
|
||||
"tls enabled"
|
||||
"tls.enabled"
|
||||
"tls key"
|
||||
"tls.key_file"
|
||||
"TLS key path"
|
||||
"token"
|
||||
"TOKEN"
|
||||
"token is missing in the context"
|
||||
"token without payload"
|
||||
"token without the bearer prefix"
|
||||
"Total number of errors for connection in pool"
|
||||
"Total number of errors in pool"
|
||||
"Total number of requests to specific node in pool"
|
||||
"tracing config updated"
|
||||
"tracing.enabled"
|
||||
"tracing.endpoint"
|
||||
"tracing.exporter"
|
||||
"true"
|
||||
"truecloudlab/frostfs-aio:"
|
||||
"type"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
"unknown resolver: %s"
|
||||
"/upload/"
|
||||
"/upload/{cid}"
|
||||
"upload_header.use_default_timestamp"
|
||||
"User-Attribute"
|
||||
"user value"
|
||||
"using credentials"
|
||||
"usupported filters"
|
||||
"v"
|
||||
"val"
|
||||
"valid duration"
|
||||
"valid epoch"
|
||||
"valid epoch, valid duration"
|
||||
"valid epoch, valid rfc3339"
|
||||
"valid epoch, valid timestamp milli"
|
||||
"valid epoch, valid timestamp nano"
|
||||
"valid epoch, valid timestamp sec"
|
||||
"valid max uint 64"
|
||||
"valid rfc3339"
|
||||
"valid timestamp sec"
|
||||
"value"
|
||||
"value in config"
|
||||
"value should be one of %v"
|
||||
"value %s of header %s must be in the future"
|
||||
"value %s of header %s must be positive"
|
||||
"variable_labels,omitempty"
|
||||
"version"
|
||||
"version_info"
|
||||
"Version of current FrostFS HTTP Gate instance"
|
||||
"w"
|
||||
"wallet"
|
||||
"wallet.address"
|
||||
"wallet.passphrase"
|
||||
"wallet.path"
|
||||
"web.max_request_body_size"
|
||||
"web.read_buffer_size"
|
||||
"web.read_timeout"
|
||||
"web.stream_request_body"
|
||||
"web.write_buffer_size"
|
||||
"web.write_timeout"
|
||||
".weight"
|
||||
"weight"
|
||||
"WRONG BASE64"
|
||||
"wrong destination for logger: %s"
|
||||
"wrong object id"
|
||||
"%w: %s"
|
||||
"X-Attribute-"
|
||||
"X-Attribute-DupKey"
|
||||
"X-Attribute-FileName"
|
||||
"X-Attribute-FROSTFS"
|
||||
"X-Attribute-MyAttribute"
|
||||
"X-Attribute-neofs"
|
||||
"X-Attribute-System-"
|
||||
"X-Attribute-SYSTEM"
|
||||
"X-Attribute-System-DupKey"
|
||||
"X-Attribute-System-Expiration-Duration"
|
||||
"X-Attribute-System-Expiration-Epoch"
|
||||
"X-Attribute-System-Expiration-Epoch1"
|
||||
"X-Attribute-SYSTEM-Expiration-Epoch2"
|
||||
"X-Attribute-system-Expiration-Epoch3"
|
||||
"X-Attribute-System-Expiration-RFC3339"
|
||||
"X-Attribute-System-Expiration-Timestamp"
|
||||
"X-Attribute-Timestamp"
|
||||
"X-Attribute-User-Attribute"
|
||||
"x-container-id"
|
||||
"X-Container-Id"
|
||||
"X-Frostfs-Namespace"
|
||||
"x-object-id"
|
||||
"X-Object-Id"
|
||||
"X-Owner-Id"
|
||||
".yaml"
|
||||
"yaml"
|
||||
".yml"
|
||||
"/zip/"
|
||||
"zip"
|
||||
"/zip/{cid}/{prefix:*}"
|
||||
"zip.compression"
|
||||
"zip create header: %v"
|
||||
"/zipfolder"
|
||||
"/zipfolder/dir"
|
||||
"zipfolder/dir/name1.txt"
|
||||
"zipfolder/name2.txt"
|
Loading…
Reference in a new issue