I'm having some troubles trying to stablish a REST API with nodeJS and express. The following code defines two routes, "stores" and "user".
Surprisingly, the route to "/user" is working nice but when a request arrives to "/stores" the request body appears undefined. I've searched for a solution but nothing seems to work for me.
Both controllers have the same structure.
What am I doing wrong?
var express = require("express"),
app = express(),
bodyParser = require("body-parser"),
methodOverride = require("method-override"),
mongoose = require('mongoose');
// Connection to DB
mongoose.connect('mongodb://localhost/appDB', function(err, res) {
if(err) throw err;
console.log('Connected to Database');
});
// Middlewares
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(methodOverride());
//Import models and controllers
var userModel=require("./models/user.js")(app,mongoose);
var storeModel=require("./models/store.js")(app,mongoose);
var usersController=require("./controllers/users.js");
var storesController=require("./controllers/stores.js");
//Router options
var router=express.Router();
router.route('/stores')
.get(storesController.getNearestStores);
router.route('/user')
.post(usersController.addUser);
app.use(router);
//Start server
app.listen(3000, function() {
console.log("Node server running on http://localhost:3000");
});
Thank you very much.
P.S.:First time with nodejs and express(and even mongo)
This is because there is no body on a GET request in the http standard. Only POST and PUT.
What you want to do instead is use a query string
get
/stores?location=mystore
this way on your callback you have access to req.query
req.query
{
location: 'mystore'
}
HTTP GET with request body
This gave me the solution, get requests don't accept parameters under HTTP standard.
Related
I am working on Salesforce and Slack integration. And I don't know much about javascript and its related technologies. Could you please look into the code and let me know whats missing?
// Import express and request moduless
var express = require('express');
var request = require('request');
var url = require('url');
var clientId = '****';
var clientSecret = '****';
var SF_LOGIN_URL = "http://login.salesforce.com";
var SF_CLIENT_ID = "****";
// We define the port we want to listen to. Logically this has to be the same port than we specified on ngrok.
const PORT=4390;
// Instantiates Express and assigns our app variable to it
var app = express();
app.enable('trust proxy');
//var server = http.createServer(app);
//Lets start our server
app.listen(PORT, function () {
//Callback triggered when server is successfully listening.
console.log("Example app listening on port " + PORT);
});
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
// Route the endpoint that our slash command will point to and send back a simple response to indicate that ngrok is working
app.post('/oauth', function(req, res) {
oauth(req, res);
});
function oauth(req, res){
res.redirect(200, `${SF_LOGIN_URL}/services/oauth2/authorize?response_type=code&client_id=${SF_CLIENT_ID}&redirect_uri=****/oauth&display=touch}`);
console.log(url.location.href);
}
It looks to me like you're redirecting an authorization request to Salesforce, and asking Salesforce.com (SFDC) to redirect it back to ****/oauth (from the redirect_uri= query parameter to the SFDC URL.
Are you hoping it will get redirected back to your own /oauth endpoint?
If so, it's possible SFDC is redirecting it with a GET operation rather than a POST operation. Be aware that the parameters to a GET show up in req.params rather than req.body.
Try implementing a get() handler to see if you get something workable.
app.get('/oauth', function(req, res) {
console.log ('GET /oauth', req.params)
/* do something here */
});
this is simple demo, making http post request and tries the log request object;
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
var router = express.Router();
app.use(router)
app.use(bodyParser.json())
foo=(req, res)=>{
console.log(req.body)
res.send('Request Handled Here!')
}
router.route('/').post(foo)
app.listen(3300, '127.0.0.1', (req, res)=>{
console.log("Express listening!!!!")
});
I can see data "Request Handled Here" message but return data is undefined always in the console, I couldn't figure why "req" object is undefined out.
Edited: I am using postman to test api, content-type:application/json and there is {message:"hello world!"} dummy data in Body section
Edited2: it seems my only issue there is no "body" attribute in request context, it retrieves all req header but I just want to get posted data, many samples on net contains req.body section whats wrong here?
The problem in middleware declaration order. router must be added after body-parser:
var app = express()
var router = express.Router();
app.use(bodyParser.json());
app.use(router);
I am new to MEAN Stack and have been developing some applications on Mean stack.But I am stuck with my app.post() method .The browser's console gives a 405 error saying that the method is not allowed.Please help me.
Here;s my code for server file in javascript
var app =express();
var mongoose =require('mongoose');
var bodyParser =require('body-parser');
var urlencodedparser=app.use(bodyParser.urlencoded({extended:false}));
var jsonParser = bodyParser.json()
app.get('/',function(request,response){
response.sendFile(__dirname+'/clients/views/index.html');
});
app.post('/api/meetups',jsonParser,function(req,res){
console.log(req.body);
});
var port=process.env.PORT || 3000;
app.listen(port,function(){
console.log('Listening to the server at port '+port);
});
Based on the Application.post() Express documentation, I think you probably want to change the first line of your post listener from:
app.post('/api/meetups',jsonParser,function(req,res){
console.log(req.body);
});
To this:
app.post('/api/meetups',function(req,res){
console.log(req.body);
});
I don't think it takes the additional parameter you specified related to JSON parsing. If you need to parse JSON you may want to look into using body-parser with middleware like this (which you would put ABOVE the post listener):
var bodyParser = require('body-parser');
app.use(bodyParser.json());
Good luck!
I am using express.js (v 4.13.4), node.js (v 0.12.5) and body-parser (v 1.13.2) to create a simple chat RESTful API.
I have this url path which must be called by the user:
http://myhost/chat/room/:roomId/message/:messageId
Body-parser is set like this:
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
I am unable to read the first url parameter :roomId but the :messageId is available.
I am accessing those parameters using req.params.roomId and req.params.messageId in request callback function.
Question:
Is it wrong to have parameters in the middle of a url?
Why would the application not parse :roomId?
The parameters roomId and so are send as query parameter therefore req.params.roomId is required to fetch.
Another way to do is send params as body, that way URL will be clean and then to access params body-parser is required.
To send params in body, create a post request through postman and specify params there.refer this for sending params in body
It is working in my case.
var app = require('express')();
var bodyParser= require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.get('/chat/room/:roomId/message/:messageId', function(req, res){
console.log('Room Id: '+req.params.roomId);
console.log('Message Id: '+req.params.messageId);
res.sendStatus(200);
});
app.listen(3000);
Now, if I try to access localhost:3000/chat/room/1/message/100, I get
Room Id: 1
Message Id: 100
Please check the spelling of roomId. May be typo can be the issue.
Thank you for your answers Mukesh Sharma and Himani Agrawal.
I found the issue now, here it is:
If I register a room router like this:
var RoomRouter = express.Router();
RoomRouter.get('/:roomId/message/:messageId', function(req, res) {
console.log('Room Id: '+req.params.roomId);
console.log('Message Id: '+req.params.messageId);
res.status(200);
res.send("Ok");
});
app.use('/chat/room', RoomRouter);
:roomId and :messageId are received accordingly.
But if I register the room router like this (as it was when I posted the error) :roomId is not available.
var RoomRouter = express.Router();
RoomRouter.get('/message/:messageId', function(req, res) {
console.log('Room Id: '+req.params.roomId);
console.log('Message Id: '+req.params.messageId);
res.status(200);
res.send("Ok");
});
app.use('/chat/room/:roomId', RoomRouter);
This was my issue, I don't know exactly why the url would be parsed differently in two different situation but I am sure this has a logic somewhere.
I'am trying to handle http post message from Mailgun bounce webhook. When sending it to Mailgun's Postbin service all data is found of course. But I'm now sending that POST to my localhost server for development purposes and all I get is empty json array. I use Test Webhook.
Intent is to keep this simple as possible besides our main service. That for I started using nodejs/expressjs to create stand alone webservice to work as relay to receive POST messages of email bounces from Mailgun and inform admins about bounced email addresses.
Now I can't figure why I don't get the same data as is visible in Postbin.
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var mailgun = require('mailgun-js')({apiKey: 'key-...', domain: 'mymailgundomain.com'});
app.use(bodyParser.urlencoded({
extended: true
}));
function router(app) {
app.post('/webhooks/*', function (req, res, next) {
var body = req.body;
if (!mailgun.validateWebhook(body.timestamp, body.token, body.signature)) {
console.error('Request came, but not from Mailgun');
res.send({ error: { message: 'Invalid signature. Are you even Mailgun?' } });
return;
}
next();
});
app.post('/webhooks/mailgun/', function (req, res) {
// actually handle request here
console.log("got post message");
res.send("ok 200");
});
}
app.listen(5000, function(){
router(app);
console.log("listening post in port 5000");
});
I'm running this from Mailgun's Test Webhook using url like http://mylocalhostwithpublicip.com:5000/webhooks/mailgun
Code structure is copied from https://github.com/1lobby/mailgun-js. Probably I'm missing something fundamental here as I can't figure it out myself.
The reason you're not seeing req.body populated is because the body-parser module does not support multipart/form-data requests. For those kinds of requests you need a different module such as multer, busboy/connect-busboy, multiparty, or formidable.
If your content-type (shown by logging console.dir(req.headers['content-type'])) is 'application/x-www-form-urlencoded', and you're using body-parser, try adding the following line:
bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))
to make it work with multer, you can use .any() (version 1.1.0)
for me it worked like this: (assuming multer is included and declared as "multer")
post('/track', multer.any(),function(req, res){
//if body is a string, parse the json
var data=(typeof req.body=='string')?JSON.parse(req.body):req.body;
//if data is an object but you can't verify if a field exists with hasOwnProperty, force conversion with JSON
if(typeof data=='object' && typeof data.hasOwnProperty=='undefined')
data=JSON.parse(JSON.stringify(data));
//data is your object
});
var multer = require('multer');
var msg = multer();
post('/track', msg.any(), function(req, res){
console.log(req.body);
}
I make a custom parser for get data in req.body when the Content-type = 'multipart/alternative'
https://github.com/josemadev/Multiparser/