How to handle ALL requests (regardless endpoint) in firebase functions - javascript

I am trying to handle errors in firebase functions. For instance if the route/function does not exist to throw error/send error back to client with some meaningful message. This is first time i am using firebase functions and i can't find solution in their docs or anywhere else.
what i do have now:
//...
// HTTP endpoints
exports.authorize = user.authorize;
exports.deleteUser = user.deleteUser;
What i need is to somehow handle case where someone access function which does not exist or send invalid headers. I want to handle this globally without need to wrap all functions into something.
Any help/tips appreciated.

Cloud Functions only respond to the endpoint URL they were assigned at the time of deployment, which matches the name they were given for export. There are not wildcard or catch-all URLs.
What you can do instead is use Firebase Hosting has a forwarding proxy and rewrite any URLs using a wildcard to Firebase Hosting to a specific named function that can handle the request.

Related

Is it possible for PaaS's HTTP trigger by Javascript's fetch to be restricted on domain basis?

I've developed a js to help users input there info in a form by fetching public data.
Now I'm thinking to deploy it as kind of an API service.
Is it possible and safe enough for HTTP trigger of PaaS's like GCF and Amazon Lambda to be triggered only from specif domains I allow? Like js's fetching and reading its header's origin and check its domain.
I've considered generating passcodes per my customer and placing it in key.js in user's directory or env value, have my js file open on URL, let user website read the js with return of key.js in query param and check its validity.
But forms can be everywhere in cutomers tree, placing it in env for each custmomer can be bothersome at scaling.
you can use ReCaptcha v3, add the allowed domains that can access your function endpoint, and verify the token is valid on the function implementation.
This isn't a native GCF feature, but you could try
Adding a filter in your GCF code (e.g. express.js) to check the requested domain
Making your GCF private and letting it ensure callers are authorized (GCP callers)
Run in Cloud Run, App Engine or another service with Identity Aware Proxy and screen out callers that way

The relationship between front end and middleware

I have a front end application, which I would like to return results with from an Express backend. Let's just call those results country and city for this reference.
I have done a bunch of searching, but I cannot find any solid resources on the relationship between the front end and middleware. Yes, I know what these things are, and the order in which they should flow, but the confusion sits with :
Do I need to connect my front end and middleware? How so?
If I am already connected to my backend from the front end, would I also have to connect to middleware?
How would I return the country and city from the middleware and/or express backend?
Any other info you think would be helpful for the greater dev community who is still learning would be beneficial.
While you could return data from a middleware, it's probably not what you are trying to do. A middleware is a piece of code that is executed between the time the request is receive by your backend, and the resource is fetch. In a middleware you could do things such as check if a user has access to a certain resource or authenticate a user by some sort of credential passed with the request.
Either way, the way you would, typically, do request from your front-end to your backend is via an XmlHttpRequest. Those request are usually Asynchronous, so they usage will not block the whole page while being executed. There are many ways you could create XmlHttpRequest. The native Javascript way is kinda ugly so I would suggest using the fetch api instead. You could also go with third party library if you need to do more complex stuff. I personnally like axios but this is up to you.
To give you a better understanding of what Express is doing, it's basically an infinite loop that waits for http request. You need to defined routes, that execute function that returns data.
Here is a basic example. Note that this script is executed via NodeJS :
// myserver.js
const express = require('express')
const app = express()
app.get('/cities', (req, res) => {
const cities = /** somehow get all the cities **/
res.json(cities);
})
/** the rest of the server... **/
/** For example, the route for Countries **/
In the previous example, we've built a basic server that listen to the url localhost:3000/cities and execute a function when this url is fetched. The said function will fetch all the cities and return them as JSON.
In your frontend, You would need to do a XmlHttpRequest that would call this url, to get the server to execute the function, which will return the data. Phew... I hope I did not lost you there.
A typical example would be a simple call using the fetch api.
Please note that this script is executed in the browser.
// myclient.js
async fetchAllCities() {
const cities = await fetch('http://localhost:3000/cities');
console.log(cities);
}
// just for fun, we add a click listener on a button and call the function defined above.
document.getElementById('myButton').addEventListener('click', async function() {
// we fetch the cities when we click on the button !
await fetchAllCities();
});
In the previous example, I am using the fetch function to call the url we declared in our Express server.
I'm also using Async / Await, which can be a little tricky, but it just mean Wait for the data to be there before going forward.
I highly suggest reading on the subject. Here are some references.
How do I return the response from an asynchronous call?
Understanding async/await on NodeJS.
Await from MDN
I hope this brief overview of XmlHttpRequest helped you get the base of how an API works.
Middleware is used to help the back-end do its job in processing incoming requests. It does not exist separate from the back-end. It's part of the back-end. For example, you might have middleware that checks to see if an incoming request is properly authorized/authenticated before the route can be handled by it's regular route handler.
Do I need to connect my front end and middleware? How so?
No. Your front-end sends requests to the back-end. The back-end may or may not use middleware to service the request. That's entirely up to the implementation in the back-end and what it needs to do for any given request.
If I am already connected to my backend from the front end, would I also have to connect to middleware?
No. You don't separately connect to middleware. You connect to your back-end and the back-end may or may not use middleware to do its job (something the front-end will have no knowledge of).
How would I return the country and city from the middleware and/or express backend?
You would have to show more details about what you're actually trying to return back from a request, but a common data format is JSON so you could construct a Javascript object with your desired response and then send it back to the client as the response from the incoming request using either res.json(someObj) or res.send(someObj) (both do the same thing if someObj is a Javascript object).
For example:
app.get("/getsomething", (req res) => {
// do some processing here to get cityResult and countryResult
// construct object to send back to client
const obj = { city: cityResult, country: countryResult};
// send this object as JSON back the the client as the response to this
// incoming request
res.json(obj);
});

