functions.https.onCall access to the req param from the http call - firebase

I am referring the following function
https://firebase.google.com/docs/functions/callable
The syntax is:-
exports.addMessage = functions.https.onCall((data, context) => {
// ...
});
Is there an option to get the req param we have in the standard http function
exports.date = functions.https.onRequest((req, res) => {
// ...
});
specifically interested in
req.protocol
req.get("host")

Callables don't support redirects. They're expected to send direct responses to the client (otherwise, they wouldn't be "callable").
If you want to send a redirect to the client, use regular HTTP triggers with an HTTP client that can follow redirects (or handle the redirect yourself).

Related

Can't do a post request using axios, returning unauthorised 401 error

I created an auth service from scratch using Redux, React and Node. Everything was working fine until I wire up my Post section o redux to my BackEnd. The redux part is ok I guess. My problem is when I send the Authorization Bearer token. I'm being able to post using insomnia. But when I try to post using the web app I can't.
This is my action:
export const createPost = ( formValues: any) => async(dispatch: any, getState: any) => {
const { userId } = getState().auth;
let token = userId
const headers = {
header: {
'Content-Type' : 'application/json',
'Accept' : 'application/json',
Authorization: `Bearer ${token}`
}
};
const response = await AlleSys.post('/posts', {...formValues, headers})
// dispatch({type: CREATE_POST, payload: response.data})
userId is my JWT token.
I already set up Cors on my backend
const corsOptions ={
origin:'http://localhost:3000',
credentials:true, //access-control-allow-credentials:true
optionSuccessStatus:200
}
app.use(cors(corsOptions))
On Insomnia. The same request on insomnia works fine.
On insomnia I'm using the same bearer token from my application, so the problem is not the JWT.
Querying an endpoint with GET, POST, PUT, DELETE from a Nodejs server or Insomnia will result in calling before checking the OPTIONS.
But browsers will limit the HTTP requests to be at the same domain which makes you run into CORS issues. Since Insomnia is not a browser and CORS is a browser security restriction only, it didn't get limited.
From docs for the CORS you are using:
Certain CORS requests are considered 'complex' and require an initial OPTIONS request (called the "pre-flight request"). An example of a 'complex' CORS request is one that uses an HTTP verb other than GET/HEAD/POST (such as DELETE) or that uses custom headers. To enable pre-flighting, you must add a new OPTIONS handler for the route you want to support:
So I think you should include app.options('*', cors()) before all routes and put it at the top of your file to be processed first.
I changed my code to:
export const createPost = ( formValues: any) => async(dispatch: any, getState: any) => {
const { userId } = getState().auth;
let token = userId
const headers = {
authorization: `Bearer ${token}`
};
const response = await AlleSys.post('/posts', {...formValues}, {headers})
And Worked!

How to add header or request param to getServerSideProps in Nextjs

I want to pass a simple string value or a JWT access token to the getServerSideProps function in NextJS, then I want to do some requests for the user from the server side.
My JWT access token is currently stored in memory (in a state).
How do I pass my JWT access token or any other string value to getServerSideProps?
I have read many times that you can pass cookies to getServerSideProps but I wanted to add this access token value to the request header or request param.
Is there any other way than cookies or querystring parameter to add custom values to the getServerSideProps function in nextjs that is executed on the server?
You can pass values to getServerSideProps if you set up a custom server. You can use their example to parse the url and then add values to the query, but note that their example uses URL.parse from node and that has been deprecated so you'll want to modify it for more recent versions of node.
A second way to handle this (still using a custom server) would be to take advantage of Express-style response locals. Using their first example on the above-linked Next page, it could look like this:
// Custom Server
...
app.prepare().then(() => {
createServer((req, res) => {
res.locals.myServerValue = "someValue"
handle(req, res)
}).listen(3000, (err) => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
...
Now in getServerSideProps, you can access this value from the response object:
export const getServerSideProps = async ({ res }) => {
// Get the value from res.locals
const myServerValue = res.locals.myServerValue
// Do something with myServerValue
console.log(myServerValue) // prints "someValue"
// If desired, pass the value to the page if that's how you're using it
return {
props: {
myServerValue
}
}
}

Change the HTTP status code with a Google Cloud Function Promise

My code checks if a user is authorized, if the user is, the proper code is run. If the user is not, it run reject() to reject the promise.
If I run the code authenticated, I get
{"error":{"status":"INVALID_ARGUMENT","message":"Bad Request"}}
I am trying to change the status code to Forbidden (code 403) which you would normally do with res.status(403) however since this is a promise it is different. How can I change the error code returned?
My code is as follows:
const cloudFunction = functions.https.onCall((data, context) => {
return new Promise(function(resolve, reject) {
auth.verifyIdToken(data.userId).then(function(decodedToken) {
if(claims.admin === true) {
// Run code if user has admin role
}
else {
reject()
// Return error code 403 because user does not have admin role
}
}).catch(err => reject(err)) // Return error code 401 because user is not logged in
})
});
You can't change the HTTP status for a callable function. Callable functions essentially take over and hide the HTTP protocol for the request and response. All you do is specify the input and output objects, and the SDKs handle everything else.
If you need to control the HTTP status of a response, you will have to use a regular HTTP type function instead. Then you will have full control over the request and response.

app.post on parse heroku server is unauthorized

I am trying to post to my server from twilio, but I am getting a 403 error. Basically my parse-heroku serve is rejecting any request from twilio. I am working with TWIMLAPP and masked numbers. I am having trouble posting to a function in my index file when a text goes through. In my TWIMLAPP my message url is https://parseserver.herokuapp.com/parse/index/sms Any help is appreciated. These are the errors in twilio
var app = express();
app.use(require('body-parser').urlencoded());
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'https://www.twilio.com');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader("X-Parse-Master-Key", "xxxxxxx");
res.setHeader("X-Parse-Application-Id", "xxxxxx");
// Pass to next layer of middleware
next();
});
app.post('/sms', twilio.webhook({ validate: false }), function (req, res) {
console.log("use-sms")
from = req.body.From;
to = req.body.To;
body = req.body.Body;
gatherOutgoingNumber(from, to)
.then(function (outgoingPhoneNumber) {
var twiml = new twilio.TwimlResponse();
twiml.message(body, { to: outgoingPhoneNumber });
res.type('text/xml');
res.send(twiml.toString());
});
});

Node.js : How to do something on all HTTP requests in Express?

So I would like to do something like:
app.On_All_Incoming_Request(function(req, res){
console.log('request received from a client.');
});
the current app.all() requires a path, and if I give for example this / then it only works when I'm on the homepage, so it's not really all..
In plain node.js it is as simple as writing anything after we create the http server, and before we do the page routing.
So how to do this with express, and what is the best way to do it?
Express is based on the Connect middleware.
The routing capabilities of Express are provided by the router of your app and you are free to add your own middlewares to your application.
var app = express.createServer();
// Your own super cool function
var logger = function(req, res, next) {
console.log("GOT REQUEST !");
next(); // Passing the request to the next handler in the stack.
}
app.configure(function(){
app.use(logger); // Here you add your logger to the stack.
app.use(app.router); // The Express routes handler.
});
app.get('/', function(req, res){
res.send('Hello World');
});
app.listen(3000);
It's that simple.
(PS : If you just want some logging you might consider using the logger provided by Connect)
You should do this:
app.all("*", (req, res, next) => {
console.log(req); // do anything you want here
next();
});
You can achieve it by introducing a middleware function.
app.use(your_function) can be of help. app.use with accept a function that will get executed on every request logged to your server.
Example:
app.use((req, res, next) => {
console.log("req received from client");
next(); // this will invoke next middleware function
});
Express supports wildcards in route paths. So app.all('*', function(req, res) {}) is one way to go.
But that's just for route handlers. The difference is that an Express route handler is expected to send a response, and, if it doesn't, Express will never send a response. If you want to do something without explicitly sending a response, like check for a header, you should use Express middleware. app.use(function(req, res, next) { doStuff(); next(); }

Resources