简体   繁体   English

API不接受Express中来自Form的数据

[英]API not accepting data from Form in express

I have an api as follows, the problem I am having is that when I create aa form using handlebars and submit the form to this API, I know it is hitting the api because it show the validation message but it is not accepting the values provided in the form: 我有如下所示的api,我遇到的问题是,当我使用车把创建表单并将表单提交到此API时,我知道它正在击中api,因为它显示了验证消息,但不接受提供的值形式:

exports.register = function (req, res, next) {
  var username = _.get(req.body, 'username');
  var password = _.get(req.body, 'password');

  if (!username) {
    throw {username: 'This field is required.', status: 400};
  }
  if (!password) {
    throw {password: 'This field is required.', status: 400};
  }

  Users.register(dbUtils.getSession(req), username, password)
    .then(response => writeResponse(res, response, 201))
    .catch(next);
};

So basically is a simple registration api, the form ask for user name and password and then you click submit. 因此,基本上是一个简单的注册api,该表单要求输入用户名和密码,然后单击“提交”。

Following is the code for my handlebars file: 以下是我的把手文件的代码:

<div class="row">
    <div class="col-md-6 mx-auto">
        <div class="card card-body">

            <h3 class="text-center">Account Register</h3>
            <form action="/api/v0/register" method="POST" enctype='application/json'>
                <div class="form-group">
                    <label for="name">Name</label>
                    <input type="text" class="form-control" name="username" value="{{name}}" required>
                </div>

                <div class="form-group">
                    <label for="password">Password</label>
                    <input type="password" class="form-control" name="password" value="{{password}}" required>
                </div>


                <button type="submit" class="btn btn-primary">Submit</button>

            </form>
        </div>
    </div>
</div>

When I click submit the page show the response from my route that username is required. 当我单击“提交”页面时,显示我的路线的响应,要求提供用户名。 What I am confused about is why the username and password is not being detected by the route: 我感到困惑的是,为什么路由未检测到用户名和密码:

Message: 信息:

{
"username": "This field is required."
}

I am using Nodejs, express, express handlebars. 我正在使用Nodejs,Express,Express把手。

My Complete app.js is as follows: 我的完整app.js如下:

var express = require('express')
  , path = require('path')
  , routes = require('./routes')
  , nconf = require('./config')
  , swaggerJSDoc = require('swagger-jsdoc')
  , methodOverride = require('method-override')
  , errorHandler = require('errorhandler')
  , bodyParser = require('body-parser')
  , setAuthUser = require('./middlewares/setAuthUser')
  , neo4jSessionCleanup = require('./middlewares/neo4jSessionCleanup')
  , writeError = require('./helpers/response').writeError;

  const exphbs = require('express-handlebars');


var app = express()
  , api = express();

app.use(nconf.get('api_path'), api);

// Handlebars middleware
app.engine('handlebars', exphbs({
  defaultLayout: 'main'
}));
app.set('view engine', 'handlebars');

// Body Parser middleware
app.use(bodyParser.urlencoded({ extended: false}));
app.use(bodyParser.json());

var swaggerDefinition = {
  info: {
    title: 'Neo4j Movie Demo API (Node/Express)',
    version: '1.0.0',
    description: '',
  },
  host: 'localhost:3000',
  basePath: '/',
};

// options for the swagger docs
var options = {
  // import swaggerDefinitions
  swaggerDefinition: swaggerDefinition,
  // path to the API docs
  apis: ['./routes/*.js'],
};

// initialize swagger-jsdoc
var swaggerSpec = swaggerJSDoc(options);

// serve swagger
api.get('/swagger.json', function(req, res) {
  res.setHeader('Content-Type', 'application/json');
  res.send(swaggerSpec);
});

app.use('/docs', express.static(path.join(__dirname, 'swaggerui')));
app.set('port', nconf.get('PORT'));

//api.use(bodyParser.json());
api.use(methodOverride());

//enable CORS
api.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Credentials", "true");
  res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT,DELETE");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
  next();
});

//api custom middlewares:
api.use(setAuthUser);
api.use(neo4jSessionCleanup);


// User Register Route
app.get('/users/register', (req, res) => {

  res.render('users/register');
});

//api routes
api.post('/register', routes.users.register);
api.post('/login', routes.users.login);
api.get('/users/me', routes.users.me);
api.get('/movies', routes.movies.list);
api.get('/movies/recommended', routes.movies.getRecommendedMovies);
api.get('/movies/rated', routes.movies.findMoviesRatedByMe);
api.get('/movies/:id',  routes.movies.findById);
api.get('/movies/genre/:id',  routes.movies.findByGenre);
api.get('/movies/daterange/:start/:end', routes.movies.findMoviesByDateRange);
api.get('/movies/directed_by/:id', routes.movies.findMoviesByDirector);
api.get('/movies/acted_in_by/:id', routes.movies.findMoviesByActor);
api.get('/movies/written_by/:id', routes.movies.findMoviesByWriter);
api.post('/movies/:id/rate', routes.movies.rateMovie);
api.delete('/movies/:id/rate', routes.movies.deleteMovieRating);
api.get('/people', routes.people.list);
api.get('/people/:id', routes.people.findById);
api.get('/people/bacon', routes.people.getBaconPeople);
api.get('/genres', routes.genres.list);

