简体   繁体   中英

Why is request.body undefined?

I have a node-js server which includes bodyparser and everything:

var express = require('express');
var dbcon = require('./app/db/databaseconnection');
var bodyParser = require('body-parser');

var app = express();
var router = express.Router();

var filepath = __dirname + '/views/';
app.set('view engine', 'ejs');
app.use(express.static(__dirname + '/public'));
app.use('/', router);
app.use(bodyParser);
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: false })); // support encoded bodies
app.use('*', (request, response) => response.render(filepath + '404', { page_name: '404' }));


// var results = dbcon.getProducts().then(results => {
//      return results;
//  }).catch(err => { console.log(err) })
 //ejs.render(store , { results });
router.get('/', (request, response) => response.render(filepath + 'index', { page_name: 'home' }));
router.get('/store', (request, response) => {
    return dbcon.getProducts().then(results => {
        return response.render(filepath + 'store', { page_name: 'store', products: results });
    });
});
router.get('/product', (request, response) => {
    return dbcon.getProductDetails().then(results => {
        return response.render(filepath + 'product', { page_name: 'product', products: results, req: request });
    });
});
router.get('/purchase', (request, response) => {
    return dbcon.getProductDetails().then(results => {
        response.render(filepath + 'purchase', { page_name: 'purchase', products: results, req: request, res: response });
    });
});
router.post('/purchase', (request, response) => {
    //return dbcon.createCustomer(request.body.fname, request.body.lname, request.body.address, request.body.city, request.body.state, request.body.country, request.body.zip, request.body.phone, request.body.cardnumber, request.body.cardtype, request.body.expirationdate, request.body.securitycode, request.body.cardaddress, request.body.productID);
    console.log(request.body.name);
    response.redirect('/receipt');
});
router.get('/receipt', (request, response) => response.render(filepath + 'receipt', { page_name: 'receipt' }));
router.get('/about', (request, response) => response.render(filepath + 'about', { page_name: 'about' }));
router.get('/contact', (request, response) => response.render(filepath + 'contact', { page_name: 'contact' }));
router.get('/build', (request, response) => response.render(filepath + 'build/build'));
router.get('/learn', (request, response) => response.render(filepath + 'learn/learn'));

app.listen(3000, () => console.log("Server running at Port 3000"));

I also have a ejs page which includes a form:

<!DOCTYPE html>
<html>

<head>
    <title>PC Store | Purchase</title>
    <% include partials/header %>
    <link rel="stylesheet" link="/css/purchaseCanvas.css" />
    <script src="/js/toggleCountries.js"></script>
</head>

<body>
    <header>
        <% include partials/navbar %>
    </header>
    <main>
    <div class="container">
        <h1 align="center">Order</h1>
        <div class="orderproduct center">
        <% for (var i = 0; i < products.length; i++) { 
            //console.log(products[i]); 
            if (products[i].model == req.query.product) { %>
            <h4>Product: </h4>
            <img src="/img/productImages/<%= products[i].image01 %>" width="100">
            <h5>Brand: <%= products[i].brand %></h5>
            <h5>Model: <%= products[i].model %></h5>
            <h5>Series: <%= products[i].series %></h5>
            <h5>Price: $<%= products[i].price %></h5>
            <input type="hidden" id="productID" name="productID" value="<%= products[i].productID %>">
            <hr>
        <% }} %>
        </div>
        <form action="/purchase" method="post">
            <div class="canvas">
                <br><br>
                <div class="center">
                    <input type="text" class="form-control" id="fname" name="fname" placeholder="First Name" required>
                    <p id="fnameError" class="errorText"></p>
                </div><br>
                <div class="center">
                    <input type="text" class="form-control" id="lname" name="lname" placeholder="Last Name" required>
                    <p id="lnameError" class="errorText"></p>
                </div><br>
                <div class="center">
                    <input type="text" class="form-control" id="address" name="address" placeholder="Shipping Address" required>
                    <p id="addressError" class="errorText"></p>
                </div><br>
                <div class="center">
                    <input type="text" class="form-control" id="city" name="city" placeholder="City" required>
                    <p id="cityError" class="errorText"></p>
                </div><br>
                <div class="center">
                    <select class="form-control" id="country" name="country"></select>
                    <p id="countryError" class="errorText"></p>
                </div><br>
                <div class="center">
                    <select class="form-control" id ="state" name="state">
                        <option value="-1">Select State</option>
                    </select>
                    <p id="stateError" class="errorText"></p>
                </div> <br>
                <script>populateCountries("country", "state");</script>
                <div class="center">
                    <input type="text" class="form-control" id="zip" name="zip" placeholder="Zip Code" required>
                    <p id="zipError" class="errorText"></p>
                </div><br>
                <div class="center">
                    <input type="tel" class="form-control" id="phone" name="phone" placeholder="Phone Number" required>
                    <p id="phoneError" class="errorText"></p>
                </div><br>
                <div class="center">
                    <input type="text" class="form-control" id="cardnumber" name="cardnumber" placeholder="Card Number" required>
                    <p id="cardnumberError" class="errorText"></p>
                </div><br>
                <div class="center">
                    <select class="form-control" id="cardtype" name="cardtype">
                        <option value="-1">Select Card Type</option>
                        <option value="Visa">Visa</option>
                        <option value="MasterCard">MasterCard</option>
                        <option value="American Express">American Express</option>
                        <option value="Discover">Discover</option>
                    </select>
                    <p id="cardtypeError" class="errorText"></p>
                </div> <br>
                <div class="center">
                    <input type="date" class="form-control" id="expirationdate" name="expirationdate" placeholder="Expiration Date" required>
                    <p id="expirationdateError" class="errorText"></p>
                </div><br>
                    <div class="center">
                    <input type="text" class="form-control" id="securitycode" name="securitycode" placeholder="Security Code" required>
                    <p id="securitycodeError" class="errorText"></p>
                </div><br>
                <div class="center">
                    <input type="text" class="form-control" id="cardaddress" name="cardaddress" placeholder="Billing Address" required>
                    <p id="cardaddressError" class="errorText"></p>
                </div><br>
                <div class="center">
                    <input type="submit" class="btn btn-primary" value="Order">
                </div>
            </div>
        </form>
    </div>
    </main>
    <footer>
        <% include partials/footer %>
    </footer>
</body>

</html>   

From a post I read that you can use request.body to get the values from the inputs in the form. So I tried to do that but it doesn't work. When I do request.body it says undefined and when I try to do request.body.fname it says error and that name doesn't exist. Anyone know what the problem could be? People have stated that it was because of the order of app.use, but I've tried changing it and it still wouldn't work. Please Help!

Looks like you are hooking up your routes before any parsing middleware, which would explain why you don't get any body (usually if it's hooked up correctly you would at least get an empty object).

app.use('/', router);
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: false })); // support encoded bodies

Needs to be

app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: false })); // support encoded bodies
app.use('/', router);

History:

Earlier versions of Express used to have a lot of middleware bundled with it. bodyParser was one of the middleware that came with it. When Express 4.0 was released they decided to remove the bundled middleware from Express and make them separate packages instead. The syntax then changed from app.use(express.json()) to app.use(bodyParser.json()) after installing the bodyParser module.

bodyParser was added back to Express in release 4.16.0, because people wanted it bundled with Express like before. That means you don't have to use bodyParser.json() anymore if you are on the latest release. You can use express.json() instead.

The release history for 4.16.0 is here for those who are interested, and the pull request is here .

Okay, back to the point,

Implementation:

All you need to add is just add,

app.use(express.json());
app.use(express.urlencoded({ extended: true}));

Before route declaration, instead of,

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

And Express will take care of your request. :)

Full example will looks like,

const express       = require('express')
const app           = express()

app.use(express.json())
app.use(express.urlencoded({ extended: true}));

app.post('/test-url', (req, res) => {
    console.log(req.body)
    return res.send("went well")
})

app.listen(3000, () => {
    console.log("running on port 3000")
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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