You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-07-05 00:28:52 +02:00
Allow path-style URIs in S3 driver.
Although path-style URIs have been deprecated by AWS, they may still be used with products like Minio because no additional DNS configuration is required. Path-style URIs must be explicitly enabled since it is not clear how they can be auto-detected reliably. More importantly, faulty detection could cause regressions in current installations.
This commit is contained in:
@ -283,6 +283,8 @@ use constant CFGOPT_REPO_S3_REGION => CFGDEF_RE
|
|||||||
push @EXPORT, qw(CFGOPT_REPO_S3_REGION);
|
push @EXPORT, qw(CFGOPT_REPO_S3_REGION);
|
||||||
use constant CFGOPT_REPO_S3_TOKEN => CFGDEF_REPO_S3 . '-token';
|
use constant CFGOPT_REPO_S3_TOKEN => CFGDEF_REPO_S3 . '-token';
|
||||||
push @EXPORT, qw(CFGOPT_REPO_S3_TOKEN);
|
push @EXPORT, qw(CFGOPT_REPO_S3_TOKEN);
|
||||||
|
use constant CFGOPT_REPO_S3_URI_STYLE => CFGDEF_REPO_S3 . '-uri-style';
|
||||||
|
push @EXPORT, qw(CFGOPT_REPO_S3_URI_STYLE);
|
||||||
use constant CFGOPT_REPO_S3_VERIFY_TLS => CFGDEF_REPO_S3 . '-verify-tls';
|
use constant CFGOPT_REPO_S3_VERIFY_TLS => CFGDEF_REPO_S3 . '-verify-tls';
|
||||||
push @EXPORT, qw(CFGOPT_REPO_S3_VERIFY_TLS);
|
push @EXPORT, qw(CFGOPT_REPO_S3_VERIFY_TLS);
|
||||||
|
|
||||||
@ -401,6 +403,13 @@ use constant CFGOPTVAL_REPO_CIPHER_TYPE_NONE => 'none';
|
|||||||
use constant CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC => 'aes-256-cbc';
|
use constant CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC => 'aes-256-cbc';
|
||||||
push @EXPORT, qw(CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
|
push @EXPORT, qw(CFGOPTVAL_REPO_CIPHER_TYPE_AES_256_CBC);
|
||||||
|
|
||||||
|
# Repo S3 URI style
|
||||||
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
use constant CFGOPTVAL_REPO_S3_URI_STYLE_HOST => 'host';
|
||||||
|
push @EXPORT, qw(CFGOPTVAL_REPO_S3_URI_STYLE_HOST);
|
||||||
|
use constant CFGOPTVAL_REPO_S3_URI_STYLE_PATH => 'path';
|
||||||
|
push @EXPORT, qw(CFGOPTVAL_REPO_S3_URI_STYLE_PATH);
|
||||||
|
|
||||||
# Info output
|
# Info output
|
||||||
#-----------------------------------------------------------------------------------------------------------------------------------
|
#-----------------------------------------------------------------------------------------------------------------------------------
|
||||||
use constant CFGOPTVAL_OUTPUT_TEXT => 'text';
|
use constant CFGOPTVAL_OUTPUT_TEXT => 'text';
|
||||||
@ -1839,6 +1848,22 @@ my %hConfigDefine =
|
|||||||
&CFGDEF_COMMAND => CFGOPT_REPO_TYPE,
|
&CFGDEF_COMMAND => CFGOPT_REPO_TYPE,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
&CFGOPT_REPO_S3_URI_STYLE =>
|
||||||
|
{
|
||||||
|
&CFGDEF_SECTION => CFGDEF_SECTION_GLOBAL,
|
||||||
|
&CFGDEF_TYPE => CFGDEF_TYPE_STRING,
|
||||||
|
&CFGDEF_PREFIX => CFGDEF_PREFIX_REPO,
|
||||||
|
&CFGDEF_INDEX_TOTAL => CFGDEF_INDEX_REPO,
|
||||||
|
&CFGDEF_DEFAULT => CFGOPTVAL_REPO_S3_URI_STYLE_HOST,
|
||||||
|
&CFGDEF_ALLOW_LIST =>
|
||||||
|
[
|
||||||
|
&CFGOPTVAL_REPO_S3_URI_STYLE_HOST,
|
||||||
|
&CFGOPTVAL_REPO_S3_URI_STYLE_PATH,
|
||||||
|
],
|
||||||
|
&CFGDEF_COMMAND => CFGOPT_REPO_TYPE,
|
||||||
|
&CFGDEF_DEPEND => CFGOPT_REPO_S3_BUCKET,
|
||||||
|
},
|
||||||
|
|
||||||
&CFGOPT_REPO_S3_VERIFY_TLS =>
|
&CFGOPT_REPO_S3_VERIFY_TLS =>
|
||||||
{
|
{
|
||||||
&CFGDEF_SECTION => CFGDEF_SECTION_GLOBAL,
|
&CFGDEF_SECTION => CFGDEF_SECTION_GLOBAL,
|
||||||
|
@ -455,6 +455,19 @@
|
|||||||
<example>us-east-1</example>
|
<example>us-east-1</example>
|
||||||
</config-key>
|
</config-key>
|
||||||
|
|
||||||
|
<!-- CONFIG - REPO SECTION - REPO-S3-URI-STYLE KEY -->
|
||||||
|
<config-key id="repo-s3-uri-style" name="S3 Repository URI Style">
|
||||||
|
<summary>S3 URI Style.</summary>
|
||||||
|
|
||||||
|
<text>The following URI styles are supported:
|
||||||
|
<ul>
|
||||||
|
<li><id>host</id> - Connect to <id>bucket.endpoint</id> host.</li>
|
||||||
|
<li><id>path</id> - Connect to <id>endpoint</id> host and prepend bucket to URIs.</li>
|
||||||
|
</ul></text>
|
||||||
|
|
||||||
|
<example>path</example>
|
||||||
|
</config-key>
|
||||||
|
|
||||||
<!-- CONFIG - REPO SECTION - REPO-S3-VERIFY-TLS KEY -->
|
<!-- CONFIG - REPO SECTION - REPO-S3-VERIFY-TLS KEY -->
|
||||||
<config-key id="repo-s3-verify-tls" name="S3 Repository Verify TLS">
|
<config-key id="repo-s3-verify-tls" name="S3 Repository Verify TLS">
|
||||||
<summary>Verify S3 server certificate.</summary>
|
<summary>Verify S3 server certificate.</summary>
|
||||||
|
@ -36,6 +36,10 @@
|
|||||||
|
|
||||||
<p>Specifies the database user name when connecting to <postgres/>. If not specified <backrest/> will connect with the local OS user or <id>PGUSER</id>, which was the previous behavior.</p>
|
<p>Specifies the database user name when connecting to <postgres/>. If not specified <backrest/> will connect with the local OS user or <id>PGUSER</id>, which was the previous behavior.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
|
||||||
|
<release-item>
|
||||||
|
<p>Allow path-style URIs in <proper>S3</proper> driver.</p>
|
||||||
|
</release-item>
|
||||||
</release-feature-list>
|
</release-feature-list>
|
||||||
|
|
||||||
<release-improvement-list>
|
<release-improvement-list>
|
||||||
|
@ -27,6 +27,9 @@ sub libcAutoConstant
|
|||||||
CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_DIFF => 'diff',
|
CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_DIFF => 'diff',
|
||||||
CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_INCR => 'incr',
|
CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_INCR => 'incr',
|
||||||
|
|
||||||
|
CFGOPTVAL_REPO_S3_URI_STYLE_HOST => 'host',
|
||||||
|
CFGOPTVAL_REPO_S3_URI_STYLE_PATH => 'path',
|
||||||
|
|
||||||
CFGOPTVAL_REPO_TYPE_CIFS => 'cifs',
|
CFGOPTVAL_REPO_TYPE_CIFS => 'cifs',
|
||||||
CFGOPTVAL_REPO_TYPE_POSIX => 'posix',
|
CFGOPTVAL_REPO_TYPE_POSIX => 'posix',
|
||||||
CFGOPTVAL_REPO_TYPE_S3 => 's3',
|
CFGOPTVAL_REPO_TYPE_S3 => 's3',
|
||||||
@ -91,6 +94,8 @@ sub libcAutoExportTag
|
|||||||
'CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_FULL',
|
'CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_FULL',
|
||||||
'CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_DIFF',
|
'CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_DIFF',
|
||||||
'CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_INCR',
|
'CFGOPTVAL_REPO_RETENTION_ARCHIVE_TYPE_INCR',
|
||||||
|
'CFGOPTVAL_REPO_S3_URI_STYLE_HOST',
|
||||||
|
'CFGOPTVAL_REPO_S3_URI_STYLE_PATH',
|
||||||
'CFGOPTVAL_REPO_TYPE_CIFS',
|
'CFGOPTVAL_REPO_TYPE_CIFS',
|
||||||
'CFGOPTVAL_REPO_TYPE_POSIX',
|
'CFGOPTVAL_REPO_TYPE_POSIX',
|
||||||
'CFGOPTVAL_REPO_TYPE_S3',
|
'CFGOPTVAL_REPO_TYPE_S3',
|
||||||
@ -286,6 +291,7 @@ sub libcAutoExportTag
|
|||||||
'CFGOPT_REPO_S3_PORT',
|
'CFGOPT_REPO_S3_PORT',
|
||||||
'CFGOPT_REPO_S3_REGION',
|
'CFGOPT_REPO_S3_REGION',
|
||||||
'CFGOPT_REPO_S3_TOKEN',
|
'CFGOPT_REPO_S3_TOKEN',
|
||||||
|
'CFGOPT_REPO_S3_URI_STYLE',
|
||||||
'CFGOPT_REPO_S3_VERIFY_TLS',
|
'CFGOPT_REPO_S3_VERIFY_TLS',
|
||||||
'CFGOPT_REPO_TYPE',
|
'CFGOPT_REPO_TYPE',
|
||||||
'CFGOPT_RESUME',
|
'CFGOPT_RESUME',
|
||||||
|
@ -458,6 +458,7 @@ STRING_EXTERN(CFGOPT_REPO1_S3_KEY_SECRET_STR, CFGOPT_REPO1
|
|||||||
STRING_EXTERN(CFGOPT_REPO1_S3_PORT_STR, CFGOPT_REPO1_S3_PORT);
|
STRING_EXTERN(CFGOPT_REPO1_S3_PORT_STR, CFGOPT_REPO1_S3_PORT);
|
||||||
STRING_EXTERN(CFGOPT_REPO1_S3_REGION_STR, CFGOPT_REPO1_S3_REGION);
|
STRING_EXTERN(CFGOPT_REPO1_S3_REGION_STR, CFGOPT_REPO1_S3_REGION);
|
||||||
STRING_EXTERN(CFGOPT_REPO1_S3_TOKEN_STR, CFGOPT_REPO1_S3_TOKEN);
|
STRING_EXTERN(CFGOPT_REPO1_S3_TOKEN_STR, CFGOPT_REPO1_S3_TOKEN);
|
||||||
|
STRING_EXTERN(CFGOPT_REPO1_S3_URI_STYLE_STR, CFGOPT_REPO1_S3_URI_STYLE);
|
||||||
STRING_EXTERN(CFGOPT_REPO1_S3_VERIFY_TLS_STR, CFGOPT_REPO1_S3_VERIFY_TLS);
|
STRING_EXTERN(CFGOPT_REPO1_S3_VERIFY_TLS_STR, CFGOPT_REPO1_S3_VERIFY_TLS);
|
||||||
STRING_EXTERN(CFGOPT_REPO1_TYPE_STR, CFGOPT_REPO1_TYPE);
|
STRING_EXTERN(CFGOPT_REPO1_TYPE_STR, CFGOPT_REPO1_TYPE);
|
||||||
STRING_EXTERN(CFGOPT_RESUME_STR, CFGOPT_RESUME);
|
STRING_EXTERN(CFGOPT_RESUME_STR, CFGOPT_RESUME);
|
||||||
@ -1728,6 +1729,14 @@ static ConfigOptionData configOptionData[CFG_OPTION_TOTAL] = CONFIG_OPTION_LIST
|
|||||||
CONFIG_OPTION_DEFINE_ID(cfgDefOptRepoS3Token)
|
CONFIG_OPTION_DEFINE_ID(cfgDefOptRepoS3Token)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
CONFIG_OPTION
|
||||||
|
(
|
||||||
|
CONFIG_OPTION_NAME(CFGOPT_REPO1_S3_URI_STYLE)
|
||||||
|
CONFIG_OPTION_INDEX(0)
|
||||||
|
CONFIG_OPTION_DEFINE_ID(cfgDefOptRepoS3UriStyle)
|
||||||
|
)
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
CONFIG_OPTION
|
CONFIG_OPTION
|
||||||
(
|
(
|
||||||
|
@ -365,6 +365,8 @@ Option constants
|
|||||||
STRING_DECLARE(CFGOPT_REPO1_S3_REGION_STR);
|
STRING_DECLARE(CFGOPT_REPO1_S3_REGION_STR);
|
||||||
#define CFGOPT_REPO1_S3_TOKEN "repo1-s3-token"
|
#define CFGOPT_REPO1_S3_TOKEN "repo1-s3-token"
|
||||||
STRING_DECLARE(CFGOPT_REPO1_S3_TOKEN_STR);
|
STRING_DECLARE(CFGOPT_REPO1_S3_TOKEN_STR);
|
||||||
|
#define CFGOPT_REPO1_S3_URI_STYLE "repo1-s3-uri-style"
|
||||||
|
STRING_DECLARE(CFGOPT_REPO1_S3_URI_STYLE_STR);
|
||||||
#define CFGOPT_REPO1_S3_VERIFY_TLS "repo1-s3-verify-tls"
|
#define CFGOPT_REPO1_S3_VERIFY_TLS "repo1-s3-verify-tls"
|
||||||
STRING_DECLARE(CFGOPT_REPO1_S3_VERIFY_TLS_STR);
|
STRING_DECLARE(CFGOPT_REPO1_S3_VERIFY_TLS_STR);
|
||||||
#define CFGOPT_REPO1_TYPE "repo1-type"
|
#define CFGOPT_REPO1_TYPE "repo1-type"
|
||||||
@ -398,7 +400,7 @@ Option constants
|
|||||||
#define CFGOPT_TYPE "type"
|
#define CFGOPT_TYPE "type"
|
||||||
STRING_DECLARE(CFGOPT_TYPE_STR);
|
STRING_DECLARE(CFGOPT_TYPE_STR);
|
||||||
|
|
||||||
#define CFG_OPTION_TOTAL 172
|
#define CFG_OPTION_TOTAL 173
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Command enum
|
Command enum
|
||||||
@ -588,6 +590,7 @@ typedef enum
|
|||||||
cfgOptRepoS3Port,
|
cfgOptRepoS3Port,
|
||||||
cfgOptRepoS3Region,
|
cfgOptRepoS3Region,
|
||||||
cfgOptRepoS3Token,
|
cfgOptRepoS3Token,
|
||||||
|
cfgOptRepoS3UriStyle,
|
||||||
cfgOptRepoS3VerifyTls,
|
cfgOptRepoS3VerifyTls,
|
||||||
cfgOptRepoType,
|
cfgOptRepoType,
|
||||||
cfgOptResume,
|
cfgOptResume,
|
||||||
|
@ -3938,6 +3938,68 @@ static ConfigDefineOptionData configDefineOptionData[] = CFGDEFDATA_OPTION_LIST
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------------------
|
||||||
|
CFGDEFDATA_OPTION
|
||||||
|
(
|
||||||
|
CFGDEFDATA_OPTION_NAME("repo-s3-uri-style")
|
||||||
|
CFGDEFDATA_OPTION_REQUIRED(true)
|
||||||
|
CFGDEFDATA_OPTION_SECTION(cfgDefSectionGlobal)
|
||||||
|
CFGDEFDATA_OPTION_TYPE(cfgDefOptTypeString)
|
||||||
|
CFGDEFDATA_OPTION_INTERNAL(false)
|
||||||
|
|
||||||
|
CFGDEFDATA_OPTION_INDEX_TOTAL(1)
|
||||||
|
CFGDEFDATA_OPTION_SECURE(false)
|
||||||
|
|
||||||
|
CFGDEFDATA_OPTION_HELP_SECTION("repository")
|
||||||
|
CFGDEFDATA_OPTION_HELP_SUMMARY("S3 URI Style.")
|
||||||
|
CFGDEFDATA_OPTION_HELP_DESCRIPTION
|
||||||
|
(
|
||||||
|
"The following URI styles are supported:\n"
|
||||||
|
"\n"
|
||||||
|
"* host - Connect to bucket.endpoint host.\n"
|
||||||
|
"* path - Connect to endpoint host and prepend bucket to URIs."
|
||||||
|
)
|
||||||
|
|
||||||
|
CFGDEFDATA_OPTION_COMMAND_LIST
|
||||||
|
(
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchiveGet)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchiveGetAsync)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchivePush)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdArchivePushAsync)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdBackup)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdCheck)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdExpire)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdInfo)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdLocal)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdLs)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRemote)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdRestore)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaCreate)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaDelete)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStanzaUpgrade)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStart)
|
||||||
|
CFGDEFDATA_OPTION_COMMAND(cfgDefCmdStop)
|
||||||
|
)
|
||||||
|
|
||||||
|
CFGDEFDATA_OPTION_OPTIONAL_LIST
|
||||||
|
(
|
||||||
|
CFGDEFDATA_OPTION_OPTIONAL_ALLOW_LIST
|
||||||
|
(
|
||||||
|
"host",
|
||||||
|
"path"
|
||||||
|
)
|
||||||
|
|
||||||
|
CFGDEFDATA_OPTION_OPTIONAL_DEPEND_LIST
|
||||||
|
(
|
||||||
|
cfgDefOptRepoType,
|
||||||
|
"s3"
|
||||||
|
)
|
||||||
|
|
||||||
|
CFGDEFDATA_OPTION_OPTIONAL_DEFAULT("host")
|
||||||
|
CFGDEFDATA_OPTION_OPTIONAL_PREFIX("repo")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------------------
|
||||||
CFGDEFDATA_OPTION
|
CFGDEFDATA_OPTION
|
||||||
(
|
(
|
||||||
|
@ -131,6 +131,7 @@ typedef enum
|
|||||||
cfgDefOptRepoS3Port,
|
cfgDefOptRepoS3Port,
|
||||||
cfgDefOptRepoS3Region,
|
cfgDefOptRepoS3Region,
|
||||||
cfgDefOptRepoS3Token,
|
cfgDefOptRepoS3Token,
|
||||||
|
cfgDefOptRepoS3UriStyle,
|
||||||
cfgDefOptRepoS3VerifyTls,
|
cfgDefOptRepoS3VerifyTls,
|
||||||
cfgDefOptRepoType,
|
cfgDefOptRepoType,
|
||||||
cfgDefOptResume,
|
cfgDefOptResume,
|
||||||
|
@ -2120,6 +2120,18 @@ static const struct option optionList[] =
|
|||||||
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | cfgOptRepoS3Token,
|
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | cfgOptRepoS3Token,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// repo-s3-uri-style option
|
||||||
|
// -----------------------------------------------------------------------------------------------------------------------------
|
||||||
|
{
|
||||||
|
.name = CFGOPT_REPO1_S3_URI_STYLE,
|
||||||
|
.has_arg = required_argument,
|
||||||
|
.val = PARSE_OPTION_FLAG | cfgOptRepoS3UriStyle,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "reset-" CFGOPT_REPO1_S3_URI_STYLE,
|
||||||
|
.val = PARSE_OPTION_FLAG | PARSE_RESET_FLAG | cfgOptRepoS3UriStyle,
|
||||||
|
},
|
||||||
|
|
||||||
// repo-s3-verify-tls option and deprecations
|
// repo-s3-verify-tls option and deprecations
|
||||||
// -----------------------------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------------------------
|
||||||
{
|
{
|
||||||
@ -2489,6 +2501,7 @@ static const ConfigOption optionResolveOrder[] =
|
|||||||
cfgOptRepoS3Port,
|
cfgOptRepoS3Port,
|
||||||
cfgOptRepoS3Region,
|
cfgOptRepoS3Region,
|
||||||
cfgOptRepoS3Token,
|
cfgOptRepoS3Token,
|
||||||
|
cfgOptRepoS3UriStyle,
|
||||||
cfgOptRepoS3VerifyTls,
|
cfgOptRepoS3VerifyTls,
|
||||||
cfgOptTarget,
|
cfgOptTarget,
|
||||||
cfgOptTargetAction,
|
cfgOptTargetAction,
|
||||||
|
@ -369,6 +369,7 @@ storageRepoGet(const String *type, bool write)
|
|||||||
|
|
||||||
result = storageS3New(
|
result = storageS3New(
|
||||||
cfgOptionStr(cfgOptRepoPath), write, storageRepoPathExpression, cfgOptionStr(cfgOptRepoS3Bucket), endPoint,
|
cfgOptionStr(cfgOptRepoPath), write, storageRepoPathExpression, cfgOptionStr(cfgOptRepoS3Bucket), endPoint,
|
||||||
|
strEqZ(cfgOptionStr(cfgOptRepoS3UriStyle), STORAGE_S3_URI_STYLE_HOST) ? storageS3UriStyleHost : storageS3UriStylePath,
|
||||||
cfgOptionStr(cfgOptRepoS3Region), cfgOptionStr(cfgOptRepoS3Key), cfgOptionStr(cfgOptRepoS3KeySecret),
|
cfgOptionStr(cfgOptRepoS3Region), cfgOptionStr(cfgOptRepoS3Key), cfgOptionStr(cfgOptRepoS3KeySecret),
|
||||||
cfgOptionTest(cfgOptRepoS3Token) ? cfgOptionStr(cfgOptRepoS3Token) : NULL, STORAGE_S3_PARTSIZE_MIN,
|
cfgOptionTest(cfgOptRepoS3Token) ? cfgOptionStr(cfgOptRepoS3Token) : NULL, STORAGE_S3_PARTSIZE_MIN,
|
||||||
STORAGE_S3_DELETE_MAX, host, port, STORAGE_S3_TIMEOUT_DEFAULT, cfgOptionBool(cfgOptRepoS3VerifyTls),
|
STORAGE_S3_DELETE_MAX, host, port, STORAGE_S3_TIMEOUT_DEFAULT, cfgOptionBool(cfgOptRepoS3VerifyTls),
|
||||||
|
@ -98,6 +98,7 @@ struct StorageS3
|
|||||||
const String *securityToken; // Security token, if any
|
const String *securityToken; // Security token, if any
|
||||||
size_t partSize; // Part size for multi-part upload
|
size_t partSize; // Part size for multi-part upload
|
||||||
unsigned int deleteMax; // Maximum objects that can be deleted in one request
|
unsigned int deleteMax; // Maximum objects that can be deleted in one request
|
||||||
|
StorageS3UriStyle uriStyle; // Path or host style URIs
|
||||||
const String *bucketEndpoint; // Set to {bucket}.{endpoint}
|
const String *bucketEndpoint; // Set to {bucket}.{endpoint}
|
||||||
unsigned int port; // Host port
|
unsigned int port; // Host port
|
||||||
|
|
||||||
@ -258,6 +259,10 @@ storageS3Request(
|
|||||||
unsigned int retryRemaining = 2;
|
unsigned int retryRemaining = 2;
|
||||||
bool done;
|
bool done;
|
||||||
|
|
||||||
|
// When using path-style URIs the bucket name needs to be prepended
|
||||||
|
if (this->uriStyle == storageS3UriStylePath)
|
||||||
|
uri = strNewFmt("/%s%s", strPtr(this->bucket), strPtr(uri));
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
done = true;
|
done = true;
|
||||||
@ -917,9 +922,9 @@ static const StorageInterface storageInterfaceS3 =
|
|||||||
Storage *
|
Storage *
|
||||||
storageS3New(
|
storageS3New(
|
||||||
const String *path, bool write, StoragePathExpressionCallback pathExpressionFunction, const String *bucket,
|
const String *path, bool write, StoragePathExpressionCallback pathExpressionFunction, const String *bucket,
|
||||||
const String *endPoint, const String *region, const String *accessKey, const String *secretAccessKey,
|
const String *endPoint, StorageS3UriStyle uriStyle, const String *region, const String *accessKey,
|
||||||
const String *securityToken, size_t partSize, unsigned int deleteMax, const String *host, unsigned int port, TimeMSec timeout,
|
const String *secretAccessKey, const String *securityToken, size_t partSize, unsigned int deleteMax, const String *host,
|
||||||
bool verifyPeer, const String *caFile, const String *caPath)
|
unsigned int port, TimeMSec timeout, bool verifyPeer, const String *caFile, const String *caPath)
|
||||||
{
|
{
|
||||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||||
FUNCTION_LOG_PARAM(STRING, path);
|
FUNCTION_LOG_PARAM(STRING, path);
|
||||||
@ -927,6 +932,7 @@ storageS3New(
|
|||||||
FUNCTION_LOG_PARAM(FUNCTIONP, pathExpressionFunction);
|
FUNCTION_LOG_PARAM(FUNCTIONP, pathExpressionFunction);
|
||||||
FUNCTION_LOG_PARAM(STRING, bucket);
|
FUNCTION_LOG_PARAM(STRING, bucket);
|
||||||
FUNCTION_LOG_PARAM(STRING, endPoint);
|
FUNCTION_LOG_PARAM(STRING, endPoint);
|
||||||
|
FUNCTION_LOG_PARAM(ENUM, uriStyle);
|
||||||
FUNCTION_LOG_PARAM(STRING, region);
|
FUNCTION_LOG_PARAM(STRING, region);
|
||||||
FUNCTION_TEST_PARAM(STRING, accessKey);
|
FUNCTION_TEST_PARAM(STRING, accessKey);
|
||||||
FUNCTION_TEST_PARAM(STRING, secretAccessKey);
|
FUNCTION_TEST_PARAM(STRING, secretAccessKey);
|
||||||
@ -962,7 +968,9 @@ storageS3New(
|
|||||||
driver->securityToken = strDup(securityToken);
|
driver->securityToken = strDup(securityToken);
|
||||||
driver->partSize = partSize;
|
driver->partSize = partSize;
|
||||||
driver->deleteMax = deleteMax;
|
driver->deleteMax = deleteMax;
|
||||||
driver->bucketEndpoint = strNewFmt("%s.%s", strPtr(bucket), strPtr(endPoint));
|
driver->uriStyle = uriStyle;
|
||||||
|
driver->bucketEndpoint = uriStyle == storageS3UriStyleHost ?
|
||||||
|
strNewFmt("%s.%s", strPtr(bucket), strPtr(endPoint)) : strDup(endPoint);
|
||||||
driver->port = port;
|
driver->port = port;
|
||||||
|
|
||||||
// Force the signing key to be generated on the first run
|
// Force the signing key to be generated on the first run
|
||||||
|
@ -12,6 +12,18 @@ Storage type
|
|||||||
#define STORAGE_S3_TYPE "s3"
|
#define STORAGE_S3_TYPE "s3"
|
||||||
STRING_DECLARE(STORAGE_S3_TYPE_STR);
|
STRING_DECLARE(STORAGE_S3_TYPE_STR);
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
URI style
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
storageS3UriStyleHost,
|
||||||
|
storageS3UriStylePath,
|
||||||
|
} StorageS3UriStyle;
|
||||||
|
|
||||||
|
#define STORAGE_S3_URI_STYLE_HOST "host"
|
||||||
|
#define STORAGE_S3_URI_STYLE_PATH "path"
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Defaults
|
Defaults
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -24,8 +36,8 @@ Constructor
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
Storage *storageS3New(
|
Storage *storageS3New(
|
||||||
const String *path, bool write, StoragePathExpressionCallback pathExpressionFunction, const String *bucket,
|
const String *path, bool write, StoragePathExpressionCallback pathExpressionFunction, const String *bucket,
|
||||||
const String *endPoint, const String *region, const String *accessKey, const String *secretAccessKey,
|
const String *endPoint, StorageS3UriStyle uriStyle, const String *region, const String *accessKey,
|
||||||
const String *securityToken, size_t partSize, unsigned int deleteMax, const String *host, unsigned int port, TimeMSec timeout,
|
const String *secretAccessKey, const String *securityToken, size_t partSize, unsigned int deleteMax, const String *host,
|
||||||
bool verifyPeer, const String *caFile, const String *caPath);
|
unsigned int port, TimeMSec timeout, bool verifyPeer, const String *caFile, const String *caPath);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -210,6 +210,7 @@ testRun(void)
|
|||||||
" --repo-s3-port s3 repository port [default=443]\n"
|
" --repo-s3-port s3 repository port [default=443]\n"
|
||||||
" --repo-s3-region s3 repository region\n"
|
" --repo-s3-region s3 repository region\n"
|
||||||
" --repo-s3-token s3 repository security token\n"
|
" --repo-s3-token s3 repository security token\n"
|
||||||
|
" --repo-s3-uri-style s3 URI Style [default=host]\n"
|
||||||
" --repo-s3-verify-tls verify S3 server certificate [default=y]\n"
|
" --repo-s3-verify-tls verify S3 server certificate [default=y]\n"
|
||||||
" --repo-type type of storage used for the repository\n"
|
" --repo-type type of storage used for the repository\n"
|
||||||
" [default=posix]\n"
|
" [default=posix]\n"
|
||||||
|
@ -9,14 +9,14 @@ Test S3 Storage
|
|||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test server
|
Test server
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#define S3_TEST_HOST "bucket.s3.amazonaws.com"
|
#define S3_TEST_HOST "s3.amazonaws.com"
|
||||||
#define DATE_REPLACE "????????"
|
#define DATE_REPLACE "????????"
|
||||||
#define DATETIME_REPLACE "????????T??????Z"
|
#define DATETIME_REPLACE "????????T??????Z"
|
||||||
#define SHA256_REPLACE \
|
#define SHA256_REPLACE \
|
||||||
"????????????????????????????????????????????????????????????????"
|
"????????????????????????????????????????????????????????????????"
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
testS3ServerRequest(const char *verb, const char *uri, const char *content)
|
testS3ServerRequest(const char *verb, const char *uri, const char *content, StorageS3UriStyle uriStyle)
|
||||||
{
|
{
|
||||||
String *request = strNewFmt(
|
String *request = strNewFmt(
|
||||||
"%s %s HTTP/1.1\r\n"
|
"%s %s HTTP/1.1\r\n"
|
||||||
@ -40,9 +40,13 @@ testS3ServerRequest(const char *verb, const char *uri, const char *content)
|
|||||||
strCatFmt(request, "content-md5:%s\r\n", md5Hash);
|
strCatFmt(request, "content-md5:%s\r\n", md5Hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uriStyle == storageS3UriStyleHost)
|
||||||
|
strCatFmt(request, "host:bucket." S3_TEST_HOST "\r\n");
|
||||||
|
else
|
||||||
|
strCatFmt(request, "host:" S3_TEST_HOST "\r\n");
|
||||||
|
|
||||||
strCatFmt(
|
strCatFmt(
|
||||||
request,
|
request,
|
||||||
"host:" S3_TEST_HOST "\r\n"
|
|
||||||
"x-amz-content-sha256:%s\r\n"
|
"x-amz-content-sha256:%s\r\n"
|
||||||
"x-amz-date:" DATETIME_REPLACE "\r\n"
|
"x-amz-date:" DATETIME_REPLACE "\r\n"
|
||||||
"\r\n",
|
"\r\n",
|
||||||
@ -88,29 +92,29 @@ testS3Server(void)
|
|||||||
// storageS3NewRead() and StorageS3FileRead
|
// storageS3NewRead() and StorageS3FileRead
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
// Ignore missing file
|
// Ignore missing file
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/fi%26le.txt", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/fi%26le.txt", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(404, "Not Found", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse(404, "Not Found", NULL, NULL));
|
||||||
|
|
||||||
// Error on missing file
|
// Error on missing file
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/file.txt", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/file.txt", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(404, "Not Found", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse(404, "Not Found", NULL, NULL));
|
||||||
|
|
||||||
// Get file
|
// Get file
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/file.txt", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/file.txt", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, "this is a sample file"));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, "this is a sample file"));
|
||||||
|
|
||||||
// Get zero-length file
|
// Get zero-length file
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/file0.txt", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/file0.txt", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
||||||
|
|
||||||
// Throw non-404 error
|
// Throw non-404 error
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/file.txt", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/file.txt", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(303, "Some bad status", NULL, "CONTENT"));
|
harnessTlsServerReply(testS3ServerResponse(303, "Some bad status", NULL, "CONTENT"));
|
||||||
|
|
||||||
// storageS3NewWrite() and StorageWriteS3
|
// storageS3NewWrite() and StorageWriteS3
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
// File is written all at once
|
// File is written all at once
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_PUT, "/file.txt", "ABCD"));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_PUT, "/file.txt", "ABCD", storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(
|
harnessTlsServerReply(testS3ServerResponse(
|
||||||
403, "Forbidden", NULL,
|
403, "Forbidden", NULL,
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||||
@ -125,15 +129,15 @@ testS3Server(void)
|
|||||||
"</Error>"));
|
"</Error>"));
|
||||||
|
|
||||||
harnessTlsServerAccept();
|
harnessTlsServerAccept();
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_PUT, "/file.txt", "ABCD"));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_PUT, "/file.txt", "ABCD", storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
||||||
|
|
||||||
// Zero-length file
|
// Zero-length file
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_PUT, "/file.txt", ""));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_PUT, "/file.txt", "", storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
||||||
|
|
||||||
// File is written in chunks with nothing left over on close
|
// File is written in chunks with nothing left over on close
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_POST, "/file.txt?uploads=", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_POST, "/file.txt?uploads=", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(
|
harnessTlsServerReply(testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||||
@ -143,9 +147,11 @@ testS3Server(void)
|
|||||||
"<UploadId>WxRt</UploadId>"
|
"<UploadId>WxRt</UploadId>"
|
||||||
"</InitiateMultipartUploadResult>"));
|
"</InitiateMultipartUploadResult>"));
|
||||||
|
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_PUT, "/file.txt?partNumber=1&uploadId=WxRt", "1234567890123456"));
|
harnessTlsServerExpect(
|
||||||
|
testS3ServerRequest(HTTP_VERB_PUT, "/file.txt?partNumber=1&uploadId=WxRt", "1234567890123456", storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", "etag:WxRt1", NULL));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", "etag:WxRt1", NULL));
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_PUT, "/file.txt?partNumber=2&uploadId=WxRt", "7890123456789012"));
|
harnessTlsServerExpect(
|
||||||
|
testS3ServerRequest(HTTP_VERB_PUT, "/file.txt?partNumber=2&uploadId=WxRt", "7890123456789012", storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", "eTag:WxRt2", NULL));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", "eTag:WxRt2", NULL));
|
||||||
|
|
||||||
harnessTlsServerExpect(testS3ServerRequest(
|
harnessTlsServerExpect(testS3ServerRequest(
|
||||||
@ -154,11 +160,12 @@ testS3Server(void)
|
|||||||
"<CompleteMultipartUpload>"
|
"<CompleteMultipartUpload>"
|
||||||
"<Part><PartNumber>1</PartNumber><ETag>WxRt1</ETag></Part>"
|
"<Part><PartNumber>1</PartNumber><ETag>WxRt1</ETag></Part>"
|
||||||
"<Part><PartNumber>2</PartNumber><ETag>WxRt2</ETag></Part>"
|
"<Part><PartNumber>2</PartNumber><ETag>WxRt2</ETag></Part>"
|
||||||
"</CompleteMultipartUpload>\n"));
|
"</CompleteMultipartUpload>\n",
|
||||||
|
storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
||||||
|
|
||||||
// File is written in chunks with something left over on close
|
// File is written in chunks with something left over on close
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_POST, "/file.txt?uploads=", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_POST, "/file.txt?uploads=", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(
|
harnessTlsServerReply(testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||||
@ -168,9 +175,11 @@ testS3Server(void)
|
|||||||
"<UploadId>RR55</UploadId>"
|
"<UploadId>RR55</UploadId>"
|
||||||
"</InitiateMultipartUploadResult>"));
|
"</InitiateMultipartUploadResult>"));
|
||||||
|
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_PUT, "/file.txt?partNumber=1&uploadId=RR55", "1234567890123456"));
|
harnessTlsServerExpect(
|
||||||
|
testS3ServerRequest(HTTP_VERB_PUT, "/file.txt?partNumber=1&uploadId=RR55", "1234567890123456", storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", "etag:RR551", NULL));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", "etag:RR551", NULL));
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_PUT, "/file.txt?partNumber=2&uploadId=RR55", "7890"));
|
harnessTlsServerExpect(
|
||||||
|
testS3ServerRequest(HTTP_VERB_PUT, "/file.txt?partNumber=2&uploadId=RR55", "7890", storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", "eTag:RR552", NULL));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", "eTag:RR552", NULL));
|
||||||
|
|
||||||
harnessTlsServerExpect(testS3ServerRequest(
|
harnessTlsServerExpect(testS3ServerRequest(
|
||||||
@ -179,27 +188,28 @@ testS3Server(void)
|
|||||||
"<CompleteMultipartUpload>"
|
"<CompleteMultipartUpload>"
|
||||||
"<Part><PartNumber>1</PartNumber><ETag>RR551</ETag></Part>"
|
"<Part><PartNumber>1</PartNumber><ETag>RR551</ETag></Part>"
|
||||||
"<Part><PartNumber>2</PartNumber><ETag>RR552</ETag></Part>"
|
"<Part><PartNumber>2</PartNumber><ETag>RR552</ETag></Part>"
|
||||||
"</CompleteMultipartUpload>\n"));
|
"</CompleteMultipartUpload>\n",
|
||||||
|
storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
||||||
|
|
||||||
// storageDriverExists()
|
// storageDriverExists()
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
// File missing
|
// File missing
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_HEAD, "/BOGUS", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_HEAD, "/BOGUS", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(404, "Not Found", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse(404, "Not Found", NULL, NULL));
|
||||||
|
|
||||||
// File exists
|
// File exists
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_HEAD, "/subdir/file1.txt", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_HEAD, "/subdir/file1.txt", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", "content-length:999", NULL));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", "content-length:999", NULL));
|
||||||
|
|
||||||
// Info()
|
// Info()
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
// File missing
|
// File missing
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_HEAD, "/BOGUS", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_HEAD, "/BOGUS", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(404, "Not Found", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse(404, "Not Found", NULL, NULL));
|
||||||
|
|
||||||
// File exists
|
// File exists
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_HEAD, "/subdir/file1.txt", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_HEAD, "/subdir/file1.txt", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(
|
harnessTlsServerReply(testS3ServerResponse(
|
||||||
200, "OK",
|
200, "OK",
|
||||||
"content-length:9999\r\n"
|
"content-length:9999\r\n"
|
||||||
@ -209,7 +219,7 @@ testS3Server(void)
|
|||||||
// InfoList()
|
// InfoList()
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
harnessTlsServerExpect(
|
harnessTlsServerExpect(
|
||||||
testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2&prefix=path%2Fto%2F", NULL));
|
testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2&prefix=path%2Fto%2F", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
@ -228,10 +238,10 @@ testS3Server(void)
|
|||||||
// storageDriverList()
|
// storageDriverList()
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
// Throw errors
|
// Throw errors
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse( 344, "Another bad status", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse( 344, "Another bad status", NULL, NULL));
|
||||||
|
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(
|
harnessTlsServerReply(testS3ServerResponse(
|
||||||
344, "Another bad status with xml", NULL,
|
344, "Another bad status with xml", NULL,
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||||
@ -239,7 +249,7 @@ testS3Server(void)
|
|||||||
"<Code>SomeOtherCode</Code>"
|
"<Code>SomeOtherCode</Code>"
|
||||||
"</Error>"));
|
"</Error>"));
|
||||||
|
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(
|
harnessTlsServerReply(testS3ServerResponse(
|
||||||
403, "Forbidden", NULL,
|
403, "Forbidden", NULL,
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||||
@ -247,7 +257,7 @@ testS3Server(void)
|
|||||||
"<Code>RequestTimeTooSkewed</Code>"
|
"<Code>RequestTimeTooSkewed</Code>"
|
||||||
"<Message>The difference between the request time and the current time is too large.</Message>"
|
"<Message>The difference between the request time and the current time is too large.</Message>"
|
||||||
"</Error>"));
|
"</Error>"));
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(
|
harnessTlsServerReply(testS3ServerResponse(
|
||||||
403, "Forbidden", NULL,
|
403, "Forbidden", NULL,
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||||
@ -255,7 +265,7 @@ testS3Server(void)
|
|||||||
"<Code>RequestTimeTooSkewed</Code>"
|
"<Code>RequestTimeTooSkewed</Code>"
|
||||||
"<Message>The difference between the request time and the current time is too large.</Message>"
|
"<Message>The difference between the request time and the current time is too large.</Message>"
|
||||||
"</Error>"));
|
"</Error>"));
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(testS3ServerResponse(
|
harnessTlsServerReply(testS3ServerResponse(
|
||||||
403, "Forbidden", NULL,
|
403, "Forbidden", NULL,
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||||
@ -265,7 +275,7 @@ testS3Server(void)
|
|||||||
"</Error>"));
|
"</Error>"));
|
||||||
|
|
||||||
// list a file/path in root
|
// list a file/path in root
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
@ -280,7 +290,8 @@ testS3Server(void)
|
|||||||
"</ListBucketResult>"));
|
"</ListBucketResult>"));
|
||||||
|
|
||||||
// list a file in root with expression
|
// list a file in root with expression
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2&prefix=test", NULL));
|
harnessTlsServerExpect(
|
||||||
|
testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2&prefix=test", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
@ -293,7 +304,7 @@ testS3Server(void)
|
|||||||
|
|
||||||
// list files with continuation
|
// list files with continuation
|
||||||
harnessTlsServerExpect(
|
harnessTlsServerExpect(
|
||||||
testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2&prefix=path%2Fto%2F", NULL));
|
testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2&prefix=path%2Fto%2F", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
@ -316,7 +327,7 @@ testS3Server(void)
|
|||||||
HTTP_VERB_GET,
|
HTTP_VERB_GET,
|
||||||
"/?continuation-token=1ueGcxLPRx1Tr%2FXYExHnhbYLgveDs2J%2Fwm36Hy4vbOwM%3D&delimiter=%2F&list-type=2"
|
"/?continuation-token=1ueGcxLPRx1Tr%2FXYExHnhbYLgveDs2J%2Fwm36Hy4vbOwM%3D&delimiter=%2F&list-type=2"
|
||||||
"&prefix=path%2Fto%2F",
|
"&prefix=path%2Fto%2F",
|
||||||
NULL));
|
NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
@ -332,7 +343,7 @@ testS3Server(void)
|
|||||||
|
|
||||||
// list files with expression
|
// list files with expression
|
||||||
harnessTlsServerExpect(
|
harnessTlsServerExpect(
|
||||||
testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2&prefix=path%2Fto%2Ftest", NULL));
|
testS3ServerRequest(HTTP_VERB_GET, "/?delimiter=%2F&list-type=2&prefix=path%2Fto%2Ftest", NULL, storageS3UriStyleHost));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
@ -357,8 +368,13 @@ testS3Server(void)
|
|||||||
|
|
||||||
// storageDriverPathRemove()
|
// storageDriverPathRemove()
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
// Switch to path-style URIs
|
||||||
|
harnessTlsServerClose();
|
||||||
|
harnessTlsServerAccept();
|
||||||
|
|
||||||
// delete files from root
|
// delete files from root
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?list-type=2", NULL));
|
harnessTlsServerExpect(
|
||||||
|
testS3ServerRequest(HTTP_VERB_GET, "/bucket/?list-type=2", NULL, storageS3UriStylePath));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
@ -373,18 +389,20 @@ testS3Server(void)
|
|||||||
"</ListBucketResult>"));
|
"</ListBucketResult>"));
|
||||||
|
|
||||||
harnessTlsServerExpect(
|
harnessTlsServerExpect(
|
||||||
testS3ServerRequest(HTTP_VERB_POST, "/?delete=",
|
testS3ServerRequest(HTTP_VERB_POST, "/bucket/?delete=",
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
"<Delete><Quiet>true</Quiet>"
|
"<Delete><Quiet>true</Quiet>"
|
||||||
"<Object><Key>test1.txt</Key></Object>"
|
"<Object><Key>test1.txt</Key></Object>"
|
||||||
"<Object><Key>path1/xxx.zzz</Key></Object>"
|
"<Object><Key>path1/xxx.zzz</Key></Object>"
|
||||||
"</Delete>\n"));
|
"</Delete>\n",
|
||||||
|
storageS3UriStylePath));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL, "<DeleteResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"></DeleteResult>"));
|
200, "OK", NULL, "<DeleteResult xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"></DeleteResult>"));
|
||||||
|
|
||||||
// nothing to do in empty subpath
|
// nothing to do in empty subpath
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_GET, "/?list-type=2&prefix=path%2F", NULL));
|
harnessTlsServerExpect(
|
||||||
|
testS3ServerRequest(HTTP_VERB_GET, "/bucket/?list-type=2&prefix=path%2F", NULL, storageS3UriStylePath));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
@ -394,7 +412,7 @@ testS3Server(void)
|
|||||||
|
|
||||||
// delete with continuation
|
// delete with continuation
|
||||||
harnessTlsServerExpect(
|
harnessTlsServerExpect(
|
||||||
testS3ServerRequest(HTTP_VERB_GET, "/?list-type=2&prefix=path%2Fto%2F", NULL));
|
testS3ServerRequest(HTTP_VERB_GET, "/bucket/?list-type=2&prefix=path%2Fto%2F", NULL, storageS3UriStylePath));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
@ -410,7 +428,9 @@ testS3Server(void)
|
|||||||
"</ListBucketResult>"));
|
"</ListBucketResult>"));
|
||||||
|
|
||||||
harnessTlsServerExpect(
|
harnessTlsServerExpect(
|
||||||
testS3ServerRequest(HTTP_VERB_GET, "/?continuation-token=continue&list-type=2&prefix=path%2Fto%2F", NULL));
|
testS3ServerRequest(
|
||||||
|
HTTP_VERB_GET, "/bucket/?continuation-token=continue&list-type=2&prefix=path%2Fto%2F", NULL,
|
||||||
|
storageS3UriStylePath));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
@ -425,25 +445,27 @@ testS3Server(void)
|
|||||||
"</ListBucketResult>"));
|
"</ListBucketResult>"));
|
||||||
|
|
||||||
harnessTlsServerExpect(
|
harnessTlsServerExpect(
|
||||||
testS3ServerRequest(HTTP_VERB_POST, "/?delete=",
|
testS3ServerRequest(HTTP_VERB_POST, "/bucket/?delete=",
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
"<Delete><Quiet>true</Quiet>"
|
"<Delete><Quiet>true</Quiet>"
|
||||||
"<Object><Key>path/to/test1.txt</Key></Object>"
|
"<Object><Key>path/to/test1.txt</Key></Object>"
|
||||||
"<Object><Key>path/to/test3.txt</Key></Object>"
|
"<Object><Key>path/to/test3.txt</Key></Object>"
|
||||||
"</Delete>\n"));
|
"</Delete>\n",
|
||||||
|
storageS3UriStylePath));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
||||||
|
|
||||||
harnessTlsServerExpect(
|
harnessTlsServerExpect(
|
||||||
testS3ServerRequest(HTTP_VERB_POST, "/?delete=",
|
testS3ServerRequest(HTTP_VERB_POST, "/bucket/?delete=",
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
"<Delete><Quiet>true</Quiet>"
|
"<Delete><Quiet>true</Quiet>"
|
||||||
"<Object><Key>path/to/test2.txt</Key></Object>"
|
"<Object><Key>path/to/test2.txt</Key></Object>"
|
||||||
"</Delete>\n"));
|
"</Delete>\n",
|
||||||
|
storageS3UriStylePath));
|
||||||
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse(200, "OK", NULL, NULL));
|
||||||
|
|
||||||
// delete error
|
// delete error
|
||||||
harnessTlsServerExpect(
|
harnessTlsServerExpect(
|
||||||
testS3ServerRequest(HTTP_VERB_GET, "/?list-type=2&prefix=path%2F", NULL));
|
testS3ServerRequest(HTTP_VERB_GET, "/bucket/?list-type=2&prefix=path%2F", NULL, storageS3UriStylePath));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
@ -458,12 +480,13 @@ testS3Server(void)
|
|||||||
"</ListBucketResult>"));
|
"</ListBucketResult>"));
|
||||||
|
|
||||||
harnessTlsServerExpect(
|
harnessTlsServerExpect(
|
||||||
testS3ServerRequest(HTTP_VERB_POST, "/?delete=",
|
testS3ServerRequest(HTTP_VERB_POST, "/bucket/?delete=",
|
||||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||||
"<Delete><Quiet>true</Quiet>"
|
"<Delete><Quiet>true</Quiet>"
|
||||||
"<Object><Key>path/sample.txt</Key></Object>"
|
"<Object><Key>path/sample.txt</Key></Object>"
|
||||||
"<Object><Key>path/sample2.txt</Key></Object>"
|
"<Object><Key>path/sample2.txt</Key></Object>"
|
||||||
"</Delete>\n"));
|
"</Delete>\n",
|
||||||
|
storageS3UriStylePath));
|
||||||
harnessTlsServerReply(
|
harnessTlsServerReply(
|
||||||
testS3ServerResponse(
|
testS3ServerResponse(
|
||||||
200, "OK", NULL,
|
200, "OK", NULL,
|
||||||
@ -475,7 +498,7 @@ testS3Server(void)
|
|||||||
// storageDriverRemove()
|
// storageDriverRemove()
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
// remove file
|
// remove file
|
||||||
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_DELETE, "/path/to/test.txt", NULL));
|
harnessTlsServerExpect(testS3ServerRequest(HTTP_VERB_DELETE, "/bucket/path/to/test.txt", NULL, storageS3UriStylePath));
|
||||||
harnessTlsServerReply(testS3ServerResponse(204, "No Content", NULL, NULL));
|
harnessTlsServerReply(testS3ServerResponse(204, "No Content", NULL, NULL));
|
||||||
|
|
||||||
harnessTlsServerClose();
|
harnessTlsServerClose();
|
||||||
@ -669,8 +692,8 @@ testRun(void)
|
|||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
StorageS3 *driver = (StorageS3 *)storageDriver(
|
StorageS3 *driver = (StorageS3 *)storageDriver(
|
||||||
storageS3New(
|
storageS3New(
|
||||||
path, true, NULL, bucket, endPoint, region, accessKey, secretAccessKey, NULL, 16, 2, NULL, 0, 0, testContainer(),
|
path, true, NULL, bucket, endPoint, storageS3UriStyleHost, region, accessKey, secretAccessKey, NULL, 16, 2, NULL, 0,
|
||||||
NULL, NULL));
|
0, testContainer(), NULL, NULL));
|
||||||
|
|
||||||
HttpHeader *header = httpHeaderNew(NULL);
|
HttpHeader *header = httpHeaderNew(NULL);
|
||||||
|
|
||||||
@ -717,8 +740,8 @@ testRun(void)
|
|||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
driver = (StorageS3 *)storageDriver(
|
driver = (StorageS3 *)storageDriver(
|
||||||
storageS3New(
|
storageS3New(
|
||||||
path, true, NULL, bucket, endPoint, region, accessKey, secretAccessKey, securityToken, 16, 2, NULL, 0, 0,
|
path, true, NULL, bucket, endPoint, storageS3UriStyleHost, region, accessKey, secretAccessKey, securityToken, 16, 2,
|
||||||
testContainer(), NULL, NULL));
|
NULL, 0, 0, testContainer(), NULL, NULL));
|
||||||
|
|
||||||
TEST_RESULT_VOID(
|
TEST_RESULT_VOID(
|
||||||
storageS3Auth(driver, strNew("GET"), strNew("/"), query, strNew("20170606T121212Z"), header, HASH_TYPE_SHA256_ZERO_STR),
|
storageS3Auth(driver, strNew("GET"), strNew("/"), query, strNew("20170606T121212Z"), header, HASH_TYPE_SHA256_ZERO_STR),
|
||||||
@ -737,8 +760,8 @@ testRun(void)
|
|||||||
testS3Server();
|
testS3Server();
|
||||||
|
|
||||||
Storage *s3 = storageS3New(
|
Storage *s3 = storageS3New(
|
||||||
path, true, NULL, bucket, endPoint, region, accessKey, secretAccessKey, NULL, 16, 2, host, port, 1000, testContainer(),
|
path, true, NULL, bucket, endPoint, storageS3UriStyleHost, region, accessKey, secretAccessKey, NULL, 16, 2, host, port,
|
||||||
NULL, NULL);
|
1000, testContainer(), NULL, NULL);
|
||||||
|
|
||||||
// Coverage for noop functions
|
// Coverage for noop functions
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -767,7 +790,7 @@ testRun(void)
|
|||||||
"*** Request Headers ***:\n"
|
"*** Request Headers ***:\n"
|
||||||
"authorization: <redacted>\n"
|
"authorization: <redacted>\n"
|
||||||
"content-length: 0\n"
|
"content-length: 0\n"
|
||||||
"host: " S3_TEST_HOST "\n"
|
"host: bucket." S3_TEST_HOST "\n"
|
||||||
"x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n"
|
"x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n"
|
||||||
"x-amz-date: <redacted>\n"
|
"x-amz-date: <redacted>\n"
|
||||||
"*** Response Headers ***:\n"
|
"*** Response Headers ***:\n"
|
||||||
@ -854,7 +877,7 @@ testRun(void)
|
|||||||
"*** Request Headers ***:\n"
|
"*** Request Headers ***:\n"
|
||||||
"authorization: <redacted>\n"
|
"authorization: <redacted>\n"
|
||||||
"content-length: 0\n"
|
"content-length: 0\n"
|
||||||
"host: " S3_TEST_HOST "\n"
|
"host: bucket." S3_TEST_HOST "\n"
|
||||||
"x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n"
|
"x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n"
|
||||||
"x-amz-date: <redacted>");
|
"x-amz-date: <redacted>");
|
||||||
TEST_ERROR(storageListP(s3, strNew("/")), ProtocolError,
|
TEST_ERROR(storageListP(s3, strNew("/")), ProtocolError,
|
||||||
@ -864,7 +887,7 @@ testRun(void)
|
|||||||
"*** Request Headers ***:\n"
|
"*** Request Headers ***:\n"
|
||||||
"authorization: <redacted>\n"
|
"authorization: <redacted>\n"
|
||||||
"content-length: 0\n"
|
"content-length: 0\n"
|
||||||
"host: " S3_TEST_HOST "\n"
|
"host: bucket." S3_TEST_HOST "\n"
|
||||||
"x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n"
|
"x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n"
|
||||||
"x-amz-date: <redacted>\n"
|
"x-amz-date: <redacted>\n"
|
||||||
"*** Response Headers ***:\n"
|
"*** Response Headers ***:\n"
|
||||||
@ -878,7 +901,7 @@ testRun(void)
|
|||||||
"*** Request Headers ***:\n"
|
"*** Request Headers ***:\n"
|
||||||
"authorization: <redacted>\n"
|
"authorization: <redacted>\n"
|
||||||
"content-length: 0\n"
|
"content-length: 0\n"
|
||||||
"host: " S3_TEST_HOST "\n"
|
"host: bucket." S3_TEST_HOST "\n"
|
||||||
"x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n"
|
"x-amz-content-sha256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855\n"
|
||||||
"x-amz-date: <redacted>\n"
|
"x-amz-date: <redacted>\n"
|
||||||
"*** Response Headers ***:\n"
|
"*** Response Headers ***:\n"
|
||||||
@ -900,6 +923,11 @@ testRun(void)
|
|||||||
|
|
||||||
// storageDriverPathRemove()
|
// storageDriverPathRemove()
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
// Switch to path-style URIs
|
||||||
|
s3 = storageS3New(
|
||||||
|
path, true, NULL, bucket, endPoint, storageS3UriStylePath, region, accessKey, secretAccessKey, NULL, 16, 2, host, port,
|
||||||
|
1000, testContainer(), NULL, NULL);
|
||||||
|
|
||||||
TEST_ERROR(
|
TEST_ERROR(
|
||||||
storagePathRemoveP(s3, strNew("/")), AssertError,
|
storagePathRemoveP(s3, strNew("/")), AssertError,
|
||||||
"assertion 'param.recurse || storageFeature(this, storageFeaturePath)' failed");
|
"assertion 'param.recurse || storageFeature(this, storageFeaturePath)' failed");
|
||||||
|
Reference in New Issue
Block a user