user949300 user949300 - 1 year ago 73
Javascript Question

How to POST multiple values same name in Node.js Request

I need to programmatically submit multiple values to a POST (in this example, US states), using node.js and Request.

For example, the HTML form might be be

<select name="stateprov[]" id="stateprov" multiple="multiple" >

followed by 50 options..., one per state

And the submitted form data would look like


How can I do this using Request? Given that I have an array of states, ['CA','WI'}, I've tried

form['stateprov[]'] = states
it generates stateprov%5B%5D[0]=WI&stateprov%5B%5D[1]=CA as the output

form['stateprov[]'] = states.join(',') doesn't work either

BTW, Node people, I'm really trying to like the project, there's a lot of cool things, but your documentation is less than great.

Followup: I think the problem might be that Request ( uses qs ( to encode the form data, and it adds the extraneous [0] and [1]. Node's built in queryString ( does the encoding that I want.

Followup #2: Chatted with Mikeal Rogers who does a great job supporting Request, and he basically said that I can't do it this way in Request. Since I'm not exploiting many of the cool features of Request I'll look at the more basic http.

Answer Source

Sorry to answer my own question, but in case others run into this issue...

Mikeal Rogers is of course right. Request uses the npm package qs ( as his query string parser, and, for better or worse, when it "stringifies" an array it adds '[n]'.

function stringifyArray(arr, prefix) {
  var ret = [];
  if (!prefix) throw new TypeError('stringify expects an object');
  for (var i = 0; i < arr.length; i++) {
    ret.push(stringify(arr[i], prefix + '[' + i + ']'));  <<< see here
  return ret.join('&');

So a form with multiple values would look like:


Maybe this is what you want, but it's not what I want, and this seems to mismatch normal HTML form behavior. My HTML experience is limited, so this may be wrong:-)

It turns out that node's built in querystring.stringify does what I want, outputting


The quick hack is to change one line in Request.form() (roughly line 974)

this.body = *querystring*.stringify(form).toString('utf8')

However, anytime you do an update, you'll have to remember to do this again. Not robust. The "proper" way is to subclass. It took me a while to find one little gotcha - you cannot require('request'), because that brings in index.js, which exports the lowercase factory request() method. The "real" uppercase with a new constructor is in request.js. So you must be specific: require('request/request.js')

Here's the code: (also at

var Request = require('request/request.js');  // IMPORTANT - specify request.js, don't get index.js!!!
var querystring = require('querystring');

MyRequest.prototype = Object.create(Request.prototype);
MyRequest.prototype.constructor = MyRequest;

function MyRequest(options, callbackfn) {
  "use strict";
  if (callbackfn)
    options.callback = callbackfn;
  options.method = options.method || 'POST';, options);

MyRequest.prototype.form = function (form) {
  "use strict";
  if (form) {
    this.setHeader('content-type', 'application/x-www-form-urlencoded; charset=utf-8');
    this.body = querystring.stringify(form).toString('utf8');
    return this;

    return Request.prototype.form.apply(this, arguments);

module.exports = MyRequest;