Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pass x-amz-meta-* headers to the getPresignedUrl api call #502

Closed
fantapop opened this issue Feb 9, 2015 · 15 comments
Closed

pass x-amz-meta-* headers to the getPresignedUrl api call #502

fantapop opened this issue Feb 9, 2015 · 15 comments
Labels
guidance Question that needs advice or information.

Comments

@fantapop
Copy link

fantapop commented Feb 9, 2015

Is there a way of passing custom headers to getPresignedUrl? I'd like to pass an id field along with the presigned url so that I can correlate requests to the url with the S3 logs. I can do this using custom signing code to add the addtional header into the toSign string but the aws-sdk doesn't seem to like this.

@lsegal
Copy link
Contributor

lsegal commented Feb 9, 2015

The Metadata parameter allows you to pass x-amz-meta headers to a request but note that in addition to signing with these parameters, the client that actually sends the request will have to pass the same values as actual headers. In other words both the URL generator code and client code need to know the headers being sent.

@fantapop
Copy link
Author

fantapop commented Feb 9, 2015

Yes, that is my understanding. In this case, I'm sending the signed url to
the browser as a redirect so I can add the additional parameter as a query
string item.

On Monday, February 9, 2015, Loren Segal notifications@github.com wrote:

The Metadata parameter allows you to pass x-amz-meta headers to a request
but note that in addition to signing with these parameters, the client that
actually sends the request will have to pass the same values as actual
headers. In other words both the URL generator code and client code need to
know the headers being sent.


Reply to this email directly or view it on GitHub
#502 (comment).

@fantapop
Copy link
Author

I tried passing Metadata to the getSignedUrl function but it throws an exception:

uncaughtException: Unexpected key 'Metadata' found in params

@lsegal
Copy link
Contributor

lsegal commented Feb 11, 2015

I'm not sure which operation you are calling. You can see an example of the Metadata parameter in the S3.putObject() documentation, but Metadata is not available in all operations. If you're using getObject, for instance, you cannot pass in metadata. See the docs for the relevant operation you are trying to sign for.

@fantapop
Copy link
Author

S3 allows an x-amz-meta-* query param to be passed along with a GET request to a signed url as long as this parameter is signed with the request. What I'd like to do is use this mechanism to insert an id field that someone following the signed url cannot remove.

