Skip to content

Instantly share code, notes, and snippets.

@bahostetterlewis
Last active November 21, 2019 01:00
Show Gist options
  • Save bahostetterlewis/c84a08cd1f8dad74853c to your computer and use it in GitHub Desktop.
Save bahostetterlewis/c84a08cd1f8dad74853c to your computer and use it in GitHub Desktop.
How to manually upload files to rackspace w/ Python 3

Uploading Files to Rackspace Cloud Files Using

Problem

Rackspace's officially supported python sdk is Pyrax - unfortunately it doesn't work with python3. There is the alternative apache module called libcloud but that is tricky to get working on windows.

Solution

Rackspace has a publically available api that can be used to manually send requests to your cloud files. All it requires is an existing container, a username, and an api key

To do this we will issue an initial request to rackspace with our credentials. Rackspace will then issue us a temporary token, and a list of services and urls to communicate with. We will pull our token and the cloudfiles services from this response and grab the url for our containers region (ie: DFW). Combine that url with our container and desired filename and we have the url we will upload our file to.

Setup the headers with our temporary token and content type and open the file we wish to send.

There are two important things to note at this point

  1. We need to open in 'rb' mode because we are sending this file (opening in unicode mode seemed to always fail from my testing)
  2. We opened the file without reading it, but requests will handle sending the file data for us anyway

That's it!

This is the basic upload process without using pyrax, no frills here though so use with caution!

import json
import requests
def get_rackspace_data():
payload = {
"auth": {
"RAX-KSKEY:apiKeyCredentials": {
# EDIT THESE VALUES
"username": "YOUR USERNAME",
"apiKey": "YOUR API KEY"
}
}
}
headers = {"Content-Type": "application/json"}
r = requests.post("https://identity.api.rackspacecloud.com/v2.0/tokens", data=json.dumps(payload), headers=headers)
# all results are nested under the access key
return r.json()['access']
def find_token(data):
return data['token']['id']
def cloudfiles_service_data(data):
for service in data['serviceCatalog']:
if service['name'] == 'cloudFiles':
return service
raise KeyError('No Valid Cloud Files Service')
def find_endpoint(data, region):
try:
cloudfiles = cloudfiles_service_data(data)
except KeyError as e:
raise KeyError("No Valid Endpoint") from e
for endpoint_data in cloudfiles["endpoints"]:
if endpoint_data['region'] == region:
return endpoint_data['publicURL']
raise KeyError('No Valid Endpoint')
data = get_rackspace_data()
token = find_token(data)
endpoint = find_endpoint(data, 'DFW')
# EDIT THESE VALUES
put_url = endpoint + '/{YOUR CONTAINER NAME}/{YOUR FILE NAME}.xml'
headers = {"X-Auth-Token": token, 'Content-Type': 'application/xml'}
# EDIT THESE VALUES
with open('somefile.xml', 'rb') as f:
final = requests.put(put_url, headers=headers, data=f)
print(final)
@thijstriemstra
Copy link

thanks! still works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment