Firebase Cloud Functions - Creating a REST Endpoint with Cloud Functions

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to this video great to see you back in this miniseries in the last videos to learn what firebase cloud functions are and how to create a cloud function that listens to changes in our firebase storage in this video we'll listen to http events hence actually creating our own API let's dive into that so let's add a new cloud function here's the cloud function I created in the last video the one which reacts on storage events now I'll export a new function here with exports and then the function name and I will name this one here upload file I'll use the functions object here which we get from the firefight fire base functions package and I will use the HTTP realm to listen to HTTP events there we have on request and on request then also takes a function that gets executed and this gets executed whenever an HTTP request reaches this endpoint and you'll get the exact URL once you deployed it this object here actually will hold a request and a response object as you know it from Express Apps note Express so in there we can now do something we should absolutely send a response that's the bare minimum so what we can do here is we can send a status code of 200 with maybe some JSON data where we output a message it worked and you could also send HTML here it doesn't have to be JSON data and if this is a certain extent no it's probably worth looking into some node Express tutorials because I'll essentially be using the same syntax and language here so with that I'm sending a response and now why don't we just try it out this is a basic HTTP function cloud function which we can trigger by sending a request to it so let me run firebase deploy in our project here to put this back into firebase and create a function with this upload file function we just define and then let's see how we can trigger that deployment finished and now if you expand the console here or scroll up you will see where your functions are deployed to and for HTTP functions you'll get the endpoint you have to send a request to so I'll copy that URL here and then I'll simply open postman that is a tool that allows you to send HTTP requests well to any endpoint you want essentially in there I'll enter the URL and I won't set any special headers or a body I'll just send a get request and it's sent and now this gives me and deep back some JSON data it worked with status code 200 so this shows does a dead works and we can also send a post request to the Zen point we get back there are the same response if we only want to handle some HTTP works and at all of them we have to do this in this endpoint by default that handles all incoming requests so now we could say we just want to handle post requests so we could check if request method if this is not equal to post if it is not equal then I will return a response with maybe status code 500 and set jason-2 to pass an object where the message is not allowed or whatever you want so with that I updated this now I can deploy it again and the URL is going to stay the same and as you already see I'm using this same syntax used in a normal node Express project because firebase cloud functions for HTTP events use node Express behind the scenes so you can use the same syntax and the same packages for a node express project so that's pretty cool so this is something to keep in mind you can really build your node Express project in a restful way and on a per endpoint basis with cloud functions you can simply write any logic here which you would normally put in one of your routes in the node Express project you might be building so it's wait for this to finish in let's then try this out deployment finished it's worth waiting a couple of milliseconds or half a minute or something like that to really make sure that the function change propagated and you really reach the right endpoint and then if you try again and you send a post request you should get it worked and if you send a get request you get not allowed so now we make sure only post requests trigger this now the idea behind the functions not just to send back some dummy data I actually want to accept some data some form data let's say so a mixture of file and some fields which I can put onto cloud storage for this I first of all want to ensure that course is enabled so cross-site origin resource sharing to make sure that also apps that do not live on the same server as this function will be hosted on so basically all apps but also these apps are able to send HTTP requests to this back-end now for postman this is not important because postman is not a browser it doesn't check for weather course is allowing this access but in a browser if you send some Ajax requests you typically have the issue that the server has to enable course so basically has to allow you to access the resource even though your web app might not be running on the same origin not on the same server so I want to allow that and for that I will install a new package so navigate into the functions folder and with the npm install - - save all in store let's install the course package now this is a node express package we can use to conveniently set some headers we need to send back to the client to allow this crossorigin access and with that installed all imported here course require course this is executed as a function and I pass an object to that function where I set origin to true to setup this these course headers for this origin correctly and then it will actually wrap my entire code here with this course middleware so I will execute course as a function here and this function takes three arguments request response and then the function should execute after it basically added its own headers to the request and response so I will forward request and response here and then execute a function where I also get requests and response and where I then will simply put the code I previously had well in my cloud function itself so now it's wrapped by this course middleware and therefore it sends the right headers to allow crossorigin access since i renamed this in this anonymous function here to request and respond I should all return response status in both cases now to have this work correctly again with that we added course we still don't really accept form data we're not able to do anything with incoming files so that's the next step I want to take and Q accept such file uploads and then store them on fire by storage I need two things I need one package that parses the incoming request body for foreign data and then gives me convenient access to the files and the fields I might have added and I need access to my firebase storage which I already can do or can access with my Google Cloud storage package there so we already got this at least now for parsing that incoming request body I'll use a package name busboys which is a package that is able to handle incoming foreign data so again navigate into that functions folder and run npm install - - save busboys like that and then once this is installed we'll never get back into the main directory and I'll import busboy from the busboy package like this and then I'll go into my course wrapper and after I checked the method off the request I'll create a new busboy instance with new busboy and I'll pass an object to it where I simply forward the headers so set the headers property to request headers does require - well allow bass boy to find out whoever the incoming request is of type form data or not so if it should parse it or not with that I'll use this bass boy object and add the on listener and I'll listen to file events these will be triggered whenever pass boys successfully parses a file from the incoming request in this case we would get an event a method that gets executed a function which receives the field name in which the fall was stored the file itself the name of the file the encoding of the file and the mime type funky gets executed for every foul detected India requests reaching this endpoint now I'm only interested in false if you wanted to also get fields you would have add a busboy on field listener no fields is anything but a file so extra information you add with the request since we're sending foreign data it can be a mixture of a file and extra fields I'm only interested in the file though so once we got a file what's what's the plan the plan is to store it in firebase storage right so what I'll do here is I'll construct a path to the file by using half join which already used in the last video where I get the temporary directory of this cloud function there is a little temporary cloud storage attached to the cloud function it will be cleaned up whenever the execution is done essentially but during the execution you can use it to store files and busboys will store it in some temp directory will store that incoming file there so I'll access the temp directory and get my file there so I'm constructing a path to the file which pass by extract it and then I will create some variable here which will name upload data which initially is now I do this out set of paths boy on instead of pass by on file I'll then set upload data to an object a JavaScript object where I will set my file to default path I created here and where I set the type to the mime type bus boy detected now why do I set it up like this in a variable because now I will leave this path boy on function here and add an a verb or one pass boy on finish bass boy on simply triggers whenever it found a file but finished triggers wanted to stunt parsing the entire request this is when I want to upload the data so here in this handler function and I want to use Google Cloud Storage to upload so I'll create a bucket object here and use GCS bucket to do that to get a reference to a bucket and now I want to get my default bucket for this firebase account you can get this easily by visiting your storage and there it's basically this name without the GS colon slash slash at the beginning this is what I'll pass here this is my default bucket this is the bucket into which I want to store the file now if dead reference created I can trigger bucket upload call that method pass my file and that is why I got this upload data object here where I have a file property which holds a path to the file so now I can pass upload data file here which is that path to the file I want to upload then I can pass a JavaScript object where I will set the upload type to media and set the metadata field Q hold another metadata field where I will set the content type to the upload data type so the content type we originally detected you could add more metadata to the uploaded file of course now at some point of time upload will be done and it even returns us an error or some information about the uploaded file now if we got an error I want to return a response with status code 500 and some JSON object where I essentially pass on the error object but if we don't make it into the safe statement so if we don't have an error then I know that we successfully uploaded the file and then I will take my original response and remove it from the end of that file and put it into this then block here and with that we should have a setup where we can upload a file through HTTP request so let's try it out let's go into the root project folder and run firebase deploy and let's then see if we can successfully send foreign data requests with a file in it cue our back in here and then store that in firebase cloud storage and then it should actually all to trigger our resize function which we wrote in the last video so let's see if that both is the case the deployment is done here again don't rush this it takes some time to propagate that new endpoint to the web so I'll go back to postman and now I will go to body of my post requests make sure to set this to foreign data and then add a file here gif does any name you want like image and choose a file of course I'll take that the winter image we used before now this is the request I want to send so let me hit Send here and I actually get back an error could not handle the request let's have a look at our firebase functions log here so on firebase cloud functions I'll have a look at my upload file log here and there I can treat headers of undefined at course hmm yeah because I got an error here the course middleware does execute a function here but actually the original request and response object are just edited so that is my mistake here also I never changed this we're just correct because I should keep the original request not renamed us to requests just keep a direct we're here and the same for a response use response arrests and not the response we used before everywhere because course just appends to this original data it does replace this so this is my mistake sorry for that so let's quickly rebuild deploy this and then test us again so now the updated function redeployed let me try this again and again let's not rush this it can take a while so let's try sending this again and now it's taking really really long here then you can see in the lock that it started a function execution but somehow it's not finishing here now it will timeout after 60 seconds that's the default timeout so you got no infinite running function costing you thousands of dollars by way the basic execution so a couple of executions which are clearly defined in the official Docs actually with more than just a couple are free so you can run your function quite a lot without paying anything only if you exceed that limit you will have to pay but again you can find this in the official Docs and there on the pricing pages it is described how often you can run your function in the free tier and from which point on it will cost you money so here you can see it timed out after this one minute the question of course is why did it timeout what what's wrong here why doesn't this work it actually has two issues our function one is here when we parse file requests when we get incoming files there we get the file path but actually this is not a file path that's why we'll automatically store the fallen itself all puffs we can use to store the fallen so first of all let's import and now we're dependency the file system package which is a default node package so we don't need to install it separately and then in the file listener here I will use that file busboys detected and add the pipe method to do something to that file and then I will use FS create right stream you basically stream the file content into a new file and pass file path as an argument this will actually write this file to the system now that's one thing another thing is that Google Cloud Storage whilst we could use it in our cloud storage trigger in the HVP trigger it's not available it's not initialized we need to initialize it manually with the credentials of our firebase project that we can do it as easily by going to our firebase project and then to the settings project settings and there to service accounts there you can now download under firebase sta admin SDK you can download a private key which you need to initialize cloud storage so you can click generate new private key and then stored it in your project folder so here in the functions folder so now I added this file which holds my private key and now in your firebase cloud function you actually need to initialize your Google Cloud storage a bit differently you need to initialize it such that you can use it in every function so I'll put it a bit further down because before we import it I'll add a new constant which we'll name GC config for a Google Cloud config where I will just specify the project ID woops like that make sure the casing is correct project ID which is just your firebase project ID I'll add it in a second and a key file name property which is just the name of that JSON file make sure to add dot J's and you just generated and download it and store it in your project so the project ID is something you can find in the firebase RC file for example so I'll add this here also as a string and this Google Cloud Connect has to be passed to that function we execute here when we import the Google Cloud Storage package I'll just pass this GC config object to it to initialize that and with that I now make sure that Google Cloud Storage all the works in this HTTP trigger function and not just in the storage related cloud function that is something you have to keep in mind if you want to use the Cloud Storage package in a non storage related trigger function then you have to initialize it with your private key you download it from the firebase console now if then we're almost there but there's one more thing we have to do to kick off this whole busboys thing after all our on listeners and so on I also have to call Busboys and and pass the request raw body Hewitt raw bodies a property provided to us by a cloud function itself so to say on the request object and this simply well is required for Busboys to work correctly and to start parsing or to to parse all the requests and trigger on events now with that we're almost there one more thing though here in the upload then block that's of course a mistake here we just get a function here if we are successful and if we would have an error then we would actually end up here in the catch block so that is where we then received the error then we then in turn want to handle we don't need an if step in here we would just return our error response here so just like this this is the adjustment need to make this syntax where you get the error or the uploaded file reference which you also could use here that would only be relevant if you were to pass you see an alternative way of using the upload function by passing a callback function where you then indeed have your error or the uploaded file but if you use the promised approach as I do you work with then and catch of course so sorry about that and with that let's deploy this firebase function and let's see if with all these changes it works as it should now let's already do something else let's go to storage and I already got some files in there which actually are defaults I will upload so I will delete them to make sure that we really can see if that works so that I got an empty storage now if that I'll wait for this to finish and then we'll try out sending the same act request again and hopefully with that storing a file on cloud storage through our firebase HTTP triggered cloud function pretty advanced I guess deployment finished and as always let's give this a few seconds before we send the request and then in postman all sent the same request again queue firebase and I get back it worked which is looking good now on storage I'll reload this and actually there we should see two files now we see the uploaded file and the resized one because our other cloud function which triggers upon file changes and of course this is a file change it's uploaded so this triggers the cloud function the average cloud function also runs so the resizing cloud functions all the runs and here I can confer and by the date and time this is today so this works as it should and with dad with some errors we made it to the end of that we have our upload file HTTP endpoint which is triggered by an incoming request we check the request method we make sure that we would all to be able to reach this from some web app which uses a browser which therefore make sure that course is enabled we do enable it here we use bass voice you parse the foreign data and parse any files store them in a temporary folder and then once we parse the hold request upload it through the initialize Google Cloud Storage package and then we will kick off this whole parsing essentially here by calling end and saying we're done reading in the request here's the raw body please do something with it this is what's happening here and they hope that despite the few errors we faced which also might have been helpful seeing some things to avoid you learned how to set up HTTP endpoints through firebase cloud functions and which extra flexibility just gives you now you can build your own restful api on top of firebase you can use all the other features you can integrate this API with the other features like we do for storage and you can add extra functionality that previously you couldn't add easily at least
Info
Channel: Academind
Views: 112,436
Rating: undefined out of 5
Keywords: firebase, rest, rest api, cloud functions, http, trigger
Id: qZ1EFnFOGvE
Channel Id: undefined
Length: 24min 8sec (1448 seconds)
Published: Mon Feb 05 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.