"431 Request Header Fields Too Large" - javascript

so I get this error every time I re-render the site
" GET http://localhost:3000/api/ShopItems 431 (Request Header Fields Too Large)"
I can see that my fetch doesn't go as planed and invokes the error above ⬆️
The chrome developer tool points me to the "ShopItemsActions" fill
import { FETCH_SHOPITEMS } from "../types"
export const fetchShopItems = () => async (dispatch) => {
const res = await fetch("/api/ShopItems");
const data = res.json();
console.log(data);
dispatch({
type: FETCH_SHOPITEMS,
payload: data
});
}
The chrome developer tool mark the third line "const res = await fetch("/api/ShopItems")"
Question: how can i fix this error?
Edit:
the server side code
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const shortid = require('shortid');
const app = express();
app.use(bodyParser.json());
mongoose.connect("mongodb://localhost/bread_project_db", {
useNewUrlParser:true,
useCreateIndex: true,
useUnifiedTopology:true,
});
const ShopItem = mongoose.model(
"ShopItems",
new mongoose.Schema({
id: { type: String, default: shortid.generate },
name: String,
image: String,
price: Number,
info: String,
flourType: [String],
}))
app.get("/api/ShopItems", async (req, res)=>{
const ShopItems = await ShopItem.find({});
res.send(ShopItems);
});
app.post("/api/ShopItems", async (req, res)=>{
const newShopItem = new ShopItem(req.body);
const savedShopItem = await newShopItem.save();
res.send(savedShopItem);
});
app.delete("/api/ShopItems/:id", async (req, res) => {
const deletedShopItem = await ShopItem.findByIdAndDelete(req.params.id);
res.send(deletedShopItem);
});
const port = process.env.PORT || 5000;
app.listen( port, () => console.log(`server at http://localhost:${port}`));
I am using postman and I dont have cURL installed for some reason.
the postman just show this:
431 Request Header Fields Too Large
The server is unwilling to process the request because either an individual header field, or all the header fields collectively, are too large. Proposed in an Internet-Draft.

Related

Next.js and Express.js give CORS error, API queries only work at build time

I have a project where I use Next.js on the front-end and Express.js on the back.
Front-end side
The 'pages' file contains 'index.js'. In it, I am sending the following request.
import Home from "./home/home";
import axios from "axios";
import { useState } from "react";
export default function Index({ data }) {
const [products, setProducts] = useState(data);
const [start, setStart] = useState(1);
const getMoreProducts = async () => {
setStart(start + 1);
const { newProducts } = await axios.get(
`${process.env.NEXT_PUBLIC_BACK_END}/test`
);
setProducts([...products, ...newProducts]);
};
return (
<div>
<Home data={products} />
<button onClick={getMoreProducts}> Load more {start}</button>
</div>
);
}
export async function getServerSideProps(context) {
// Fetch data from external API
const { data } = await axios.get(
`${process.env.NEXT_PUBLIC_BACK_END}/productlist/pagination`,
{
params: {
page: 1,
limit: 5,
},
}
);
return {
props: {
data: data || {},
},
};
// Pass data to the page via props
}
Back-end side
const express = require("express");
var cors = require('cors')
const app = express();
require("dotenv").config();
const mongoose = require("mongoose");
mongoose.connect(
"*********",
{ useNewUrlParser: true }
);
const db = mongoose.connection;
db.on("error", (err) => console.error(err));
db.once("open", () => console.log("Connected to Database "));
app.use(express.json());
const productlistRouter = require("./routes/productlist");
const test = require("./routes/test");
app.use("/productlist", productlistRouter);
app.use("/test", test);
app.use(cors())
app.listen(3000, () => console.log("Server is running"));
And here is my Route code :
const express = require("express");
const router = express.Router();
const Product = require("../models/product");
const cors = require("cors");
const corsOptions = {
headers: [
{ key: "Access-Control-Allow-Credentials", value: "true" },
{ key: "Access-Control-Allow-Origin", value: "*" },
// ...
],
origin: "*",
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
};
router.get("/showall", async (req, res) => {
try {
const product = await Product.find();
res.json(product);
} catch (err) {
res.status(500).json({ message: err.message });
}
});
router.get("/pagination", cors(corsOptions), async (req, res) => {
const page = req.query.page;
const limit = req.query.limit;
const startIndex = (page - 1) * limit;
const endIndex = page * limit;
const products = await Product.find();
const result = products.slice(startIndex, endIndex);
res.json(result);
});
So, When the page is first built with Next.js, the api works, but when I click the 'Load more' button, it gives a CORS error. When I use the same query with 'postman' and other tools, it does not give any error.
On the Next.js side, it works when I send a query to another 3rd party API., but it doesn't work when I send it to my own back-end. And no matter what page or component I do this in, only the APIs that are created at the build time are working.
What could be the reason for this? and how can i solve it? I've read and searched a few articles about cors, but I still haven't found a solution for days.
CORS should be placed on top level as javascript is executed one by one line. Place app.use(cors()) just above the line of app.use("/productlist", productlistRouter);

