There’s a previous AndyPi article on accessing the TfL (Transport for London) bus API using python, and displaying the result on an LCD. Although its a fun project, almost everything these days ends up having a web browser as the output, seen as you can get it from any device (almost) anywhere. So this tutorial is accessing the same API and showing the output on a web page.

Of course, you can just point any browser to an API such as this:

https://api.tfl.gov.uk/StopPoint/490009109HH/arrivals

But the response you get is usually in JSON format, which is easy for a computer to understand but it is not particularly pretty or easy to get the information we want:

[{"$type":"Tfl.Api.Presentation.Entities.Prediction, Tfl.Api.Presentation.Entities","id":"1332570605","operationType":1,"vehicleId":"LX12DEU","naptanId":"490009109HH","stationName":"Lewisham Hospital","lineId":"136","lineName":"136","platformName":"HH","direction":"outbound","bearing":"9","destinationNaptanId":"","destinationName":"Elephant & Castle","timestamp":"2016-05-23T10:24:35.326Z","timeToStation":1411,"currentLocation":"","towards":"Blackheath, Deptford or New Cross","expectedArrival":"2016-05-23T10:48:07Z","timeToLive":"2016-05-23T10:48:37Z","modeName":"bus"},

Why JavaScript and not Python?

What we want to do instead is get the this information, but format it nicely in a web page. I could use the python code I wrote to display the information on an LCD, but add the Flask web framework to output the result as an web page. However, this would mean setting up a server to run Nginx, Flask etc … and there is another option – JavaScript. Sometimes it is useful to be able to program your website to do something dynamically (i.e. using programming logic) without needing to interact with a server. In this case, it means we can host a page statically using AWS’s S3, which serves static content only. All modern browsers have (only) JavaScript installed as standard – it is the front-end programming language of the web, we can’t really use other languages such as python in this context.

 

Javascript code

See code on github – you can simply download the html and open it in any browser.
https://github.com/andy-pi/apidata_to_web

You’ll need to enter the Naptan_Atco of the bus stop – there is an example given, but to look from other stations, search this file, and you need the code number from the 3rd column in the CSV, labelled “Naptan_Atco”.

The key lines of code are the one that calls the API:

// Set the URL, including the variable Naptan_Atco
var api_url = "https://api.tfl.gov.uk/StopPoint/" + document.getElementById('api_url').value + "/arrivals";
// make a GET request using the URL
xhttp.open("GET",api_url, true);

What’s the benefit of making a web app accessible via and API?

One of the great things about using web APIs means that is means multiple platforms can use the same API, and it only needs to be written once. In our case, for the London Buses, the API is written once, but it can be accessed on any platform – javascript webpage, a python script on a Raspberry Pi, or from a mobile phone app. Or in this case, we can add some extra functionality to a static website, without needing a full server and its associated costs. You can even just save the page to your local disk and run it from there.

 

Limitations and security

This works nicely for publicly accessible APIs such as the London bus times. However, if we were to write an application entirely accessible using a web API that requires user accounts, then we’d come up against a problem.

Web API’s are stateless, which means each individual request has no relationship with any others, so if authentication is required, we’d need to send this information with every request. Actually, most APIs require authentication either because you need to pay to use them, or you are interacting with data that is private to you. Let’s say the TfL API costs us money each time we make a request, and we have an account with them and an API key/password. This is easily be possible, but the API keys would then be stored in the client-side code, so that with each request to the API it could authenticate. The javascript would probably look a little bit like this:

// API Key
var TFL_API_KEY="mypassword"
// Set the URL, including the variable Naptan_Atco
var api_url = "https://api.tfl.gov.uk/StopPoint/" + document.getElementById('api_url').value + "/arrivals" + "password=" + TFL_API_KEY;
// make a GET request using the URL
xhttp.open("GET",api_url, true);

So this is totally insecure – anyone could get your API key and start using your account and spending your money. In this case, we’d need to have an app running on a server, with user accounts so that only those we wanted could use the service.

 

Real Use Case

The main reason I needed to work out how to do this was for a client, who needed a way for their users to enter their email address on a webpage and receive their account details back by email. I built a python-flask based API on a standard webserver, but the client wanted the front end to remain served statically from AWS S3, which means no dynamic content. In this case, there is no authentication required, it is just passing an email address to an API endpoint, so calling this API using Javascript from a static page was perfect!