DEV Community

Cover image for Beginner's Guide for Creating a Serverless REST API using NodeJS over Google Cloud Functions

Beginner's Guide for Creating a Serverless REST API using NodeJS over Google Cloud Functions

Levi Velázquez on March 21, 2019

API REST using Google Cloud Functions (Serverless) Serverless application has gained a lot of importance over time. It allows focussing ...
Collapse
 
psidneyrobinson profile image
Sid Robinson • Edited

Hey there, I'm having a hard time getting this deployed. I've copied your index.ts file so I know the file is good, I just can't figure out why my code is breaking. I'm attaching a screenshot but not sure it's coming threw.

Collapse
 
levivm profile image
Levi Velázquez

I can't see the screenshot.

Collapse
 
psidneyrobinson profile image
Sid Robinson

Yeah.. not sure why it didn't work.. here is an url.. sidneyphillip.com/screenshot.png

Thread Thread
 
levivm profile image
Levi Velázquez

This is about your TS lint configuration, it isn't nothing about the platform itself.

Check this answer: stackoverflow.com/questions/430642...

Let me know if you need anything else.

Collapse
 
lcarbonaro profile image
Les Carbonaro

Thank you Levi for this tutorial. It was very clear and easy to follow for the most part. I had an error come up from firebase deploy regarding firebase-function-helper but I see that you have since removed that import line.

In my case, I did not use Typescript or TSLint, so I had to remove the predeploy steps in firebase.json. Also the imports in index.js had to be require in my case.

The only thing I added was cors, so as to be able to call the endpoints from a front-end on a different domain, like now or Netlify, for example.

Also, other (older) tutorials I followed had mentioned downloading service account settings as a json file and then importing that in the project. A bit of a hassle. Your solution is much cleaner in this regard and, as a result, more portable.

Thank you again for a very helpful article.

Collapse
 
levivm profile image
Levi Velázquez

I'm glad it was useful to you.

Yep, I need to add cors so you can use the endpoints from another domain.

Thanks for the feedback.

Collapse
 
spock123 profile image
Lars Rye Jeppesen

Functions as a backend only works for the US region.

In other words, it's a no-go for people using firebase hosting, database, storage in other regions, as latency will be atrocious.

We had our entire backend rewritten as functions before we discovered this issue. Had to completely abandon Firebase functions because all our other Firebase assets are located in Europe. So we moved our backend elsewhere, unfortunately.

Just be aware guys: functions as an API for your frontend ONLY works for US region. We had 500ms latency for every request because of this.

Collapse
 
khmaies5 profile image
Khmaies Hassen

I have a dumb question :p
Why we have to build an api for firebase database and not directly use the firebase api to access our firestore database?

Collapse
 
levivm profile image
Levi Velázquez • Edited

This is a simple tutorial, I tried to keep our endpoints simpler as possible but most cases you need to have authentication, you need to do extra processes before inserting a record, you need to create an extra task, handle permissions, roles, etc. This is a backend service, it isn’t about just accessing database.

If you have any other question, feel free to ask :)

Collapse
 
dizid profile image
Marc de Ruyter

i have a url-shortener without users logging in. I cannot write to firestore from the Vue client because the firestore rules need a user logged in. I can also not use the firebase-admin because the code runs on the client. So, now i am trying a cloud function as an API relay.

Collapse
 
levivm profile image
Levi Velázquez

But you can authenticate using an anonymous login(it is available on firebase), so, you can login user using token generates from the client without having username or password.

Thread Thread
 
dizid profile image
Marc de Ruyter

HI Levi, Thanks for the tip, i will look into that!

Collapse
 
projectcorrelationrelationship profile image
Project-Correlation-Relationship

Hi, Excellent tutorial. I using Windows 10, and I managed to get almost all the way through but after I run the firebase deploy, I am getting the following error

"debug] [2021-01-26T09:35:46.363Z] Error: EPERM: operation not permitted, scandir 'c:/Users/abc/AppData/Local/Application Data'

Any pointers please.

Collapse
 
moevans2018 profile image
Mitch Evans

Will you or have you created a tutorial that follows this for authentication and use of API Keys? I found this article EXTREMELY useful and would love a follow up!

Collapse
 
levivm profile image
Levi Velázquez

Yep, I'm just writing it, I'm planning to release it next week.

Glad you found it useful.

Collapse
 
heyconor profile image
Conor

Hi Levi - Did you ever get around to writing this next post on authentication? I'm looking for a tutorial on how to implement authentication via a firebase-hosted RESTful API, e.g.

  • Login
  • CRUD (but only if user is authenticated)

The approach I'm familiar with is using JWTs with Node, but I appreciate this may be different with Firebase Cloud Functions. I'm not sure.

Collapse
 
thibaultwalterspieler profile image
Thibault Walterspieler

Hi,
First, thanks for this tutorial. I tried many things but I still get many "WebGL2RenderingContext" errors (x4) when deploying Firebase (firebase deploy).
thepracticaldev.s3.amazonaws.com/i...
I had followed at the letter your tutorial, but I'm still blocked.
Do you have any clue ?

Thank you again

Collapse
 