calling a function itself in a controller sails js

I know this same question has been asked before but the previous questions were in different languages and on different frameworks, and I tried all the methods mentioned in previous questions' answers but found no luck.
so here it is again.
I have a controller in my sails js app named orderController
code is:
module.exports = {
order_history: async function(req, res){
//get a response from an API and it is saved in nData
if(nData.status_code == 0 && nData.result == 'succeed'){
res.ok(nData.data);
}else{
updateCredentials();
order_history(req, res);
}
},
};
now if there are expired credentials then it updates the credentials and I want it to repeat itself so it can return the proper response in case of expired credentials. I do not want another request to be sent for this.
My advice would be to create a helper with the logic for order_history that you call from within the controller. If it fails, you can do the update_credentials, then call it again. I say this because sails is built with the idea that a controller's purpose is to be a specific response to a specific request endpoint and not meant to be reusable code. That's where the helper comes in, it's purpose is to be a globally available function. The benefit of doing it this way is that you won't end up in a situation where the order-history fails for a reason other than needing to update credentials, calls itself, fails for that reason again, updates credentials, calls itself... You can have it try updating credentials, then if it fails again respond with an error message.

How to make sure that only a specific domain can query from your REST api?

I have an app that has a REST api. I want it so that the only requests that can be made to the REST api are ones originating from the app itself. How can I do that?
I am using a node.js+express server too.
EDIT: the app is fully a public web app.
Simply define the header in your request, what this does is, it allows requests only from a certain domain, and instantly rejects any other domain.
response.set('Access-Control-Allow-Origin', 'domain.tld');
EDIT: IF you're really keen against web scraping stuff, you could make a function to double check client's origin.
function checkOrigin (origin) {
if (origin === "your.domain.tld") {
return true;
} else {
return false;
}
}
/* Handling it in response */
if (checkOrigin(response.headers.origin)) {
// Let client get the thing from API
} else {
response.write("Send them error that they're not allowed to use the API");
response.end();
}
Above example should work for the default HTTP/HTTPS module, and should also work for Express, if I'm not mistaken.
EDIT 2: To back my claim up that it should also work for Express, I found this quotation at their documentation;
The req (request) and res (response) are the exact same objects that Node provides, so you can invoke req.pipe(), req.on('data', callback), and anything else you would do without Express involved.
I would recommend using an API key from the client. CORS filters are too easy to circumvent.
A simple approach for securing a How to implement a secure REST API with node.js
Overview from above post:
Because users can CREATE resources (aka POST/PUT actions) you need to secure your api. You can use oauth or you can build your own solution but keep in mind that all the solutions can be broken if the password it's really easy to discover. The basic idea is to authenticate users using the username, password and a token, aka the apitoken. This apitoken can be generated using node-uuid and the password can be hashed using pbkdf2
Then, you need to save the session somewhere. If you save it in memory in a plain object, if you kill the server and reboot it again the session will be destroyed. Also, this is not scalable. If you use haproxy to load balance between machines or if you simply use workers, this session state will be stored in a single process so if the same user is redirected to another process/machine it will need to authenticate again. Therefore you need to store the session in a common place. This is typically done using redis.
When the user is authenticated (username+password+apitoken) generate another token for the session, aka accesstoken. Again, with node-uuid. Send to the user the accesstoken and the userid. The userid (key) and the accesstoken (value) are stored in redis with and expire time, e.g. 1h.
Now, every time the user does any operation using the rest api it will need to send the userid and the accesstoken.

Is there an equivalent of Netscape navigator functions in nodejs?

Can I access the inbuilt navigator functions like isinNet() or DomainNameorHost() from nodejs?
Since nodeJS runs on the server, not the browser, you can't access functions that are only provided in a browser.
Most developers use a middleware like Express to create a web service on nodejs.
In a route, such as
app.route("/play", function(req,res){
// code that handles URL /play
});
there is a callback function that is called when a request arrives for that route.
The req object parameter contains everything about the request.
req.ip is the upstream (incoming) ip address.
I looked around in npm for a module that might map remote ips to hostnames and could not find one. Presumably all it would do is reverseDNS, which could take time and hold up processing requests.

Categories

Resources