Middleware gets hit way too many times while next.js is compiling - express

Iam using next.js and express.js . if I use a middleware (server.use(req, res, next)) it gets hit dozen times while the page is compiling, which makes my app crash completly ...
const express = require('express')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
console.log('page loaded')
app.prepare().then(() => {
const server = express()
server.use((req, res, next) => {
console.log('ping')
next();
})
server.get('/', (req, res) => {
return app.render(req, res, '/index', req.query)
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
If I try to load the page, it prints
ping
ping
ping
ping
ping
ping
ping
ping
ping
ping
ping
ping
ping
ping
ping
of course if I put a real middleware here it makes everything crash ...
I wish for the middleware to run only if the page is actually requesting something ... So only once per 'real user' request

I had the similar trouble, but only on client-side. In my case there were a lot of parasitic requests (trackers, internal API, fonts, some _next_static things). They triggered the middleware and it was the reason of ERR_TOO_MANY_REDIRECTS.
So, as for me, filtering parasitic requests and redirects helped to solve the problem:
if (new RegExp(/^.*(fonts|_next|vk.com|favicon).*$/).test(request.url)) {
return NextResponse.next()
}

Related

BodyParser causes all API requests to hang. Even basic GET requests

As the title says, I simply don't understand what is going on here. Once I include the app.use(bodyParser.json) line, Postman just keeps handing on any request I make. I lost a good portion of the day thinking I messed up my routes.
I narrowed it down to it in this little testing file:
const express = require("express")
const bodyParser = require("body-parser")
const env = require("dotenv");
const app = express()
env.config();
app.use(bodyParser.json);
app.get("/", (req, res) => {
res.status(200).json({
message:"Hello World"
})
});
app.post("/data", (req, res) => {
req.status(200).json({
message: req.body
})
});
app.listen(process.env.PORT, ()=>{
console.log(`Server listening at port ${process.env.PORT}`);
})
Can anyone tell me what is happening and how I can fix it?
You need to call JSON body parser as a function (with brackets):
app.use(bodyParser.json());
There is another bug in the post method "data", You should call status from "res" object:
app.post("/data", (req, res) => {
res.status(200).json({
message: req.body
})
});

AXIOS GET request to instagram not working in prod

I am stuck for a few hours and I can't find an answer.
It's a very simple request that works fine in the browser (it returns a JSON answer), for example :
https://www.instagram.com/eurosportfr/channel/?__a=1
In dev the code:
const express = require('express');
const axios = require('axios');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/instagram', (req, res) => {
async function getInstagramFeed() {
await axios
.get('https://www.instagram.com/eurosportfr/?__a=1')
.then((response) => {
console.log(response);
res.write(`${JSON.stringify(response.data)}`);
res.end();
})
.catch((err) => {
console.log(err.response);
res.write('<h1>ERROR GRAVE</h1>');
res.write(err.response);
res.end();
});
}
getInstagramFeed();
});
const PORT = process.env.PORT || 8000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));
The result in DEV ENV is JSON data with all what I need.
But in production, it doesn't return me the JSON. Instead it returns me an HTML page...
You can try it here: (I display in the body the result)
https://corsmiddleware.vercel.app/instagram
When I try another api request with another API client, it works just fine in prod, example :
https://corsmiddleware.vercel.app/test
Any idea ??
Thanks
This request now requires authentification. It was working in the past, and it's still actually working here in Morocco where I am, but this solution is not reliable.
The solution is to follow the instructions on facebook :
https://developers.facebook.com/docs/instagram-basic-display-api/

Google App Engine is not loading API (after first open)