levivm profile image
Levi Velázquez • Edited

It seems to be something about your typescript, try to re-install it.

Collapse
 
thibaultwalterspieler profile image
Thibault Walterspieler

I finally success to manage this error by setting skipLibCheck: true in my tsconfig.json.
typescriptlang.org/docs/handbook/c...
Thank you anyway ;)

Collapse
 
hungtranpg profile image
hungtranpg • Edited

Great tutorial!
Should we have only one large Express app to handle all requests? Or should we divide it to multi-app by functionally?
Because of some limits
cloud.google.com/functions/quotas

Collapse
 
johnswicks profile image
johnswicks • Edited

Hey Man thanks for helping out everyone.I have read data from all documents in a collection but I cannot get into my subcollections of cloud firestore. I am trying to get result from subcollections but I always get []. I would be very helpful if you share piece of code.

Sample Collection:
Users(collection)->Id(Documents in collection)->ratedBy(Sub collection in document)-> detail(ratedby document)

Collapse
 
interpegasus profile image
Arturo

Hi Levi, Thanks for the tutorial. Currently, the API endpoints work fine after they are deployed.

However, when running the emulator locally, the API endpoints seem not to be recognized.

URL: mylocal_server/v1/warm or mylocal_server/crew-iq/us-central1...
Browser Output: 'Cannot GET /v1/warm'

Do you know what might cause the issue or what would be the local API endpoint?

$ firebase emulators:start --only functions
i emulators: Starting emulators: functions
✔ functions: Using node@10 from host.
✔ functions: Emulator started at 0.0.0.0:8080
i functions: Watching "/home/ubuntu/environment/Crew-IQ/functions" for Cloud Functions...
⚠ functions: The Cloud Firestore emulator is not running, so calls to Firestore will affect production.
✔ functions[webApi]: http function initialized (0.0.0.0:8080/crew-iq/us-central1/w...).
✔ All emulators started, it is now safe to connect.

Collapse
 
alextoul profile image
Alexandre Toulemonde • Edited

Since Jan 2020, we need extra settings to make the API calls public once deployed.

gcloud functions add-iam-policy-binding webApi \
--member="allUsers" \
--role="roles/cloudfunctions.invoker"

Collapse
 
vardank37 profile image
vardank37

Hey Levi, Thank you for this tutorial. I just have one question, is it possible to get data in realtime using restful API?

Collapse
 
levivm profile image
Levi Velázquez

Yes, I mean, in this example you are getting the data in real-time or do you have other concept in mind ?

Collapse
 
vardank37 profile image
vardank37 • Edited

Here we are sending get and post requests but what I am asking for is something like firebase listeners. Like how can we get data automatically ( get data in frontend ) if something changes in the database without sending a request?

Thread Thread
 
levivm profile image
Levi Velázquez

Ah, I got it, no, this for request/response flow, but Firebase has a tool for that: Firebase Cloud Messaging, so, you can have channels/listeners and send data back and forth: firebase.google.com/docs/cloud-mes...

Collapse
 
gautham495 profile image
Gautham Vijayan

Phenomenal tutorial about firebase cloud functions.

Collapse
 
levivm profile image
Levi Velázquez

Glad u liked it.

Collapse
 
crod93 profile image
Cody

The StackOverflow link is to github

Collapse
 
tfutada profile image
Takashi Futada

Thanks a lot. This helps a lot.

Collapse
 
calderaro profile image
Angel Calderaro • Edited

is there a reason to have 2 express apps? good post!

Collapse
 
levivm profile image
Levi Velázquez

It is a small trick to allow rewrite the base URL, also, one is for attaching to the function, the other one for handling the rest.

Collapse
 
kevinwong15 profile image
Little Stone

What is the advantage of having them as separate?
I believe the deployment to Firebase is still the same..

Thread Thread
 
levivm profile image
Levi Velázquez

Yes, it's the same, it's just a trick, one app handles the initial request, and the other the routing.

Collapse
 
madewithjavascript profile image
Made with Javascript

Super Helpful! using it on my project

Collapse
 
levivm profile image
Levi Velázquez

Glad to hear that.

Collapse
 
prvnbist profile image
Praveen Bisht

Sweet, exactly what I was looking for. Thanks!

Collapse
 
levivm profile image
Levi Velázquez

Good, it helped you out.

Collapse
 
akshay_pal01 profile image
Akshay Pal

Good, It is helpful.

Collapse
 
opchaves profile image
Paulo Chaves

Great tutorial Levi!
Are you able to test this API locally (hitting a local firestore) or you have to deploy it whenever you want to test an endpoint?

Collapse
 
levivm profile image
Levi Velázquez

You need to deploy and hit the endpoint to test the whole thing, but you can test you JavaScript code using a local server but you need to set it up. This is serverless, so Google Cloud Function handles it for you.

Collapse
 
engmms profile image
engmms • Edited

Hi Levi
really very useful tutorial , thanks
I face this problem ( I am new with nodsJS and TypeScript

dev-to-uploads.s3.amazonaws.com/i/...

Collapse
 
levivm profile image
Levi Velázquez

That error is from your tslinter, you should add variable types or relax the your linter rules about errors.