Imagine there’s a PythonAnywhere user, homer8bc
, with poetic
inclinations. He wants to serve his newest poem (he believes it’s quite
epic) as a static text page. He’s old school — he doesn’t believe in HTML,
and as for CSS? Forget it! His friend, S. Yodos, lives in Cyme, while
homer8bc
resides on Ios island, so in-person communication is difficult…
After uploading the first lines of his masterpiece to his account,
homer8bc
follows the usual
steps. He
goes to the Web page, adds a new web app using the manual config option,
and sets the static files mapping from /story.txt
to
/home/homer8bc/mysite/story.txt
. Then, he reloads the web app.
Feeling quite pleased with himself, homer8bc
sends the link to
https://homer8bc.pythonanywhere.com/story.txt
to his friend. To his surprise, S. Yodos replies, baffled. He explains that
he was up late last night writing tutorials for peasants, and his tired
eyes must be playing tricks on him because the “great poem” looks more like
worms wriggling in his garden:
That’s certainly not what our poet had in mind! But, determined as ever,
homer8bc
doesn’t give up. After searching through our
documentation, he discovers the
solution:
using PythonAnywhere’s API to add static headers to the requests for his
poem to specify that the text should be rendered as UTF-8!
He first goes to the Account page and clicks the “API Token” tab to create
an API token. Then, for the sake of clarity, he adds another static file
mapping — from /story-with-headers.txt
to the same story.txt
file:
Next, homer8bc
starts a fresh Python console (so that the
API_TOKEN
environment variable is available) and runs the following code
(Note: you’ll need to adjust some variables to match your setup, if you
want to follow in his footsteps!):
import os
import requests
username = "homer8bc" # use your username
api_token = os.getenv("API_TOKEN")
host = "www.pythonanywhere.com" # on EU use "eu.pythonanywhere.com"
domain = f"{username}.pythonanywhere.com" # on EU use f"{username}.eu.pythonanywhere.com"
static_url = "/story-with-headers.txt" # use static url set before
authorization_headers = {"Authorization": f"Token {api_token}"}
api_endpoint = f"https://{host}/api/v0/user/{username}/webapps/{domain}/static_headers/"
response = requests.post(
url=api_endpoint,
headers=authorization_headers,
data={"url": static_url, "name": "Content-Type", "value": "text/plain; charset=utf-8"}
)
This code grabs api_token
from the environment and sends a POST
request
to the /static_headers/
API endpoint for homer8bc
’s domain. The key
part is in the data
of the request: the url
specifies the static
URL defined in the web app’s static file mapping, which in this case is
/story-with-headers.txt
. Keep in mind, this is a one-to-one mapping. If the mapping
were, e.g., from /static
to some directory, then all resources in that
directory would get the added header.
The name
field defines the static header name — here, it’s
Content-Type
— and the value
is set to text/plain; charset=utf-8
,
which does the trick.
If everything goes well, the response should return a status code of 201
,
meaning the static header has been successfully added. As a sanity check,
it’s possible to a perform a GET
request to the static_headers
API
endpoint to confirm:
response = requests.get(api_endpoint, headers=authorization_headers)
print(response.json())
One should see something like this:
[{'id': 999,
'url': '/story-with-headers.txt',
'name': 'Content-Type',
'value': 'text/plain; charset=utf-8'}]
Seeing that the response matches what he intended, homer8bc
reloads the
web app using the button on the Web page. Finally, when he visits
https://homer8bc.pythonanywhere.com/story-with-headers.txt, the first verses of his poem proudly
appear as intended:
Before sending the link to S. Yodos, homer8bc
decides to add another
15,689 lines of gore and violence. “Wrath wasn’t such a bad topic after
all,” he murmurs to himself. “Worms, you mumble? I’ll give you WAR, then!
And ten years of it!” — and the rest is
history…