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

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(); }

Related

Trying to implement shopify webhooks but getting 'InternalServerError: stream is not readable'

I'm building an app for shopify and need to add the GDPR webhooks. My back end is handled using next.js and I'm writing a webhook handler to verify them. The docs havent been very helpful because they dont show how to do it with node. This is my verification function.
export function verifiedShopifyWebhookHandler(
next: (req, res, body) => Promise
): NextApiHandler {
return async (req, res) => {
const hmacHeader = req.headers['x-shopify-hmac-sha256'];
const rawBody = await getRawBody(req);
const digest = crypto.createHmac('sha256', process.env.SHOPIFY_API_SECRET).update(rawBody).digest('base64');
if (digest === hmacHeader) {
return next(req, res, rawBody);
}
const webhookId = req.headers['x-shopify-webhook-id'];
return res.status(401).end();
};
}
But I get this Error: error - InternalServerError: stream is not readable
I think it has to do with now Next.js parses the incoming requests before they are sent to my api. Any ideas?
I discovered the answer. Next.js was pre parsing the body in the context which made it so that I couldn't use the raw body parser to parse it. By setting this:
export const config = {
api: {
bodyParser: false
}
};
above the api function in the api file it prevented next from parsing it and causing the issue. I found the answer because people had the same issue integrating swipe and using the bodyParser.

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

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).

Firebase HTTP function CORS

I'm still having problems with CORS when using Firebase HTTP functions.
Here is my web console error:
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:3000' is therefore not allowed access. The
response had HTTP status code 404.
Here is my function:
const cors = require('cors')({ origin: true });
const express = require('express');
const functions = require('firebase-functions');
const app = express();
const validate_user = require('./validate_user_id_token.js');
const charge_card = async(req, res) => {
// ...
}
app.use(cors);
app.use(validate_user);
app.use(charge_card);
exports.foo = functions.https.onRequest(app);
I think I've read over every single Firebse CORS question. I also have a near replica of the sample provided here.
Please help :)
Edit:
The URL I am calling is correct (used texdiff.com just to be sure, and functions logs are showing it as executed but returning 404). For reasons unknown, a 404 is returned regardless. Perhaps that is CORS mechanism?
Update:
I got things working without using express by putting using cors() in my onRequest handler:
exports = module.exports = functions.https.onRequest(async(req, res) => {
cors(req, res, () => {});
await charge_card(req, res);
});
Not ideal, but it works for now :/
According to the Firebase documentation, there are a couple of references to CORS configuration:
Using CORS:
You can enable the use of CORS by calling it within the function, just like you did in your update to the question:
// Usage of the `cors` express middleware
return cors(req, res, () => {
// TO-DO
});
Also if you have an already existing Express app, you can then enable CORS by doing:
const app = express();
app.use(cors({ origin: true }));
This is what you had already done on the first step, but there's the difference in the { origin: true } definition, so maybe that is related.
In any case, as per the documentation it looks like it is indeed fine to add the cors within the request.

req.body is always an empty object: {}

I can't figure out why my express app never gets the correct body data from the client. For express, I have the following:
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
next();
});
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.post('/authenticate', async (req, res) => {
debugger;
res.send(req.body);
});
And for my front end, I just run the following code:
await fetch("http://localhost:3000/authenticate", {
method: "POST",
body: "anything"
})
But in the request handler, req.body is always {}. I tried sending strings, JSON objects, stringified JSON objects, but no matter what, it always comes out to {}.
The only thing I could think of is that the front-end is on a different domain (it's on http://localhost:4200). But I highly doubt that's the issue.
It doesn't look like you are actually sending JSON. This looks like you are sending the raw string anything, which isn't JSON.

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());
});
});

Resources