Learning Outcomes
- outline the problems associated with scaling the backend of a web application
- implenent a serverless web application using Google Cloud Functions
Resources
Lab
Set Up
Fork https://gitlab.com/langarabrian/gcpfunc4. Remove the fork relationship. Make the project private. Clone the project in your Google Cloud Shell environment.
Finish Backend
The backend has a feathers mongoose service books
for managing a collection of books. We are going to deploy to Google Cloud Functions. Feathers comes with a transport for Express which have been for previous assignments. There is no transport for Google Cloud Functions, so we are going to have marshal the incoming requests to invoke the correct Feathers service method.
Change to the gcpfunc4/backend
directory. Run yarn install
.
Set your MONGODBURI
environment variable. Run the backend with the PORT=8080 yarn run startff
command. startff
is a script which runs Functions Framework. The Functions Framework allows you test at Google Cloud Function locally without having to deploy it. Verify that there are no errors in the console. Use Web Preview to preview the application in a new tab. There should just be message that the request is unsupported.
The first thing we need to do is support the creation of new books in the collection.
Rewrite the feathersGCF
function in backend\src\index.ts
as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Set up Google Cloud Functions entry point
export const feathersGCF: HttpFunction = async (req, res) => {
// for CORS
res.set('Access-Control-Allow-Origin', '*');
if ( req.method === 'OPTIONS') {
// Send response to OPTIONS requests for CORS
res.set('Access-Control-Allow-Headers', 'Content-Type');
res.status(204).send('');
} else if ( req.method === 'POST' && req.path === '/books') {
const books = app.service('books');
const result = await books.create( req.body );
res.json( result );
} else {
console.log( 'method: ' + req.method );
console.log( 'path: ' + req.path );
res.send('Unsupported request');
}
};
Because the frontend will be running a domain separate from the Google Cloud Function, we need to configure the function to support cross-origin resource sharing (CORS).
1
res.set('Access-Control-Allow-Origin', '*');
signals that our function will accept CORS requests from any other domain. Before a cross-origin request, browsers will send an OPTIONS
pre-flight request to confirm that the server will accept it. The response to this request has to indicate which headers can be modified in the subsequent request. In our case, we are going to POST
a JSON formatted request so we have to allow the Content-Type
header to be modified to permit that:
1
res.set('Access-Control-Allow-Headers', 'Content-Type');
Then we handle the expected POST /books
request. Any other request is flagged as unsupported.
Because the web preview domain is authenticated, it is not possible to test the function with an actual frontend running in the browser. The best we can do is use curl
to generate an appropriately structured request. Restart the backend and then try the following in another terminal tab (you will have to remove the spaces around “localhost”):
1
curl -H "Content-Type: application/json" -X POST -d '{"isbn":4444,"title":"Smarter Than You Think","pages":321}' http:// localhost :8080/books
Verify that the output contains the information about the new book and check that the document is acutally present in the database.
Stop the backend. Deploy the backend to Google Cloud Functions as follows:
1
gcloud functions deploy feathersGCF --allow-unauthenticated --trigger-http --runtime nodejs12 --set-env-vars MONGODBURI=$MONGODBURI
It will take a few mintues to deploy. When successful, you will see the HTTP endpoint for the function which will look something like:
1
https://your-subdomain-here.cloudfunctions.net/feathersGCF
Test the deployed function as follows:
1
curl -H "Content-Type: application/json" -X POST -d '{"isbn":8888,"title":"Capital","pages":1001}' https://your-subdomain-here.cloudfunctions.net/feathersGCF/books
Set Up the frontend
In another tab, go to the gcpfunc4/frontend
directory. Run yarn install
.
Update frontend/src/feathers.ts
with the base URL of your Google Cloud Function (something like https://your-subdomain-here.cloudfunctions.net/feathersGCF
).
Start the development server for the React frontend (PORT=8080 yarn start
). Preview and test the application. Make sure any added books show up in the MongdoDB as expected.
Assignment
- Modify the Google Cloud Function (GCF) so it displays all the books in the database in the table at the bottom of the page. You will have to add the code to the GCF that will handle a
GET /books
request. - Modify the GCF so that books can be deleted. You will have to add the coded to GCF that will handle a
DELETE /books/:id
request. - Implement CI/CD for the project so that the backend gets deployed to Google Cloud Functions and a working public frontend gets deployed to Firebase.