为什么我的POST请求无法在Node中运行

时间:2016-05-08 06:52:20

标签: node.js express

我非常坚持这种“几乎存在”的问题。我是编程新手,但在我遇到这个问题之前一直很好。

所以,我有这个POST调用来放置一个新用户,如果“id”不存在,我可以使用Passpost.js从Facebook获得。

这是POST调用(使用“request”模块):

passport.use(new FacebookStrategy({
    clientID: config.facebook.appID,
    clientSecret: config.facebook.appSecret,
    callbackURL: config.facebook.callbackURL,
    profileFields: ['id', 'displayName', 'photos', 'emails', 'birthday', 'location', 'bio', 'likes.limit(100)']
},
function(accessToken, refreshToken, profile, done){
    userModel.findOne({'profileID':profile.id}, function(err, result){
        if(result){
            done(null, result);
        } else {
            request({
                url: 'http://localhost:3000/api/user',
                qs: {id:  'profile.id',},
                method: 'POST',
                json: {
                    fullname:   profile.displayName,
                    profilePic: profile.photos[0].value || '',
                    email:      profile.emails[0].value || '',
                    birthday:   profile._json.birthday || '',
                    location:   profile._json.location.name || '',
                    about:      profile._json.bio || '',
                    likes:      profile._json.likes || ''
                }
            }, function(error, response, body){
                if(error) {
                    console.log(error);
                } else {
                    console.log(response.statusCode, body);
                }
            });

        }
    })


}
)
)

我正在我的路由器上抓取POST调用:

apiRouter.post('/api/user', secureAPIPages, function(req, res, next){
    userModel.findOne({'profileID':req.query.id}, function(err, result){
        if(result){
            console.log('User exists already');
        } else {

            var newUser = new userModel({
                profileID   :   res.query.id,
                fullname    :   res.json.displayName,
                profilePic  :   res.json.photos || '',
                email       :   res.json.emails || '',
                birthday    :   res.json.birthday || '',
                location    :   res.json.location || '',
                about       :   res.json.bio || '',
                likes       :   res.json.likes || ''
            });

            newUser.save(function(err){
                console.log('User has been saved');
            })
        }
    })
})

我从POST调用得到这个:302 undefined(302是statusCode,未定义是请求模块中POST调用的主体)。

这实际上是一个两部分问题:

1)为什么我的POST电话无效? 2)我的apiRouter.post路线看起来不错吗?

这可能是非常简单的事情,但我花了无数个小时来尝试调试这个,但我真的没有到达任何地方。

我们非常推荐您的帮助。

谢谢, 砂眼

3 个答案:

答案 0 :(得分:2)

您通过请求发布的数据位于req.body中,而不是res.json。

var newUser = new userModel({
                profileID   :   res.query.id,
                fullname    :   res.json.displayName,
                profilePic  :   res.json.photos || '',
                email       :   res.json.emails || '',
                birthday    :   res.json.birthday || '',
                location    :   res.json.location || '',
                about       :   res.json.bio || '',
                likes       :   res.json.likes || ''
            });

应该是

var newUser = new userModel({
                profileID   :   req.query.id,
                fullname    :   req.body.displayName,
                profilePic  :   req.body.photos || '',
                email       :   req.body.emails || '',
                birthday    :   req.body.birthday || '',
                location    :   req.body.location || '',
                about       :   req.body.bio || '',
                likes       :   req.body.likes || ''
            });

答案 1 :(得分:2)

什么是apiRouter? 我希望它是快递对象的实例。就像在某个地方你有像

这样的行
var express = require('express');
var apiRouter = express.Router();

根据这个假设,虽然建议将函数封装在另一个文件中,但该路径看起来还不错。将有助于将api层与路线隔离开来:

var controllers = require("../controllers/web");
var express = require('express');
var router = express.Router();