How to fix MongoDB connection error in node.js

I'm getting a cors error when trying to login into my MERN app
Screenshot.It's working fine locally and in the Network tab it shows a 503 error code.
My Heroku logs show these messages.
const err = new MongooseError(message);
MongooseError: Operation users.findOne() buffering timed out after 10000ms
But, I'm getting the 'User Name verified' console log in the Heroku logs which is present in the validation.js file below. So the backend connection is fine I think.
I used 0.0.0.0/0 in MongoDB network access and used cors package for all origin.
Also tried using mongoose.connect using async/await, and using the older drivers in MongoDB but nothing seems to work. If anyone knows how to fix it please respond.
Here is my code in node.js.
index.js
const express = require('express')
const cors = require('cors')
const DBConnect = require('./mongo')
const Login = require('./routes/login')
const Google = require('./routes/google')
const Register = require('./routes/register')
const SaveData = require('./routes/saveData')
require('dotenv').config()
const port = process.env.PORT || 5000
const app = express()
const corsOptions = {
origin: '*',
credentials: true,
optionSuccessStatus: 200
}
app.use(cors(corsOptions))
app.use(express.json())
DBConnect().then(()=>console.log('DB Connection successfull!'))
app.get('/', (req,res)=>{ res.json('Server running')})
app.use('/api/gauth', Google)
app.use('/api/login', Login)
app.use('/api/register', Register)
app.use('/api/save', SaveData)
app.listen(port,()=>console.log(`Server listening on port ${port}`))
mongo.js
const mongoose = require('mongoose')
module.exports = async () => {
const username = process.env.USER_NAME
const password = process.env.PASSWORD
const cluster = process.env.CLUSTER
const dbname = process.env.DB_NAME
const url = `mongodb+srv://${username}:${password}#${cluster}.mongodb.net/${dbname}?retryWrites=true&w=majority`
const mongooseOptions = {
useNewUrlParser: true,
useUnifiedTopology: true
}
await mongoose.connect(url, mongooseOptions)
.then(x => console.log(`Connected to MongoDB : ${x.connections[0].name}`))
.catch(err => console.error('Error connecting to mongo', err))
}
google.js
const app = require('express')()
const googleAuth = require('../components/validation')
const userModel = require('../components/models')
const bcrypt = require('bcrypt')
const JWT = require('jsonwebtoken')
const dotenv = require('dotenv')
dotenv.config()
app.post('/', async (req,res)=>{
const user = await googleAuth(req.body.token)
const emailExist = await userModel.findOne({ email: user.email })
const token = JWT.sign({_id: user.id}, process.env.TOKEN_KEY)
const data = {
token: token,
email: user.email,
name: user.name,
image: user.image,
data: emailExist && emailExist.data || []
}
if(!emailExist){
const salt = await bcrypt.genSalt(10)
const cipherPass = await bcrypt.hash(user.id, salt)
const newUser = new userModel({
username: user.name,
email: user.email,
password: cipherPass,
image: user.image,
data: []
})
try{
await newUser.save()
res.status(200).json(data)
}catch (err){
res.status(500).json(err)
}
}else{
res.status(200).json(data)
}
})
module.exports = app
validation.js
const { OAuth2Client } = require('google-auth-library')
const client = new OAuth2Client(process.env.OAUTH_ID)
const googleAuth = async token => {
const ticket = await client.verifyIdToken({
idToken: token,
audience: process.env.OAUTH_ID
})
const payload = ticket.getPayload()
// console.log('Paylod:', payload)
console.log(`User ${payload.name} verified`)
const { sub, name, email, picture } = payload
const userId = sub
return { id:userId, name:name, email:email, image:picture}
}
module.export = googleAuth

Why Expres Async Errors send different result as expected

I found a nice npm package by the name of Express Async Errors which according to the documentation, it's really nice to use.
However, if I implement it, the server will crash.
Here is my Route handler code
Controller
const { Genre } = require("../models");
const { StatusCodes } = require("http-status-codes");
const getGenre = async (req, res) => {
const genre = await Genre.findById({ _id: req.params.id });
if (!genre) {
return res.status(StatusCodes.BAD_REQUEST).json({
message: "The genre with the given ID was not found.",
});
}
res.status(StatusCodes.OK).json({ status: "success", data: genre });
};
*router*
const express = require("express");
const { authenticate, admin } = require("../middleware");
const router = express.Router();
const { schemaValidator } = require("../middleware");
const validateRequest = schemaValidator(true);
const { genres } = require("../controllers");
const { getAllGenres, getGenre, createGenre, updateGenre, deleteGenre } =
genres;
.route("/genres")
.get(getAllGenres)
Main Application Entry
require("express-async-errors");
//Routers
const routers = require("./router");
const connectDB = require("./DB/connect");
const express = require("express");
const app = express();
app.use(config.get("URI"), routers);
app.use(notFoundMiddleware);
const start = async () => {
const port = process.env.PORT || 3000;
const connectionString = config.get("mongoDB.connString");
await connectDB(connectionString)
.then(() => DBdebug(`Connected to MongoDB: ${connectionString}`))
.catch(() => console.log("MongoDB connection failure"));
app.listen(port, () => debug(`Listening on port ${port}...`));
};
start();
Above code is imported into index.js together with express-async-errors.
According to the document, if I create an error, express-async-errors has to handle this without crashing the application. My question is what I'm doind wrong???
I shut down the Mongo-driver just to create a scenario that the server is down with a status 503.
MongooseServerSelectionError: connect ECONNREFUSED 127.0.0.1:27017
at Function.Model.$wrapCallback (/Volumes/Seagate/lib/model.js:5087:32)
at /Volumes/Seagate/lib/query.js:4510:21
at /Volumes/Seagate/node_modules/mongoose/lib/helpers/promiseOrCallback.js:32:5
From previous event:
at promiseOrCallback (/Volumes/Seagate/node_modules/mongoose/lib/helpers/promiseOrCallback.js:31:10)
at model.Query.exec (/Volumes/Seagate/node_modules/mongoose/lib/query.js:4509:10)
at model.Query.Query.then (/Volumes/Seagate/node_modules/mongoose/lib/query.js:4592:15)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
Instead of above error, I should see "Something went wrong" as the default message in Postman without crashing the application.
Can someone point me to the right direction?
NB: The link which I had used us is https://www.npmjs.com/package/express-async-errors
Thank you very much in advanced.
After two days of researching my problem, I finally convinced my self that the problem was me and found a solution for this particular matter.
I have created an ErrorHandlerMiddleware and in the particular middleware I check if the error is an instance of MongooseError object, if this is the case, I just send for now an custom message.
See code below:
const { StatusCodes } = require("http-status-codes");
const { CustomApiError } = require("../errors");
const Mongoose = require("mongoose");
const errorHandlerMiddleware = (err, req, res, next) => {
console.log("errorMiddleWare");
if (err instanceof CustomApiError) {
return res.status(err.statusCode).json({ message: err.message });
}
if (err instanceof Mongoose.Error) {
return res.status(StatusCodes.INTERNAL_SERVER_ERROR).json({
message: "There is a technical problem, please try again later",
});
}
};
module.exports = { errorHandlerMiddleware };
In main application entry, I just pass errorHandlerMiddleware as a argument reference in app.use.
See code below
require("express-async-errors");
//Routers
const routers = require("./router");
const connectDB = require("./DB/connect");
const express = require("express");
const app = express();
app.use(config.get("URI"), routers);
app.use(notFoundMiddleware);
app.use(errorHandlerMiddleware);
const start = async () => {
const port = process.env.PORT || 3000;
const connectionString = config.get("mongoDB.connString");
await connectDB(connectionString)
.then(() => DBdebug(`Connected to MongoDB: ${connectionString}`))
.catch(() => console.log("MongoDB connection failure"));
app.listen(port, () => debug(`Listening on port ${port}...`));
};
start();
And this is the final result in PostMan:
If there are any comments regarding this solution, feel free to do this.
By comments and can learn more!!!
Thank you in advanced and keep coding!!!!

How to send SMS to a number stored in a JSON file?

I need to send SMS (by Twilio) to defined phone numbers, which are saved in the phone.json file when the submit button will be clicked.
I am using node.js
How am I going to do this?
This is how my phone.json looks:
[
{"Nombre": "Nombre1" ,
"Numero": "+34...."
},
{"Nombre": "Nombre2",
"Numero": "+34..."
}
]
In SMS.js I would create a function like this:
function submit() {
client.messages
.create({
body: "content",
from: "+....",
to: ""}) //this number should come from phone.json
.then(message => console.log(message.sid));
}
This is how my index.js looks:
const http =require('http');
const express = require('express');
const MessagingResponse = require('twilio').twiml.MessagingResponse;
const { fstat } = require('fs');
const { response } = require('express');
const info = require("./database.json");
const app = express();
app.use(express.static("public"));
app.use(express.urlencoded({extended: true}));
app.listen(8000, console.log(`Server running at http://localhost:8000`));
I would be very happy about every suggestion.
I'm assuming you want to do this server-side in Node.js, then you need fs to read the JSON and then you just loop over it in your submit() like this:
import fs from "fs"; // CommonJS syntax: const fs = require("fs");
phone_numbers = JSON.parse(fs.readFileSync("phone.json", "utf8"));
phone_numbers.forEach(function(item, index) {
console.log(item, index);
client.messages
.create({
body: "content",
from: "+....",
to: item["Numero"],
})
.then(message => console.log(message.sid));
});

How to get information from instagram with cheerio and express

I am trying to get the username of the profile on the url of that users page. Just to figure out the basic of getting Instagram data
The code below is what I have tried to do and miserably failed(also I am a beginner sorry for bad code)
const express = require('express');
const bodyParser = require('body-parser');
const request = require('request-promise');
const path = require('path');
var cheerio = require('cheerio');
const app = express()
var followers = [];
app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: true }));
app.set('view engine', 'ejs')
app.get('/', function (req, res) {
request({
method: 'GET',
url: 'https://www.instagram.com/unrivaledhype/'
}, function(err, response, body, callback) {
if(err) return console.error(err);
$ = cheerio.load(url);
var post = $("*");
var follwerCount = post.find('h1').text();
console.log(follwerCount);
followers.push({follwerCount: follwerCount})
});
res.send(JSON.stringify(followers, null, 4));
});
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
It just displays follwerCount:"" but(even though I named it misspelled followerCount I went for the username) although if someone can show me how to get the follower count that would be greatly appreciated.
Unfortunately, Instagram pages are rendered on the client side, so it is not possible to get information like the number of followers through this way.
A solution to this problem would be to use puppeteer.
With puppeteer you can start a headless version of chrome, which also interprets javascript, so that Instagram pages get rendered completely.
Example code:
const puppeteer = require('puppeteer')
class InstagramClient {
async start() {
this.browser = await puppeteer.launch({
headless: true //When set to true, a new browser window will ge opened
})
}
async stop() {
await this.browser.close()
}
async getFollowers(username) {
if (!this.browser) throw new Error('Browser not started')
const page = await this.browser.newPage()
await page.goto(`https://instagram.com/${username}/`)
const pageExists = await page.evaluate(_ => {
return document.querySelector('.error-container') === null
})
if (!pageExists) {
throw new Error(`Page of ${username} doesn't exist`)
}
//Wait until the page got completly renderer
await page.waitForSelector('h1')
const followers = await page.evaluate(username => {
//This code will get executed on the instagram page
//Get the number of followers
const followers = document.querySelector(`a[href="/accounts/login/?next=%2F${username}%2Ffollowers%2F&source=followed_by_list"]`).querySelector('span').innerText
//Return the number of followers back to the node process
return followers
}, username)
page.close()
return followers
}
}
module.exports = InstagramClient
const InstagramClient = require('./utils/instagram-client')
async function start() {
const client = new InstagramClient()
await client.start()
console.log('#instagram:', await client.getFollowers('instagram'))
console.log('#unrivaledhype:', await client.getFollowers('unrivaledhype'))
console.log('#teslamotors:', await client.getFollowers('teslamotors'))
await client.stop()
}
start()
Output:
#instagram: 309m
#unrivaledhype: 3,230
#teslamotors: 6m
If you want a more detailed explanation, check out this video:
A Guide to Web Scraping with NodeJS
Express example:
const express = require('express')
const InstagramClient = require('./utils/instagram-client')
const app = express()
const client = new InstagramClient()
app.get('/:instagramName/followers', async (request, response) => {
const instagramName = request.params.instagramName
try {
const followers = await client.getFollowers(instagramName)
response.json({
success: true,
followers: followers
})
} catch (e) {
response.json({
success: false,
error: e.toString()
})
return
}
})
async function start() {
await client.start()
app.listen(3000, _ => console.log('Server is listening on port 3000'))
}
start()

Categories

Resources