[bug] S3 provider should limit max key size to 1024 #31
This commit is contained in:
parent
f28e17f3e5
commit
5e3efde376
@ -11,6 +11,7 @@
|
|||||||
* ~~\#28 \[bug\] Address slow directory responses in S3 mounts for deep nested directories~~
|
* ~~\#28 \[bug\] Address slow directory responses in S3 mounts for deep nested directories~~
|
||||||
* \#29 \[bug\] S3 error responses are not being logged
|
* \#29 \[bug\] S3 error responses are not being logged
|
||||||
* ~~\#30 \[bug\] Sia json error responses are not logged~~
|
* ~~\#30 \[bug\] Sia json error responses are not logged~~
|
||||||
|
* ~~\#31 \[bug\] S3 provider should limit max key size to 1024~~
|
||||||
|
|
||||||
### Changes from v2.0.2-rc
|
### Changes from v2.0.2-rc
|
||||||
|
|
||||||
|
@ -200,6 +200,7 @@ enum class api_error {
|
|||||||
item_exists,
|
item_exists,
|
||||||
item_not_found,
|
item_not_found,
|
||||||
more_data,
|
more_data,
|
||||||
|
name_too_long,
|
||||||
no_disk_space,
|
no_disk_space,
|
||||||
not_implemented,
|
not_implemented,
|
||||||
not_supported,
|
not_supported,
|
||||||
@ -216,31 +217,33 @@ enum class api_error {
|
|||||||
|
|
||||||
[[nodiscard]] auto api_error_from_string(std::string_view str) -> api_error;
|
[[nodiscard]] auto api_error_from_string(std::string_view str) -> api_error;
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto api_error_to_string(const api_error &error)
|
||||||
api_error_to_string(const api_error &error) -> const std::string &;
|
-> const std::string &;
|
||||||
|
|
||||||
enum class database_type {
|
enum class database_type {
|
||||||
rocksdb,
|
rocksdb,
|
||||||
sqlite,
|
sqlite,
|
||||||
};
|
};
|
||||||
[[nodiscard]] auto database_type_from_string(
|
|
||||||
std::string type,
|
|
||||||
database_type default_type = database_type::rocksdb) -> database_type;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
database_type_to_string(const database_type &type) -> std::string;
|
database_type_from_string(std::string type,
|
||||||
|
database_type default_type = database_type::rocksdb)
|
||||||
|
-> database_type;
|
||||||
|
|
||||||
|
[[nodiscard]] auto database_type_to_string(const database_type &type)
|
||||||
|
-> std::string;
|
||||||
|
|
||||||
enum class download_type {
|
enum class download_type {
|
||||||
default_,
|
default_,
|
||||||
direct,
|
direct,
|
||||||
ring_buffer,
|
ring_buffer,
|
||||||
};
|
};
|
||||||
[[nodiscard]] auto download_type_from_string(
|
|
||||||
std::string type,
|
|
||||||
download_type default_type = download_type::default_) -> download_type;
|
|
||||||
|
|
||||||
[[nodiscard]] auto
|
[[nodiscard]] auto
|
||||||
download_type_to_string(const download_type &type) -> std::string;
|
download_type_from_string(std::string type,
|
||||||
|
download_type default_type = download_type::default_)
|
||||||
|
-> download_type;
|
||||||
|
|
||||||
|
[[nodiscard]] auto download_type_to_string(const download_type &type)
|
||||||
|
-> std::string;
|
||||||
|
|
||||||
enum class exit_code : std::int32_t {
|
enum class exit_code : std::int32_t {
|
||||||
success = 0,
|
success = 0,
|
||||||
|
@ -39,6 +39,19 @@
|
|||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
#include "utils/time.hpp"
|
#include "utils/time.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
[[nodiscard]] auto set_request_path(auto &request, const auto &cfg,
|
||||||
|
const std::string &object_name)
|
||||||
|
-> repertory::api_error {
|
||||||
|
request.path = object_name;
|
||||||
|
if ((cfg.bucket + request.path).subst(0U).size() > 1024U) {
|
||||||
|
return repertory::api_error::name_too_long;
|
||||||
|
}
|
||||||
|
|
||||||
|
return repertory::api_error::success;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
s3_provider::s3_provider(app_config &config, i_http_comm &comm)
|
s3_provider::s3_provider(app_config &config, i_http_comm &comm)
|
||||||
: base_provider(config, comm) {}
|
: base_provider(config, comm) {}
|
||||||
@ -118,12 +131,17 @@ auto s3_provider::create_directory_impl(const std::string &api_path,
|
|||||||
curl::requests::http_put_file put_file{};
|
curl::requests::http_put_file put_file{};
|
||||||
put_file.allow_timeout = true;
|
put_file.allow_timeout = true;
|
||||||
put_file.aws_service = "aws:amz:" + cfg.region + ":s3";
|
put_file.aws_service = "aws:amz:" + cfg.region + ":s3";
|
||||||
put_file.path = object_name + '/';
|
|
||||||
put_file.response_handler = [&response_data](auto &&data,
|
put_file.response_handler = [&response_data](auto &&data,
|
||||||
|
|
||||||
long /*response_code*/) {
|
long /*response_code*/) {
|
||||||
response_data = std::string(data.begin(), data.end());
|
response_data = std::string(data.begin(), data.end());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto res = set_request_path(put_file, cfg, object_name + '/');
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
long response_code{};
|
long response_code{};
|
||||||
if (not get_comm().make_request(put_file, response_code, stop_requested)) {
|
if (not get_comm().make_request(put_file, response_code, stop_requested)) {
|
||||||
utils::error::raise_api_path_error(function_name, api_path,
|
utils::error::raise_api_path_error(function_name, api_path,
|
||||||
@ -221,12 +239,17 @@ auto s3_provider::create_path_directories(const std::string &api_path,
|
|||||||
curl::requests::http_put_file put_file{};
|
curl::requests::http_put_file put_file{};
|
||||||
put_file.allow_timeout = true;
|
put_file.allow_timeout = true;
|
||||||
put_file.aws_service = "aws:amz:" + cfg.region + ":s3";
|
put_file.aws_service = "aws:amz:" + cfg.region + ":s3";
|
||||||
put_file.path = (is_encrypted ? cur_key : cur_path) + '/';
|
|
||||||
put_file.response_handler = [&response_data](auto &&data,
|
put_file.response_handler = [&response_data](auto &&data,
|
||||||
long /*response_code*/) {
|
long /*response_code*/) {
|
||||||
response_data = std::string(data.begin(), data.end());
|
response_data = std::string(data.begin(), data.end());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
res = set_request_path(put_file, cfg,
|
||||||
|
(is_encrypted ? cur_key : cur_path) + '/');
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
stop_type stop_requested{false};
|
stop_type stop_requested{false};
|
||||||
long response_code{};
|
long response_code{};
|
||||||
if (not get_comm().make_request(put_file, response_code,
|
if (not get_comm().make_request(put_file, response_code,
|
||||||
@ -655,12 +678,16 @@ auto s3_provider::get_object_info(bool directory, const std::string &api_path,
|
|||||||
curl::requests::http_head head{};
|
curl::requests::http_head head{};
|
||||||
head.allow_timeout = true;
|
head.allow_timeout = true;
|
||||||
head.aws_service = "aws:amz:" + cfg.region + ":s3";
|
head.aws_service = "aws:amz:" + cfg.region + ":s3";
|
||||||
head.path = directory ? object_name + '/' : object_name;
|
|
||||||
head.response_headers = http_headers{};
|
head.response_headers = http_headers{};
|
||||||
head.response_handler = [&response_data](auto &&data,
|
head.response_handler = [&response_data](auto &&data,
|
||||||
long /*response_code*/) {
|
long /*response_code*/) {
|
||||||
response_data = std::string(data.begin(), data.end());
|
response_data = std::string(data.begin(), data.end());
|
||||||
};
|
};
|
||||||
|
res = set_request_path(put_file, cfg,
|
||||||
|
directory ? object_name + '/' : object_name);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
stop_type stop_requested{false};
|
stop_type stop_requested{false};
|
||||||
long response_code{};
|
long response_code{};
|
||||||
@ -813,7 +840,6 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
|||||||
curl::requests::http_get get{};
|
curl::requests::http_get get{};
|
||||||
get.aws_service = "aws:amz:" + cfg.region + ":s3";
|
get.aws_service = "aws:amz:" + cfg.region + ":s3";
|
||||||
get.headers["response-content-type"] = "binary/octet-stream";
|
get.headers["response-content-type"] = "binary/octet-stream";
|
||||||
get.path = object_name;
|
|
||||||
get.range = {{
|
get.range = {{
|
||||||
read_offset,
|
read_offset,
|
||||||
read_offset + read_size - 1U,
|
read_offset + read_size - 1U,
|
||||||
@ -822,6 +848,10 @@ auto s3_provider::read_file_bytes(const std::string &api_path, std::size_t size,
|
|||||||
long /*response_code*/) {
|
long /*response_code*/) {
|
||||||
read_buffer = response_data;
|
read_buffer = response_data;
|
||||||
};
|
};
|
||||||
|
res = set_request_path(get, cfg, object_name);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
long response_code{};
|
long response_code{};
|
||||||
const auto notify_retry = [&]() {
|
const auto notify_retry = [&]() {
|
||||||
@ -912,11 +942,15 @@ auto s3_provider::remove_directory_impl(const std::string &api_path)
|
|||||||
curl::requests::http_delete del{};
|
curl::requests::http_delete del{};
|
||||||
del.allow_timeout = true;
|
del.allow_timeout = true;
|
||||||
del.aws_service = "aws:amz:" + cfg.region + ":s3";
|
del.aws_service = "aws:amz:" + cfg.region + ":s3";
|
||||||
del.path = object_name + '/';
|
|
||||||
del.response_handler = [&response_data](auto &&data, long /*response_code*/) {
|
del.response_handler = [&response_data](auto &&data, long /*response_code*/) {
|
||||||
response_data = std::string(data.begin(), data.end());
|
response_data = std::string(data.begin(), data.end());
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto res = set_request_path(del, cfg, object_name + '/');
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
long response_code{};
|
long response_code{};
|
||||||
stop_type stop_requested{};
|
stop_type stop_requested{};
|
||||||
if (not get_comm().make_request(del, response_code, stop_requested)) {
|
if (not get_comm().make_request(del, response_code, stop_requested)) {
|
||||||
@ -959,10 +993,13 @@ auto s3_provider::remove_file_impl(const std::string &api_path) -> api_error {
|
|||||||
curl::requests::http_delete del{};
|
curl::requests::http_delete del{};
|
||||||
del.allow_timeout = true;
|
del.allow_timeout = true;
|
||||||
del.aws_service = "aws:amz:" + cfg.region + ":s3";
|
del.aws_service = "aws:amz:" + cfg.region + ":s3";
|
||||||
del.path = object_name;
|
|
||||||
del.response_handler = [&response_data](auto &&data, long /*response_code*/) {
|
del.response_handler = [&response_data](auto &&data, long /*response_code*/) {
|
||||||
response_data = std::string(data.begin(), data.end());
|
response_data = std::string(data.begin(), data.end());
|
||||||
};
|
};
|
||||||
|
auto res = set_request_path(del, cfg, object_name);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
long response_code{};
|
long response_code{};
|
||||||
stop_type stop_requested{};
|
stop_type stop_requested{};
|
||||||
@ -1036,13 +1073,17 @@ auto s3_provider::upload_file_impl(const std::string &api_path,
|
|||||||
std::string response_data;
|
std::string response_data;
|
||||||
curl::requests::http_put_file put_file{};
|
curl::requests::http_put_file put_file{};
|
||||||
put_file.aws_service = "aws:amz:" + cfg.region + ":s3";
|
put_file.aws_service = "aws:amz:" + cfg.region + ":s3";
|
||||||
put_file.path = object_name;
|
|
||||||
put_file.response_handler = [&response_data](auto &&data,
|
put_file.response_handler = [&response_data](auto &&data,
|
||||||
long /*response_code*/) {
|
long /*response_code*/) {
|
||||||
response_data = std::string(data.begin(), data.end());
|
response_data = std::string(data.begin(), data.end());
|
||||||
};
|
};
|
||||||
put_file.source_path = source_path;
|
put_file.source_path = source_path;
|
||||||
|
|
||||||
|
auto res = set_request_path(put_file, cfg, object_name);
|
||||||
|
if (res != api_error::success) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
if (is_encrypted && file_size > 0U) {
|
if (is_encrypted && file_size > 0U) {
|
||||||
static stop_type no_stop{false};
|
static stop_type no_stop{false};
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
namespace repertory {
|
namespace repertory {
|
||||||
auto database_type_from_string(std::string type,
|
auto database_type_from_string(std::string type, database_type default_type)
|
||||||
database_type default_type) -> database_type {
|
-> database_type {
|
||||||
type = utils::string::to_lower(utils::string::trim(type));
|
type = utils::string::to_lower(utils::string::trim(type));
|
||||||
if (type == "rocksdb") {
|
if (type == "rocksdb") {
|
||||||
return database_type::rocksdb;
|
return database_type::rocksdb;
|
||||||
@ -50,8 +50,8 @@ auto database_type_to_string(const database_type &type) -> std::string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto download_type_from_string(std::string type,
|
auto download_type_from_string(std::string type, download_type default_type)
|
||||||
download_type default_type) -> download_type {
|
-> download_type {
|
||||||
type = utils::string::to_lower(utils::string::trim(type));
|
type = utils::string::to_lower(utils::string::trim(type));
|
||||||
if (type == "default") {
|
if (type == "default") {
|
||||||
return download_type::default_;
|
return download_type::default_;
|
||||||
@ -112,6 +112,7 @@ static const std::unordered_map<api_error, std::string> LOOKUP = {
|
|||||||
{api_error::item_exists, "item_exists"},
|
{api_error::item_exists, "item_exists"},
|
||||||
{api_error::item_not_found, "item_not_found"},
|
{api_error::item_not_found, "item_not_found"},
|
||||||
{api_error::more_data, "more_data"},
|
{api_error::more_data, "more_data"},
|
||||||
|
{api_error::name_too_long, "name_too_long"},
|
||||||
{api_error::no_disk_space, "no_disk_space"},
|
{api_error::no_disk_space, "no_disk_space"},
|
||||||
{api_error::not_implemented, "not_implemented"},
|
{api_error::not_implemented, "not_implemented"},
|
||||||
{api_error::not_supported, "not_supported"},
|
{api_error::not_supported, "not_supported"},
|
||||||
|
@ -58,6 +58,8 @@ auto from_api_error(const api_error &err) -> int {
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
case api_error::item_not_found:
|
case api_error::item_not_found:
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
case api_error::name_too_long:
|
||||||
|
return -ENAMETOOLONG;
|
||||||
case api_error::out_of_memory:
|
case api_error::out_of_memory:
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
case api_error::no_disk_space:
|
case api_error::no_disk_space:
|
||||||
@ -128,6 +130,8 @@ auto to_api_error(int err) -> api_error {
|
|||||||
return api_error::file_in_use;
|
return api_error::file_in_use;
|
||||||
case EINVAL:
|
case EINVAL:
|
||||||
return api_error::invalid_operation;
|
return api_error::invalid_operation;
|
||||||
|
case ENAMETOOLONG:
|
||||||
|
return api_error::name_too_long;
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
return api_error::item_not_found;
|
return api_error::item_not_found;
|
||||||
case ENOMEM:
|
case ENOMEM:
|
||||||
|
@ -65,6 +65,8 @@ auto from_api_error(const api_error &e) -> NTSTATUS {
|
|||||||
return STATUS_CLIENT_SERVER_PARAMETERS_INVALID;
|
return STATUS_CLIENT_SERVER_PARAMETERS_INVALID;
|
||||||
case api_error::item_not_found:
|
case api_error::item_not_found:
|
||||||
return STATUS_OBJECT_NAME_NOT_FOUND;
|
return STATUS_OBJECT_NAME_NOT_FOUND;
|
||||||
|
case api_error::name_too_long:
|
||||||
|
return STATUS_NAME_TOO_LONG;
|
||||||
case api_error::no_disk_space:
|
case api_error::no_disk_space:
|
||||||
return STATUS_DEVICE_INSUFFICIENT_RESOURCES;
|
return STATUS_DEVICE_INSUFFICIENT_RESOURCES;
|
||||||
case api_error::os_error:
|
case api_error::os_error:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user