router.get('/', controllers.home.landing);
router.get('/collections', controllers.collections.get_all_products_by_store);
router.get('/register', controllers.login.register);
router.get('/login, controllers.login.login_view);
router.post('/store_city_details', controllers.home.store_city_details)    

你的POST也很好。您从服务器获得302响应:

  

HTTP 302. HTTP响应状态代码302 Found是一种常见的方式   执行URL重定向。具有此状态代码的HTTP响应   还将在位置标题字段中提供URL。 HTTP 302    - Wikipedia, the free encyclopedia

你的代码中唯一没有意义的是

secureAPIPages 

您使用了向您发送302重定向响应的中间件。您的请求甚至没有到达您想要的端点。 如果它已返回200 StatusOkay,您将确保您的API有效。 但是那时理解了节点的请求和响应对象。

行:

function( req, res, next) ... 

您可以访问三个参数:

  • req:请求对象
  • res:响应对象
  • next:Function - 用于将控制转移到路径中的下一个功能。

如果是api的端点,请使用响应对象将回复发送回原始帖子:

collections.get_cart_data = function (req, res) {

  logger.info('[WEBSITE][API] in collections get_cart_data')
  res.json(req.session.selected_products); // sends back a response in json format that is made of the selected_products we received in the request session object
}; 

您的代码:

var newUser = new userModel({
                profileID   :   res.query.id, // I guess you want the value of the profile id in the request . Use req.query to access query values of the HTTP request
                fullname    :   res.json.displayName, // this is some weird bit of code I just cant wrap my head around..
                profilePic  :   res.json.photos || '', //  res.json is used to send a json response back to the api call  
                email       :   res.json.emails || '', // What you are trying to do is tried to save that value in another object key value pair ?? 
                birthday    :   res.json.birthday || '', // There is no req.json method i am aware of so idk . these should be 
                location    :   res.json.location || '',// req.body . 
                about       :   res.json.bio || '',
                likes       :   res.json.likes || ''
            });

            newUser.save(function(err){
                console.log('User has been saved');
            })

有不同的req方法用于访问请求对象中发送的不同值。 澄清:您在POST / GET调用中传递的值可以在请求对象中访问:

  

req.body:访问POST调用中使用的正文值   req.query:访问GET调用中使用的查询值   req.params:访问GET调用中使用的参数

所以你的api应该更像:

apiRouter.post('/api/user', secureAPIPages, function(req, res, next){
    userModel.findOne({'profileID':req.query.id}, function(err, result){
        console.log("MY REQUEST BODY OBJECT VALUES", req.body) // will show you the object you passed in " json:{} " of your POST call
        console.log("MY REQUEST Query  OBJECT VALUES", req.query) // will show {id:  'profile.id'} Please remove that trailing comma. Really got my ocd
        console.log("MY REQUEST Params OBJECT VALUES", req.params) // would be empty {}
        if(result){
            console.log('User exists already');
            res.send({"errmsg":"User exists already"})//send error response back 
        } else {
            /* Write clean code, define objects separately*/
        var newUserDetails ={
                "profileID"   :   req.query.id, // using req.query here as the qs value in your post call passes a query string appended to the url . used for auth purposes
                "fullname"    :   req.body.fullname, // Notice the use of "" for proper JSON structure. Use Jslint to verify your jsons
                "profilePic"  :   req.body.profilePic || '', // Also notice I have changed the variable names 
                "email"       :   req.body.email || '', // These need to match the key values as provided in POST call . 
                "birthday"    :   req.body.birthday || '', 
                "location"    :   req.body.location || '',
                "about"       :   req.body.about || '',
                "likes"       :   req.body.likes || ''
            }

            var newUser = new userModel(newUserDetails);

            newUser.save(function(err){
                console.log('User has been saved');
                var response = {
                "message" : " User has been saved",
                "user" : newUserDetails
                }
                res.send(response); // will send the reponse object back to your frontend
            })
        }
    })
})

答案 2 :(得分:2)

添加用户

后,只需致电done()即可
passport.use(new FacebookStrategy({
    // ommited
},
function(accessToken, refreshToken, profile, done){
    userModel.findOne({'profileID':profile.id}, function(err, result){
        if(result){
            done(null, result);
        } else {
            request({
                // ommited
            }, function(rErr, rResponse, rBody){
                 //use rResponse or rBody, depends on request package
                 //you must pass new created user to `done` callback
                 done(rErr, rBody); // <== done from passport callback
            });
        }
    })
  })
)