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

Add key prefix as a configuation option #103

Open
bubenkoff opened this issue Oct 27, 2016 · 8 comments
Open

Add key prefix as a configuation option #103

bubenkoff opened this issue Oct 27, 2016 · 8 comments
Labels

Comments

@bubenkoff
Copy link

It's not uncommon to have single s3 bucket for multiple applications, connected to a single cloudfront domain, separated just by a key prefix, example:

static.example.com/app1/assets...
static.example.com/app2/assets...

ATM there's no easy way to implement this with this very nice package
thanks!

@Mulkave
Copy link
Member

Mulkave commented Oct 30, 2016

@bubenkoff thanks for raising that point. Can you please suggest a suitable solution? I haven't faced that issue before so any details you can share are much appreciated!

@thtg88
Copy link

thtg88 commented Nov 2, 2016

I'm actually facing the same sort of problem on an S3/CloudFront environment as described by @bubenkoff , where I have just one bucket, hosting multiple apps' assets. At the moment I use just one app on the CDN, so I'm good having a public folder on the bucket's root directory, but this could potentially display the package issue if I decide to use the package on the other apps since, in a Laravel environment, you most likely always push content from the public directory, potentially overwriting every apps assets.
A possible solution could be having a config variable in config/cdn.php containing the additional folder/path (defaulting to an empty string) e.g. 'app-folder' => '',, which will then get pushed to the AwsS3Provider'sdefault array.
Then, considering the way you upload the assets (get all local's, compare with server's, remove the not modified from the array), and you are using the AWS PHP SDK putObject method, where the "destination" path is held in the Key key, we will need to prefix the Key key wth app-folder if the string is not empty and the file is brand new (not available on server).
Considering this there will most likely be a bit of refactoring in the AwsS3Provider's upload and getFilesAlreadyOnBucket methods as follows:

  1. In the getFilesAlreadyOnBucket method add a line after 401: $item->IsModified = true; this way we know if the file has actually been modified instead of just created locally;
  2. In the upload method change line 207 to: 'Key' => ($this->default['providers']['aws']['s3']['app-folder'] !== '' && $file->IsModified !== null ? str_replace('\\', '/', $this->default['providers']['aws']['s3']['app-folder'].'/'.$file->getPathName()), : str_replace('\\', '/', $file->getPathName()). This way we'll add app-folder as a prefix to the the actual local app path, so the file gets uploaded where we want. You might not want to expose the variable itself though, and access it from a getter e.g. getAppFolder, so you could apply string transformation on it, as necessary (trim('/') off the top of my head).

I fear though that these edits could "break stuff" (very technical term), as you are most likely not allowed to add a custom key to $item at point 1, but is roughly my idea.

Apolgies if I've written something outrageous or haven't formatted the answer properly, but I'm very inexperienced with GitHub's issue tracker.
What do you think?

@Mulkave
Copy link
Member

Mulkave commented Nov 16, 2016

@thtg88 Thanks for the details. I'm just afraid that would require too much config in the simple case where you only have one bucket per app. I always lean towards simplicity when it comes to config.

I was thinking whether Bucket in config can be bucket-name/app1, that should work IMO. Can you please give it a try?

@thtg88
Copy link

thtg88 commented Nov 16, 2016

@Mulkave Forgot to mention I tried that, unfortunately it throws an exception as the forward-slash '/' character gets urlencoded. I'm not at my PC right now but I can provide the Exception details if needed.
thanks for your reply anyway

@Mulkave
Copy link
Member

Mulkave commented Nov 16, 2016

@thtg88 sure some more details on the exception would help. I'm also not able to try that atm.

@thtg88
Copy link

thtg88 commented Nov 19, 2016

Hi @Mulkave , apologies for the delay. You can find the exception message below:

[2016-11-19 14:38:49] local.ERROR: exception 'Aws\S3\Exception\S3Exception' with message 'Error executing "ListObjects" on "https://s3.amazonaws.com/the-s3-bucket-name%2Fthe-application-assets-subfolder-name?encoding-type=url"; AWS HTTP error: Client error: `GET https://s3.amazonaws.com/the-s3-bucket-name%2Fthe-application-assets-subfolder-name?encoding-type=url` resulted in a `403 Forbidden` response:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calcul (truncated...)
 SignatureDoesNotMatch (client): The request signature we calculated does not match the signature you provided. Check your key and signing method. - <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calculated does not match the signature you provided. Check your key and signing method.</Message><AWSAccessKeyId>AKIAIY7T2HVCCV34ZZVA</AWSAccessKeyId><StringToSign>AWS4-HMAC-SHA256
20161119T143848Z
20161119/us-east-1/s3/aws4_request
thestringtosign-omitted</StringToSign><SignatureProvided>thsignatureprovided-omitted</SignatureProvided><StringToSignBytes>thestringtosignbytes-omitted</StringToSignBytes><CanonicalRequest>GET
/the-s3-bucket-name/the-application-assets-subfolder-name
encoding-type=url
aws-sdk-invocation-id:60f4df8826b54f3ef8e7a99eb6361085
aws-sdk-retry:0/0
host:s3.amazonaws.com
x-amz-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-amz-date:20161119T143848Z

aws-sdk-invocation-id;aws-sdk-retry;host;x-amz-content-sha256;x-amz-date
thecanonicalrequest-omitted</CanonicalRequest><CanonicalRequestBytes>thecanonicalrequestbytes-omitted</CanonicalRequestBytes><RequestId>032C69243B67DFE1</RequestId><HostId>thehostid-omitted</HostId></Error>'

exception 'GuzzleHttp\Exception\ClientException' with message 'Client error: `GET https://s3.amazonaws.com/the-s3-bucket-name%2Fthe-application-assets-subfolder-name?encoding-type=url` resulted in a `403 Forbidden` response:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>SignatureDoesNotMatch</Code><Message>The request signature we calcul (truncated...)
' in C:\Application\vendor\guzzlehttp\guzzle\src\Exception\RequestException.php:111

Should you need any other details, please let me know.
Thanks!

@maximkou
Copy link

@Mulkave, Very actual problem! Maybe I propose PR for this?

@linchpinstudios
Copy link

I'm currently running into this issue. It would be good to have this feature available. The main reason is we have different branches being staged that need different CDN assets.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants