Can Not POST NodeJS Express - node.js

I was trying to make an axios post request to an express server and I receive that Error: Request failed with status code 404 at createError. Postman says Can Not POST. I don't know what could be wrong, i'm new in all this, so all the help it's good, thanks.
Axios and Express server are from 2 different link. They are google cloud function.
Thanks for the help
Axios Post Request :
exports.notification = (req, res) => {
var axios = require('axios');
var https = require('https');
var bodyParser = require('body-parser');
var config = {
headers: {
'Content-Type' : 'application/x-www-form-urlencoded',
'Content-Type' : 'text/html',
'Content-Type' : 'application/json' }
};
var info = {
ids:[req.body.id,req.body.id1],
type: req.body.type,
event: req.body.action,
subscription_id: req.body.subid,
secret_field_1:null,
secret_field_2:null,
updated_attributes:{
field_name:[req.body.oname,req.body.nname]}
};
var myJSON = JSON.stringify(info);
return axios.post('https://us-central1-copper-mock.cloudfunctions.net/api/notification-example', myJSON)
.then((result) => {
console.log("DONE",result);
})
.catch((err) => {
console.log("ERROR",err);
console.log("Error response:");
console.log(err.response.data);
console.log(err.response.status);
console.log(err.response.headers);
})
};
Express Server
const express = require ('express');
const https = require ('https');
const bodyParser = require ('body-parser');
const app = express();
const port = 8080;
// ROUTES
var router = express.Router(); // get an instance of router
router.use(function(req, res, next) { // route middleware that will happen on every request
console.log(req.method, req.url); // log each request to the console
next(); // continue doing what we were doing and go to the route
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use('/',require ('./Routers/API/home'));
app.use('/leads',require ('./Routers/API/leads'));
app.use('/people',require ('./Routers/API/people'));
app.use('/companies',require ('./Routers/API/companies'));
app.use('/opportunities',require ('./Routers/API/opportunities'));
app.use('/projects',require ('./Routers/API/projects'));
app.use('/tasks',require ('./Routers/API/tasks'));
app.use('/activities',require ('./Routers/API/activities'));
app.use('/notification-example',require ('./Routers/API/notification_example'));
app.use('/', router); // apply the routes to our application
// START THE SERVER
// ==============================================
app.listen(port);
console.log('Listening ' + port);
module.exports={
app
};
Notification Route
const express = require('express');
const router = express.Router();
//const notification_example = require('../../Notification');
router.get('/', function(req, res) {
console.log('DATA',JSON.parse(res.data));
console.log('BODY',JSON.parse(res.body));
});
module.exports = router;

Related

Node Express how to edit the app.post url

I have a simple example of Google App Script sending a post request to my Node application. This is working perfectly.
GAS
function send_webhook_test() {
const url = 'http://my.ip.address/folder'
var body = {msg:'hello from gas'}
var params = {
'method': 'post',
'muteHttpExceptions': true,
'contentType': 'application/json',
'payload':JSON.stringify(body)
};
var res = UrlFetchApp.fetch(url, params);
console.log(res)
}
Node
const express = require("express")
const bodyParser = require("body-parser")
const app = express()
const PORT = 3000
const path = require('path');
app.use(bodyParser.json())
app.get('/',function(req,res){
res.sendFile(path.join(__dirname+'/index.html'));
});
app.post('/', (req, res) => {
console.log(req)
console.log(req.body)
res.status(200).end()
})
app.listen(PORT, () => console.log(`Server running on port ${PORT}`))
I would like to change the app.post from ('/') to ('someValue'). So I make the following edit:
GAS
const url = 'http://my.ip.address/folder/someValue'
Node
app.post('/someValue', (req, res) => {
console.log(req)
console.log(req.body)
res.status(200).end()
})
But this returns the error Cannot POST //someValue. How do I correctly change the post url?
Your request is adding a '/'char before the /someValue route.
You can use a middleware to sanitize the path before searching for the routes, or you can review your GAS code to remove the duplicated '/'

How do I grab json from an external api (serp api) from my backend and then make that same data available for my front end application?

Right now I have a front end react application using axios and and a backend server using node.js and express. I cannot for the life of me get my serp api data to post so that my front end can get it through axios and display the json data. I know how to get data to the front end but I am not a backend developer so this is proving to be incredibly difficult at the moment. I'm able to get the data from the the external api, I just don't know how to post it once I get it. Also I would not like to have all these request running on server.js so I created a controller but I think that is where it is messing up. Any help is appreciated
//pictures controller
const SerpApi = require('google-search-results-nodejs');
const {json} = require("express");
const search = new SerpApi.GoogleSearch("674d023b72e91fcdf3da14c730387dcbdb611f548e094bfeab2fff5bd86493fe");
const handlePictures = async (req, res) => {
const params = {
q: "Coffee",
location: "Austin, Texas, United States",
hl: "en",
gl: "us",
google_domain: "google.com"
};
const callback = function(data) {
console.log(data);
return res.send(data);
};
// Show result as JSON
search.json(params, callback);
//res.end();
}
// the above code works. how do i then post it to the server so that i can retrieve it to the backend?
module.exports = {handlePictures};
//server.js
const express = require('express');
const app = express();
const path = require('path');
const cors = require('cors');
const corsOptions = require('./config/corsOptions');
const { logger } = require('./middleware/logEvents');
const errorHandler = require('./middleware/errorHandler');
const cookieParser = require('cookie-parser');
const credentials = require('./middleware/credentials');
const PORT = process.env.PORT || 3500;
// custom middleware logger
app.use(logger);
// Handle options credentials check - before CORS!
// and fetch cookies credentials requirement
app.use(credentials);
// Cross Origin Resource Sharing
app.use(cors(corsOptions));
// built-in middleware to handle urlencoded form data
app.use(express.urlencoded({ extended: false }));
// built-in middleware for json
app.use(express.json());
//middleware for cookies
app.use(cookieParser());
//serve static files
app.use('/', express.static(path.join(__dirname, '/public')));
// routes
app.use('/', require('./routes/root'));
app.use('/pictures', require('./routes/api/pictures'));
app.all('*', (req, res) => {
res.status(404);
if (req.accepts('html')) {
res.sendFile(path.join(__dirname, 'views', '404.html'));
} else if (req.accepts('json')) {
res.json({ "error": "404 Not Found" });
} else {
res.type('txt').send("404 Not Found");
}
});
app.use(errorHandler);
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
//api/pictures.js
const picturesController= require('../../controllers/picturesController');
const express = require('express')
const router = express.Router();
// for POST request use app.post
router.route('/')
.post( async (req, res) => {
// use the controller to request external API
const response = await picturesController.handlePictures()
// send the response back to client
res.json(response)
})
module.exports = router;
You just need to return the result from SerpApi in your handlePictures function. To do this make a new Promise and when search.json runs callback do what you need with the results and pass it in resolve.
Your picturesController.js with an example of returning all results.
//pictures controller
const SerpApi = require("google-search-results-nodejs");
const { json } = require("express");
const search = new SerpApi.GoogleSearch(process.env.API_KEY); //your API key from serpapi.com
const handlePictures = async (req, res) => {
return new Promise((resolve) => {
const params = {
q: "Coffee",
location: "Austin, Texas, United States",
hl: "en",
gl: "us",
google_domain: "google.com",
};
const callback = function(data) {
resolve(data);
};
search.json(params, callback);
});
};
module.exports = { handlePictures };
Output:
And I advise you to change your API key to SerpApi to prevent it from being used by outsiders.
Since I don't have the full context of your App I can just assume the context. But given the fact that you already have wrapped the logic of calling the external API into a dedicated controller you can use it in the following way in an express app (used the hello world example from express):
// import your controller here
const express = require('express')
const app = express()
const port = 3000
// for POST request use app.post
app.get('/', async (req, res) => {
// use the controller to request external API
const response = await yourController.method()
// send the response back to client
res.json(response)
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
Here's an example how to execute the http request from the frontend:
const response = await fetch('http://localhost:3000') // result from res.json(response)

Getting a cors error running vue with express

I'm running my Vue App on my express server (nodejs running on port 60702) like:
'use strict';
const fs = require('fs');
const path = require('path');
const express = require('express');
var https = require('https');
const morgan = require('morgan');
const cors = require('cors');
const bodyParser = require('body-parser');
const nconf = require('./config');
const pkg = require('./package.json');
const swaggerSpec = require('./swagger');
const swaggerUI = require('swagger-ui-express');
const app = express();
app.options('*', cors()) // include before other routes
// create a write stream (in append mode)
var accessLogStream = fs.createWriteStream(path.join(__dirname, 'access.log'), {
flags: 'a'
});
// setup the logger
app.use(morgan('combined', {
stream: accessLogStream
}));
// Enable CORS (cross origin resource sharing)
app.use(cors());
// Set up body parser
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
// Load the Vue App
app.use(express.static(path.join(__dirname, '../../client/pvapp-client/dist')));
app.get('/api/version', (req, res) => res.status(200).send(pkg.version));
const userRouter = require('./routes/user');
const systemRouter = require('./routes/system');
const yieldRouter = require('./routes/yield');
const adjustmentRouter = require('./routes/adjustmentfactors');
app.use('/user', userRouter);
app.use('/system', systemRouter);
app.use('/yield', yieldRouter);
app.use('/adjustmentfactors', adjustmentRouter);
//Default route
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '../../client/pvapp-client/dist/index.html'));
});
//const listener = app.listen(nconf.get('port'), () => console.log(`Ready on port ${listener.address().port}.`));
https.createServer({
key: fs.readFileSync('certs/apache-selfsigned.key'),
cert: fs.readFileSync('certs/apache-selfsigned.crt')
}, app)
.listen(nconf.get('port'), function() {
console.log(`App listening on port ${nconf.get('port')}! Go to https://192.168.51.47:${nconf.get('port')}/`)
});
The User router is:
router.post('/login', async (req, res) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods', 'GET,POST");
let compareUser = await db.query('SELECT * FROM app_users WHERE username=? LIMIT 1', [req.body.username]); // use db.query() to retrieve the password
if (compareUser.length < 1) // compareUser is an array with at most one item
res.sendStatus(403);
let valid = bcrypt.compareSync(req.body.password, compareUser[0].password);
if (!valid)
res.sendStatus(403);
let user = new User(compareUser[0]);
const token = jwt.sign({
user
}, nconf.get('jwtToken'), {
expiresIn: '14d'
});
Object.assign(user, {
token
});
res.json(user);
});
The vue config is:
module.exports = {
baseUrl: process.env.NODE_ENV === 'production' ? '/vue' : '/',
devServer: {
port: 60702,
https: true,
disableHostCheck: true
}
};
Axios:
const apiClient = axios.create({
baseURL: `https://192.168.51.47:60702`,
withCredentials: false, // This is the default
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
})
export default {
// user Endpoints
getUser(email) {
return apiClient.get(`/user/${email}`)
},
registerUser(user) {
return apiClient.post(`/user/register`, user)
},
loginUser(user) {
return apiClient.post(`/user/login`, user)
},
But even if I included cors I'm getting:
Cross-source (cross-origin) request blocked: The same source rule
prohibits reading the external resource on
https://143.93.46.35:60702/user/login. (Reason: CORS request failed).
The axios call in vue also has the correct baseUrl with the port.
I checked the POST request to the backend at /user/login with Postman and get the exprected correct request, too.
It was solved by re-creating the dist folder with
npm run build
Thanks to #Dan for his help
Don't use apiClient. Do a get with the full url, rebuild your app,
delete old dist folder, CTRL+F5 refresh once loaded. In fact, put a
"?" on the end of the url and make sure you see it in Chrome headers

express server returns 405 on routes in production

Im building an express instance for the first time and ive run into an issue where everything works locally, but when deployed sending a post request to the route responds:
Failed to load resource: the server responded with a status of 405
(Not Allowed)
Ive included the relevant code below:
server/index.js
const express = require('express');
const bodyParser = require('body-parser')
const path = require('path');
const app = express();
app.use(express.static(path.join(__dirname, 'build')));
const routes = require('./routes')(express)
require('./db')
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
app.listen(process.env.PORT || 8080);
app.use('/', routes);
routes/index.js
var mongoose = require("mongoose");
const randomId = require('random-id');
const Submissions = require('../api/Submissions')
// routes/index.js
module.exports = (express) => {
// Create express Router
var router = express.Router();
// add routes
router.route('/submission')
.post((req, res) => {
let newSubmission = new Submissions(req.body);
newSubmission._id = randomId(17, 'aA0');
// Save the new model instance, passing a callback
newSubmission.save(function(err,response) {
if (err) {
console.log(err)
} else {
res.setHeader('Content-Type', 'application/json');
res.json({'success':true})
}
// saved!
})
});
return router;
}
client.js
let submission = {
name: this.state.newSubmission.name.trim(),
body: this.state.newSubmission.body.trim(),
email: this.state.newSubmission.email.trim(),
};
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(submission),
};
fetch("/submission", requestOptions)
.then((response) =>
response.json().then((data) => ({
data: data,
status: response.status,
}))
)
.then((res) => {
if (!res.data.success) {
notifier.warning('Failed to submit');
} else {
notifier.success('Submission successful');
}
});

Cant set headers after they are sent

I am using express backend with a react frontend everything is working fine but occasionally i get error
Cant set header after they are sent
and server gets down.i searched few ways this error might happen but in my code i could not find such cases.i tried to be simple as possible in the code.can anyone please point me what might be the issue?
Server.js file
// call the packages we need
const addItem = require('./controllers/addItem');
const addCategory = require('./controllers/addCategory');
const addSubCategory = require('./controllers/addSubCategory');
const getSubCategory = require('./controllers/getSubCategoryByCategory');
const getCategory = require('./controllers/getAllCategory');
const getAllItems = require('./controllers/getAllItems');
const cors = require('cors');
const express = require('express');
// call express
const app = express(); // define our app using express
const bodyParser = require('body-parser');
// configure app to use bodyParser()
// this will let us get the data from a POST
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
const port = process.env.PORT || 8080; // set our port
// ROUTES FOR OUR API
// =============================================================================
const addItemRoute = express.Router(); // get an instance of the express Router
const getCategoryRoute = express.Router();
const addCategoryRoute = express.Router();
const addSubCategoryRoute = express.Router();
const getSubCategoryRoute = express.Router();
const getAllItemsRoute = express.Router();
getCategoryRoute.get('/get_category', (req, res) => {
getCategory(res);
});
addCategoryRoute.post('/add_category', (req, res) => {
addCategory(req.body.name, res);
});
getSubCategoryRoute.get('/get_subcategory/:catId', (req, res) => {
getSubCategory(req.params.catId, res);
});
addSubCategoryRoute.post('/add_subcategory', (req, res) => {
addSubCategory(req.body.name, req.body.cat_id, res);
});
// code, name, quantity, length, description and subcategory id should be passed as parameters
addItemRoute.post('/add_item', (req, res) => {
addItem(req.body.item, res);
});
getAllItemsRoute.get('/get_items', (req, res) => {
getAllItems(res);
});
// more routes for our API will happen here
// REGISTER OUR ROUTES -------------------------------
// all of our routes will be prefixed with /api
app.use('/api', addItemRoute);
app.use('/api', getCategoryRoute);
app.use('/api', addCategoryRoute);
app.use('/api', addSubCategoryRoute);
app.use('/api', getSubCategoryRoute);
app.use('/api', getAllItemsRoute);
// START THE SERVER
// =============================================================================
app.listen(port);
console.log(`Server started on port ${port}`);
getAllCategories() function
Object.defineProperty(exports, '__esModule', {
value: true,
});
const pool = require('./connection');
module.exports = function (res) {
pool.getConnection((err, connection) => {
if (err) {
connection.release();
return res.json({ code: 100, status: 'Error in connection database' });
}
console.log(`connected as id ${connection.threadId}`);
connection.query('select * from category;', (err, rows) => {
connection.release();
if (!err) {
return res.json(rows);
}
});
connection.on('error', err => res.json({ code: 100, status: 'Error in connection database' }));
});
};
If you get an error in connection.query() you send a response with res.json(). This error is caught in connection.on('error') where you send another response. You can't send two responses to the same request. It seems that in this case, you don't really need connection.on() at all or if you have it to catch other errors, don't send a response on connection.query()'s error.

Resources