3

I've hosted a small PHP environment on AWS ElasticBeanstalk. The static content (.css, .js, .jpg files etc) is inaccessible directly from ElasticBeanstalk, and must come from another source. I've elected S3 to be that source, but I have a few issues.

Suppose:

  • My website on EB is <website_name>.<location>.elasticbeanstalk.com.
  • My S3 bucket is s3.<location>.amazonaws.com/elasticbeanstalk-<location>-<id>. The bucket and all its subfolders are public.
  • Inside this bucket, I have the folders /WebsiteData/images/, /WebsiteData/css/, /WebsiteData/js/etc, which store the relevant files.

Now, I'm having trouble loading the static files when I visit <website_name>.<location>.elasticbeanstalk.com/homepage.php.

I don't want to hard-code the link to my S3 bucket for every static file I reference (because I may move it to another CDN later). For example, I prefer to have my link to an image file as /WebsiteData/images/img1.jpg, rather than s3.<location>.amazonaws.com/elasticbeanstalk-<location>-<id>/WebsiteData/images/img1.jpg

Things I have tried:

  1. I initially tried mod_rewrite in my .htaccess; this does not load the images/static content when I visit <website_name>.<location>.elasticbeanstalk.com/homepage.php, it only redirects to the S3 bucket when I click on the link <website_name>.<location>.elasticbeanstalk.com/WebsiteData/images/img1.jpg. I guess this makes sense since it is a redirect on the server.

  2. Next, I tried a PHP solution: <img src="<?php echo $aws_s3_folder; ?>/WebsiteData/images/img1.jpg" alt="My image"/>. This works, obviously.

  3. Finally, I wrote a small Javascript script which just changes all links from /WebsiteData/, to s3.<location>.amazonaws.com/elasticbeanstalk-<location>-<id>/WebsiteData/. This works as well, but I get some warnings.

The last two methods do work (I can see the JS/CSS/images when I visit homepage.php), but it feels like an ugly hack to me. What's the correct way to fetch static content in this situation? Would AJAX or CloudFlare be the right way to go?

1
  1. I initially tried mod_rewrite in my .htaccess ...

You could perhaps use mod_rewrite together with mod_proxy to create a reverse proxy to your CDN. This has the advantage of hiding the location of your CDN. For example, in your HTML, reference your assets in a "virtual" subdirectory (or subdomain), eg. /cdn.

src="/cdn/WebsiteData/images/img1.jpg"

(A subdomain might be preferable in order to get around any per-domain request limit imposed by the browser?)

Then use mod_rewrite/mod_proxy to proxy all requests for /cdn/.... to your CDN (S3):

RewriteRule ^cdn/(.*) https://s3.<location>.amazonaws.com/elasticbeanstalk-<location>-<id>/$1 [P]

That is, assuming your server has the necessary modules loaded (mod_proxy, mod_proxy_http) and S3 permits proxied requests.

  1. Next, I tried a PHP solution: <img src="<?php echo $aws_s3_folder; ?>/WebsiteData/images/img1.jpg" alt="My image"/>. This works, obviously.

This doesn't feel like an "ugly hack" to me. (Unless maybe this is the only thing you are using PHP for?) In fact, this would probably be my preferred solution I think. I would, however, use the short echo format: <?=$aws_s3_folder?>

  1. I wrote a small Javascript script which just changes all links...

However, the JavaScript solution does feel like a hack. And could certainly result in some client-side errors (404s) before the code runs.

BASE Element

Another solution might be to use relative paths to all your S3 assets and include the base element in the head section of your HTML to tell the browser where these assets are. For example:

src="WebsiteData/images/img1.jpg"

Then, in your base tag (NB: Include the trailing slash on this path):

<base href="<?=$aws_s3_folder?>/">
  • Hi, thanks for the response. The <base> element seems to be working, but the proxy is not set up in S3 by default. Any idea how to do this (without inadvertently breaking something else). – Abhishek Divekar Jan 7 '17 at 5:52
  • For a reverse proxy it's AWS Elastic Beanstalk (the source) that would really need the proxy capability configured. However, the target (S3) could potentially reject the request. But I'm not sure exactly how this would be configured. You might also be able to code something yourself using CURL (ie. rewrite these URLs to your CURL script that makes the necessary request and returns the response to the client.) - however, I wonder what extra load this would place on the server and whether it might slow things down a bit? – MrWhite Jan 7 '17 at 11:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.