The S3 docs suggest using an x-* query parameter to accomplish this (http://docs.aws.amazon.com/AmazonS3/latest/dev/LogFormat.html#LogFormatCustom). The drawback of doing this is that if the parameter is not in the signature, it can be removed.

This is possible with other S3 api implementations. It doesn't seem like its currently possible with the aws-sdk, can you verify this is the case? If not, is it something that would be considered for addition?

@AdityaManohar
Copy link
Contributor

S3 allows an x-amz-meta-* query param to be passed along with a GET request to a signed url

From the S3 Object and Metadata documentation

You provide this optional information as a name-value pair when you send a PUT or POST request to create the object

This clarifies what @lsegal said about only being able to pass metadata with S3.putObject. When you are generating a pre-signed URL the metadata will be added as a query string. If you remove it you will get a signature error.

I hope this helps clarify things!

@lsegal
Copy link
Contributor

lsegal commented Feb 12, 2015

@fantapop there is no explicit support for adding arbitrary query strings to a pre-signed URL in the JS SDK, but you can use the request event cycle to add any query string values you want directly to the path. The following will ensure that your generated URL will contain x-foo=value and it cannot be removed.

var s3 = new AWS.S3({region: 'my-bucket-region', signatureVersion: 'v4'});
var req = s3.getObject({Bucket: 'mybucket', Key: 'mykey'});
req.on('build', function() { req.httpRequest.path += '?x-foo=value'; });
console.log(req.presign());

Note that you must use v4 signing when generating this URL as our S3 signer does not enforce the query string params in this way.

@fantapop
Copy link
Author

sweet. Thats what I'm looking for. Thank you.

On Thu, Feb 12, 2015 at 1:13 AM, Loren Segal notifications@github.com
wrote:

@fantapop https://github.com/fantapop there is no explicit support
for adding arbitrary query strings to a pre-signed URL in the JS SDK, but
you can use the request event cycle to add any query string values you want
directly to the path. The following will ensure that your generated URL
will contain x-foo=value and it cannot be removed.

var s3 = new AWS.S3({region: 'my-bucket-region', signatureVersion: 'v4'});var req = s3.getObject({Bucket: 'mybucket', Key: 'mykey'});
req.on('build', function() { req.httpRequest.path += '?x-foo=value'; });console.log(req.presign());

Note that you must use v4 signing when generating this URL as our S3
signer does not enforce the query string params in this way.


Reply to this email directly or view it on GitHub
#502 (comment).

@fantapop
Copy link
Author

this worked, thanks for the work-around.

On Thu, Feb 12, 2015 at 10:17 AM, Christopher Fitzner <
chrisfitzner@gmail.com> wrote:

sweet. Thats what I'm looking for. Thank you.

On Thu, Feb 12, 2015 at 1:13 AM, Loren Segal notifications@github.com
wrote:

@fantapop https://github.com/fantapop there is no explicit support
for adding arbitrary query strings to a pre-signed URL in the JS SDK, but
you can use the request event cycle to add any query string values you want
directly to the path. The following will ensure that your generated URL
will contain x-foo=value and it cannot be removed.

var s3 = new AWS.S3({region: 'my-bucket-region', signatureVersion: 'v4'});var req = s3.getObject({Bucket: 'mybucket', Key: 'mykey'});
req.on('build', function() { req.httpRequest.path += '?x-foo=value'; });console.log(req.presign());

Note that you must use v4 signing when generating this URL as our S3
signer does not enforce the query string params in this way.


Reply to this email directly or view it on GitHub
#502 (comment).

@AdityaManohar
Copy link
Contributor

@fantapop
I'm closing this issue since you seem to have it working. Feel free to reopen this issue or another issue if you have any other questions.

@akiradeveloper
Copy link

Not clear for me.

When you are generating a pre-signed URL the metadata will be added as a query string.

I wonder which part of the AWS document describe this.

A part of code from RestUtils in AWS SDK java does this but I couldn't found certain evidence in documents.

        // Any parameters that are prefixed with "x-amz-" need to be included
        // in the headers section of the canonical string to sign
        for (Map.Entry<String, String> parameter: request.getParameters().entrySet()) {
            if (parameter.getKey().startsWith("x-amz-")) {
                interestingHeaders.put(parameter.getKey(), parameter.getValue());
            }
        }

x-amz- query parameters is undocumented stuff?

@honey303
Copy link

how can we change the metadata of an s3 object from Content-Type - 'video/mp4' to 'application/zip' using a lambda function?

` var params = {
Bucket: 'videoapp-testbucket',
CopySource: 'videoapp-targetbucket/' + filename,
Key: key,
ACL: 'authenticated-read',
Metadata: {
'Content-Type': 'application/zip'
}
};
s3.copyObject(params, function(err, data) {
if (err) {
console.log(err, err.stack);
console.log(key);

  } // an error occurred
  else     console.log(data);           // successful response
});`

this is how i am trying to do it. Can someone please help? Thanks

@chrisradek
Copy link
Contributor

@honey303
For Content-Type, you specify the top-level ContentType parameter:
http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#copyObject-property

Note that ContentType does not contain a hyphen, and is not in the Metadata.
If you still have problems with this, please open a new issue since this issue is regarding presigned urls.

@honey303
Copy link

honey303 commented Mar 10, 2017

@chrisradek Thanks for your help :) Turns out my code was indeed right, except that I had to add
MetadataDirective: 'REPLACE' - to make it work.

@srchase srchase added the guidance Question that needs advice or information. label Dec 24, 2018
@lock
Copy link

lock bot commented Sep 29, 2019

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread.

@lock lock bot locked as resolved and limited conversation to collaborators Sep 29, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
guidance Question that needs advice or information.
Projects
None yet
Development

No branches or pull requests

7 participants