//api error handler
api.use(function(err, req, res, next) {
  if(err && err.status) {
    writeError(res, err);
  }
  else next(err);
});

app.listen(app.get('port'), () => {
  console.log('Express server listening on port ' + app.get('port') + ' see docs at /docs');
});

This is user the user route file: 这是用户的用户路由文件:

var Users = require('../models/users')
  , writeResponse = require('../helpers/response').writeResponse
  , writeError = require('../helpers/response').writeError
  , loginRequired = require('../middlewares/loginRequired')
  , dbUtils = require('../neo4j/dbUtils')
  , _ = require('lodash');


exports.register = function (req, res, next) {


  var username = _.get(req.body, 'username');
  var password = _.get(req.body, 'password');

  if (!username) {
    throw {username: 'This field is required.', status: 400};
  }
  if (!password) {
    throw {password: 'This field is required.', status: 400};
  }

  Users.register(dbUtils.getSession(req), username, password)
    .then(response => writeResponse(res, response, 201))
    .catch(next);
};


exports.login = function (req, res, next) {
  var username = _.get(req.body, 'username');
  var password = _.get(req.body, 'password');

  if (!username) {
    throw {username: 'This field is required.', status: 400};
  }
  if (!password) {
    throw {password: 'This field is required.', status: 400};
  }

  Users.login(dbUtils.getSession(req), username, password)
    .then(response => writeResponse(res, response))
    .catch(next);
};


exports.me = function (req, res, next) {
  loginRequired(req, res, () => {
    var authHeader = req.headers['authorization'];
    var match = authHeader.match(/^Token (\S+)/);
    if (!match || !match[1]) {
      throw {message: 'invalid authorization format. Follow `Token <token>`', status: 401};
    }

    var token = match[1];
    Users.me(dbUtils.getSession(req), token)
      .then(response => writeResponse(res, response))
      .catch(next);
  })
};

This is my user model file: 这是我的用户模型文件:

"use strict"

var uuid = require('node-uuid');
var randomstring = require("randomstring");
var _ = require('lodash');
var dbUtils = require('../neo4j/dbUtils');
var User = require('../models/neo4j/user');
var crypto = require('crypto');

var register = function (session, username, password) {
  return session.run('MATCH (user:User {username: {username}}) RETURN user', {username: username})
    .then(results => {
      if (!_.isEmpty(results.records)) {
        throw {username: 'username already in use', status: 400}
      }
      else {
        return session.run('CREATE (user:User {id: {id}, username: {username}, password: {password}, api_key: {api_key}}) RETURN user',
          {
            id: uuid.v4(),
            username: username,
            password: hashPassword(username, password),
            api_key: randomstring.generate({
              length: 20,
              charset: 'hex'
            })
          }
        ).then(results => {
            return new User(results.records[0].get('user'));
          }
        )
      }
    });
};

var me = function (session, apiKey) {
  return session.run('MATCH (user:User {api_key: {api_key}}) RETURN user', {api_key: apiKey})
    .then(results => {
      if (_.isEmpty(results.records)) {
        throw {message: 'invalid authorization key', status: 401};
      }
      return new User(results.records[0].get('user'));
    });
};

var login = function (session, username, password) {
  return session.run('MATCH (user:User {username: {username}}) RETURN user', {username: username})
    .then(results => {
        if (_.isEmpty(results.records)) {
          throw {username: 'username does not exist', status: 400}
        }
        else {
          var dbUser = _.get(results.records[0].get('user'), 'properties');
          if (dbUser.password != hashPassword(username, password)) {
            throw {password: 'wrong password', status: 400}
          }
          return {token: _.get(dbUser, 'api_key')};
        }
      }
    );
};

function hashPassword(username, password) {
  var s = username + ':' + password;
  return crypto.createHash('sha256').update(s).digest('hex');
}

module.exports = {
  register: register,
  me: me,
  login: login
};

I have also tried to console.log req.body.username and it is undefined for some reason. 我也尝试过console.log req.body.username,由于某种原因,它是未定义的。

Your middleware: 您的中间件:

// Body Parser middleware
app.use(bodyParser.urlencoded({ extended: false}));
app.use(bodyParser.json());

needs to be BEFORE you insert the api router into the routing chain. 需要在将api路由器插入路由链之前。 As you have it now, requests are routed to your api router without this middleware executing. 就像您现在拥有的那样,请求将路由到您的api路由器,而无需执行此中间件。

So, it should be like this: 因此,应该是这样的:

// Body Parser middleware
// must come before any requests, middleware or routers that want to use
// the body-parser middleware results
app.use(bodyParser.urlencoded({ extended: false}));
app.use(bodyParser.json());

app.use(nconf.get('api_path'), api);

Also, change this: 另外,更改此:

, api = express();

to: 至:

, api = express.Router();

so you're just using a router instead of an app object. 因此,您只是使用路由器而不是应用程序对象。 The app object is also a router, but a plain router is really what you want here. 该应用程序对象也是一个路由器,但是纯路由器确实是您想要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM