0

I am trying to get the data from a form's fields in a POST request. My problem is that the object that I am getting that should contain the data is empty when I use the browser, but it works if I am using Postman.

I am using the formidable module to get the data from the form.

Here is my form:

<div class="form">
  <form action="/signup" method="POST">
    <div class="form-group">
      <label for="username">Username:</label>
      <input type="text" class="form-control" id="username" placeholder="Username">
    </div>
    <div class="form-group">
      <label for="email">Email:</label>
      <input type="email" class="form-control" id="email" placeholder="Email">
    </div>
    <div class="form-group">
      <label for="password">Password:</label>
      <input type="password" class="form-control" id="password" placeholder="Password">
    </div>
    <button type="submit" class="btn btn-default" id="signup-btn">Sign Up</button>
  </form>
</div>

Here is the route I for the form:

signupPost: function (request) {
  route.post('/signup', function () {
    var form = new formidable.IncomingForm();

    form.parse(request, function (error, fields, files) {
      if (error) {
        console.error(error);
      }
      console.log(request.headers);
      console.log(fields);
    });
  });
}

The route.post function is a custom function declared in a different module:

post: function (url, handler) {
  if (this.request.method === 'POST' && this.request.url === url) {
    var data = handler();
    this.response.end(data);
  }
}

I have tried changing the headers so that the post function looks like this, but it didn't work:

post: function (url, handler) {
  if (this.request.method === 'POST' && this.request.url === url) {
    this.response.writeHead(200, {
      'content-type': 'multipart/form-data'
    });
    var data = handler();
    this.response.end(data);
  }
}

Incase it helps, here are the headers I get back from the browser:

{ host: 'localhost:8080',
  connection: 'keep-alive',
  'content-length': '0',
  'cache-control': 'max-age=0',
  origin: 'http://localhost:8080',
  'upgrade-insecure-requests': '1',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36',
  'content-type': 'application/x-www-form-urlencoded',
  accept: 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
  referer: 'http://localhost:8080/signup',
  'accept-encoding': 'gzip, deflate, br',
  'accept-language': 'en-US,en;q=0.8' }

And here are the ones from Postman:

{ 'cache-control': 'no-cache',
  'postman-token': '72c9c23c-dc66-400e-85cb-615a633efd02',
  'content-type': 'multipart/form-data; boundary=--------------------------641553275315430252355922',
  'user-agent': 'PostmanRuntime/6.2.5',
  accept: '*/*',
  host: 'localhost:8080',
  'accept-encoding': 'gzip, deflate',
  'content-length': '409',
  connection: 'keep-alive' }

I have the project on GitHub if anyone wants to see the whole project.

Caleb Kleveter
  • 11,170
  • 8
  • 62
  • 92
  • 1
    Any particular reason why your using formiddable to process form data over [bodyParser](https://github.com/expressjs/body-parser) middleware? Formiddable is more recommended for file uploads. – James Aug 07 '17 at 12:47
  • 1
    Only form elements with a name attribute will have their values passed when submitting a form. So you are not posting anything from the browser. Though I am not at all familiar with formidable, maybe that changes things. – tomtom Aug 07 '17 at 12:49
  • @James I am specifically not using Express, and from what I can tell, body-parser uses it. I am now using querystring instead. – Caleb Kleveter Aug 07 '17 at 13:49
  • @tomtom That solved my problem. You should probably post that as an answer. – Caleb Kleveter Aug 07 '17 at 13:49

2 Answers2

0

You don't need any additional library e.g. formidable for "simple" fields:

var qs = require('querystring');

function parseBody(req, callback) {
    var body = '';
    req.on('data', (data) => body += data);
    req.on('end', () => callback(qs.parse(body)))
}
...
post: function (url, handler) {
    if (this.request.method === 'POST' && this.request.url === url) {
        parseBody (this.request, function (data) {
            console.log(data);
        })
    }
}
Aikon Mogwai
  • 4,954
  • 2
  • 18
  • 31
  • Thanks for the tip, but this still doesn't solve the problem I was having in which I don't get data when using the form in the browser. – Caleb Kleveter Aug 07 '17 at 13:44
  • You should add flood data handling `if (body.length > 1e6) req.connection.destroy();`. Read more here: https://stackoverflow.com/questions/4295782/how-to-process-post-data-in-node-js – Oz Shabat Jul 22 '19 at 05:55
0

Only form elements with a name attribute will have their values passed when submitting a form. So you are not posting anything from the browser. https://www.w3schools.com/tags/att_input_name.asp

Simply adding a name attribute to the inputs should solve the problem. Ex:

<input type="text" class="form-control" name="username" id="username" placeholder="Username">
tomtom
  • 642
  • 7
  • 12