⛅ Making API Calls From a Cloudflare Worker (lesson 3)

Search for a command to run...

No comments yet. Be the first to comment.
Turn any website into an Installable App How I make web apps that install to the home screen (Android and iOS), launch full-screen (not in-browser), work offline, and offer a first-class in-app Instal

Type Narrowing allows the IDE (development environment) to narrow down the object type, from a union type, to a more specific type. Bullsh*t Example In this bullsh*t example, value is the union type string | number, meaning it can either be a string ...
There is still a lot of work to be done, but I finally have something "playable" 🔥 I would describe it as a mashup of Mine Sweeper and a rogue-like dungeon crawler RPG. That's right! The first playable demo is up! The game is still in active develo...

I recently added some dialog options for my indie game, Dungeon Sweeper: A Knights Adventure and wanted to create a TypeWriter effect for the dialog text. This technique works well for monospaced fonts and may not work for variable-width fonts. Fail...

TL;DR: I discuss adding intuitive features, dealing with Phaser quirks such as a tween memory leak and scaling issues, managing screen size, and creating an executable for a demo. I express my struggle with the less enjoyable parts of game developmen...

Being able to retrieve data from an API or Database is a common task for a Cloudflare Worker. Without some type of API call to a database or service, your site would be the same as a static site. It's the API call that will make your site dynamic.
Cloudflare Workers run on the Edge (server side), so the resulting output will be server rendered. making your page SEO (Search Engine Optimization) friendly.
In case you haven't been following along with the previous lessons (you don't have to), you can start here:
# continue where we left off
$ git clone https://github.com/joelnet/cloudflare-worker-website.git
$ cd cloudflare-worker-website
$ git checkout ae0c7dcf533099832bc313099425d270e326148e
$ npm ci
I would recommend against using a library like axios and instead use the native fetch. The reason is your Worker has 1 MB limit. Adding any new libraries should be carefully considered due to this hard limit.
Cloudflare Worker code runs server side. Thus you don't have to worry about browser incompatibility with libraries.
Test other clients you may be considering. Since Workers do not run Node.js, some npm modules may not work. For example, any library that requires node-gyp will not run in a Worker.
If a library will run in the browser, it should also run in a Cloudflare worker.
src/api.jsI like to create an src/api.js file to hold all my API calls. This way if an underlying change needs to happen, it can happen in one file. This file will also simplifies the source for files using the API.
For this demo, I will be making two API calls, fetchAllPeople and fetchPerson.
const getJson = async url => {
const response = await fetch(url)
if (!response.ok) {
throw new Error('Unexpected HTTP Response')
}
return await response.json()
}
export const fetchAllPeople = () =>
getJson('https://swapi.dev/api/people')
export const fetchPerson = id =>
getJson(`https://swapi.dev/api/people/${id}`)
If you are curious about why I create the getJson abstraction this way and want to know more, I have created a video on this topic.
src/pages/allPeople.jsThis page will display a list of all available people. The SWAPI API features pagination, which we'll ignore to keep this demo short. Feel free to implement the pagination on your own 👍
import { fetchAllPeople } from '../api'
import { htmlResponse } from '../lib/responses'
const personToLi = (person, index) =>
`<li><a href="/people/${index + 1}">${person.name}</a></li>`
const allPeople = async () => {
const { results } = await fetchAllPeople()
const persons = results.map(personToLi)
const html = `<ul>${persons.join('')}</ul>`
return htmlResponse(html)
}
export default allPeople
src/pages/person.jsThis page will display the individual person. There are more sophisticated ways of pulling the id from the URL, but I'm just going to use substring for simplicity of this demo.
import { fetchPerson } from '../api'
import { objectToTable } from '../lib/objectToTable'
import { htmlResponse } from '../lib/responses'
const person = async request => {
const url = new URL(request.url)
const id = url.pathname.substring(8)
const response = await fetchPerson(id)
const table = objectToTable(response)
const html = `${table}
<a href="/people"><< back</a>
`
return htmlResponse(html)
}
export default person
Create src/lib/objectToTable.js. This will convert an Object to an HTML table for this demo.
I don't care for looking at raw JSON, even if it's just a demo. So I'm gonna pretty it up a bit.
export const objectToTable = obj => {
const rows = Object.entries(obj)
.map(([key, value]) => `<tr><th>${key}</th><td>${value}</td></tr>`)
.join('')
return `<table>${rows}</table>`
}
Now I need to add the routes to the src/index.js Router.
Import the new pages at the top of src/index.js:
import allPeople from "./pages/allPeople";
import person from "./pages/person";
Then add the router code for those pages:
router.get('/people/?', () => allPeople(request))
router.get('/people/.+', () => person(request))
$ npm run preview
After the browser opens, navigate to /people.

Click on any person to view the /people/{id} route.

View the source to confirm the application is rendered on the server.
<ul>
<li><a href="/people/1">Luke Skywalker</a></li>
<li><a href="/people/2">C-3PO</a></li>
<li><a href="/people/3">R2-D2</a></li>
<li><a href="/people/4">Darth Vader</a></li>
<li><a href="/people/5">Leia Organa</a></li>
<li><a href="/people/6">Owen Lars</a></li>
<li><a href="/people/7">Beru Whitesun lars</a></li>
<li><a href="/people/8">R5-D4</a></li>
<li><a href="/people/9">Biggs Darklighter</a></li>
<li><a href="/people/10">Obi-Wan Kenobi</a></li>
</ul>
Pulling data from an API and rendering the content from the server side is key for application that are require SEO. Cloudflare Workers let's us do this with very little code.
Browse the repository at this point in history.
Subscribe to my Newsletter to continue learning about Cloudflare Workers!
Cheers 🍻