Creating URL Redirects with Boto3

Even though most of my back-end development is with C#, I still find Python to be a great tool to work with AWS. I highly recommend Jupyter Notebooks and the AWS Boto3 SDK.

When I first started learning the AWS toolset, I began by using the Management Console. While this is great for some operations, being able to add and maintain resources programmatically makes Dev Ops much more comfortable and more repeatable. Also, using Jupyter notebooks allows you to connect documentation to code, which is excellent when working on a team.

I am assuming you have Anaconda's distribution of Python, and the Boto 3 AWS Python SDK installed.

Creating a bucket is easy.

import boto3
s3 = boto3.resource('s3')
s3.create_bucket(Bucket='redirect-22992299', 
                 CreateBucketConfiguration={ 'LocationConstraint': 'us-east-2'})

The 'Resource' we create here represents the higher level interface to AWS. Here we are creating a new S3 Bucket. Notice that the Bucket name is unique across all users, so you will need to pick a unique identifier here.

Next we will allow the public to read our S3 bucket.

bucket.Acl().put(ACL='public-read') 

We still need an actual redirect, and to create our website redirects. For these, we will add two objects to our newly created S3 bucket. We could write an html redirect in the 'Body' statement below, but AWS provides a WebsiteRedirectionLocation, which we will use so that AWS will redirect before ever sending html to the client.

bucket.put_object(Bucket='redirect-22992299', 
                    Key='index.html', 
                    Body='0',
                    WebsiteRedirectLocation='http://www.designingforthefuture.com')
bucket.put_object(Bucket='redirect-22992299', 
                    Key='error.html', 
                    Body='0',
                    WebsiteRedirectLocation='http://www.designingforthefuture.com')

Even though we allowed the public access to our S3 bucket above, by default the objects created in the bucket will be private. To set public access to our two newly created objects we will set the permissions:

object = s3.Bucket('redirect-22992299').Object('index.html')
object.Acl().put(ACL='public-read')

Now we designate our S3 bucket as a website. To do this, you'll notice we can't use our original s3 object. We create a new object for the lower-level 'client' interface to AWS. These map closer to the AWS services, but are lower-level.

website_configuration = {
    'ErrorDocument': {'Key': 'error.html'},
    'IndexDocument': {'Suffix': 'index.html'},
}
s3client = boto3.client('s3')
s3client.put_bucket_website(
    Bucket='redirect-22992299',
    WebsiteConfiguration=website_configuration
)

Done! With this bucket set, I added a A alias in Route 53 to use the redirect. You can also set these when your S3 object has expired and you want users to be redirected to your current site.

See the complete Jupyter Notebook for full details: https://github.com/rinckd/designingforthefuture-blog/blob/master/notebooks/AWS/01_S3_buckets/01_S3_Buckets.ipynb

Comments

Posting Jupyter Notebooks to Blogs

It is nice to be able to publish Jupyter notebooks to straight to Github. I love looking through Fran├žois Chollet's work with Jupyter Notebooks and Keras. For example, this page: https://github.com/fchollet/deep-learning-with-python-notebooks/blob/master/5.4-visualizing-what-convnets-learn.ipynb

At the same time, in a blog it's nice to be able to talk about smaller snippets of code.
The best way to do this is to use the nbconvert function that is installed with jupyter notebooks.

You can convert a notebook with this command line snippet:

jupyter nbconvert --to html --template basic .\protobufs.ipynb

the --template basic argument will strip the html headers off your file, which you will have to do manually if you just use the File->Save functionality inside a Jupyter notebook session.

Grab the generated .html file and add something like this to the top to style things to your liking:

<style type="text/css">
.highlight{background: #f8f8f8; overflow:auto;width:auto;border:solid gray;border-width:.1em .1em .1em .1em;padding:0em .5em;border-radius: 4px;}
.k{color: #338822; font-weight: bold;}
.kn{color: #338822; font-weight: bold;}
.mi{color: #000000;}
.o{color: #000000;}
.ow{color: #BA22FF;  font-weight: bold;}
.nb{color: #338822;}
.n{color: #000000;}
.s{color: #cc2222;}
.se{color: #cc2222; font-weight: bold;}
.si{color: #C06688; font-weight: bold;}
.nn{color: #4D00FF; font-weight: bold;}
</style>

Then paste it in to your blog. Simple.

Comments