I have developed a react application using next.js.
Now I want to deploy it to Google Cloud App Engine.
The application does include the react frontend and a mock-API (including mock.db) in order to store data temporararily while in development.
The issue is the following:
The first instance I opened did work correctly. As soon as I opened it in another browser only the react app was served but the API was not there (resulting in the React app only showing frames of controls and no data). The API server is accessible through localhost:3033
The same persits for my colleage who tried to open it, only seeing whiteness.
I have not configured anything extra on Google Cloud App Engine, just vanilla basically.
Does this have something todo with App Engine spinning up extra instances ? I cant figure out what could cause this issue.
package.json
"prestart:api": "node createMockDb.js",
"start:api": "node apiServer.js",
"dev": "node server.js",
"build": "next build",
"start": "cross-env NODE_ENV=production node server.js & node createMockDB.js & node apiServer.js"
server.js
const express = require("express");
const next = require("next");
const port = parseInt(process.env.PORT, 10) || 8080;
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
server.get("/products/overview", (req, res) => {
return app.render(req, res, "/products/overview", req.query);
});
server.get("/products/roadmap", (req, res) => {
return app.render(req, res, "/products/roadmap", req.query);
});
server.get("/strategy/goals", (req, res) => {
return app.render(req, res, "/strategy/goals", req.query);
});
server.get("/strategy/metrics", (req, res) => {
return app.render(req, res, "/strategy/metrics", req.query);
});
/* server.get("/posts/:id", (req, res) => {
return app.render(req, res, "/posts", { id: req.params.id });
}); */
server.all("*", (req, res) => {
return handle(req, res);
});
server.listen(port, err => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}`);
});
});
apiServer.js
/* eslint-disable func-names */
/* eslint-disable no-console */
const jsonServer = require("json-server");
const server = jsonServer.create();
const path = require("path");
const router = jsonServer.router(path.join(__dirname, "server/db.json"));
const middlewares = jsonServer.defaults({
static: "node_modules/json-server/dist"
});
server.use(middlewares);
server.use(jsonServer.bodyParser);
server.use(function(req, res, next) {
setTimeout(next, 0);
});
function createSlug(value) {
return value
.replace(/[^a-z0-9_]+/gi, "-")
.replace(/^-|-$/g, "")
.toLowerCase();
}
function validateProduct(product) {
if (!product.title) return "Title is required.";
if (!product.tagline) return "Tagline is required.";
if (!product.description) return "Description is required.";
return "";
}
server.use((req, res, next) => {
if (req.method === "POST") {
req.body.createdAt = Date.now();
}
next();
});
server.post("/products/", function(req, res, next) {
const error = validateProduct(req.body);
if (error) {
res.status(400).send(error);
} else {
req.body.slug = createSlug(req.body.title);
next();
}
});
server.use(router);
const port = 3033;
server.listen(port, () => {
console.log(`JSON Server is running on port ${port}`);
});
You appear to be attempting to start multiple web servers from your npm start command in a single app engine instance:
"start": "cross-env NODE_ENV=production node server.js & node createMockDB.js & node apiServer.js"
I've never seen this before and I doubt very much GAE can deal with it. GAE expects a single node application serving requests on port process.env.PORT.
If you want multiple different servers running within the same GAE project, you should probably deploy them as independently as different services. Each of them should have an app.yaml that specifies a unique service name, and you'll deploy them each independently. The documentation here is fairly comprehensive.

How to disable CORS on localhost using expressjs

I want to disable CORS on localhost for a specific url, here is my code
const express = require('express')
const app = express()
const port = 3000
app.use(express.static('files'))
app.all('/no-cors/', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "fake");
next();
});
app.get('/', (req, res) => res.send('Hello World!'));
app.get('/sample-json', (req, res) => res.json({"foo": "bar"}));
// it shld show error in console
app.get('/no-cors/sample-json', (req, res) => {
res.json({"cors": "off"});
});
app
.listen(port, () => console.log(Example app listening on port 3000'))
but I open http://localhost:3000/no-cors/sample-json it still show me the json.
Path argument in express().get(path,...) is evaluated as whole string. Path in Express (and URL generally, not only in Express) does not work as folder structure.
That’s why the address /no-cors/sample-json is not catched with your app.all().
If you want it to work, try the path as /no-cors/*

How to disable the Etag in npm express at configuration level?

I am new to nodejs and npm. I have been task to disable Etag generation in the configuration level of npm express. I am finding the answer as
app.set('etag', false); // turn off and similar to this in online.
Disabling in the sense not in the application code, I have to disable in the express configuration of npm. Like for every request I need to get response only from server as application/json and the status should only be 200. Please help to find a solution.
sample code:
const express = require('express')
const app = express()
const port = 9000
app.get('/proj/v1/test', (req, res) => {
// app.set('etag', false);
res.status(200).json({status: "OK"});
}
)
app.listen(port)
Robert thanks for your help. My Lead was mentioning about middleware concept. The actual response he needed is to verify the every request. I got a fix with the below code
const express = require('express');
const app = express();
const port = 9000;
app.use((req, res, next) => {
app.disable('etag');
console.log('Etag removed');
next();
})
app.get('/proj/v1/test', (req, res) => {
res.status(200).json({status: "OK"});
}
)
app.get('/proj/v1/test2', (req, res) => {
res.status(200).json({version: "1"});
}
)
console.log('Server started');
app.listen(port);