最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to POST multiple values same name in Node.js Request - Stack Overflow

programmeradmin5浏览0评论

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

stateprov%5B%5D=CA&stateprov%5B%5D=WI

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

form['stateprov[]'] = states  
   fails 
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 (.html#querystring_querystring_stringify_obj_sep_eq) 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.

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

stateprov%5B%5D=CA&stateprov%5B%5D=WI

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

form['stateprov[]'] = states  
   fails 
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 (https://npmjs/package/request) uses qs (https://npmjs/package/qs) to encode the form data, and it adds the extraneous [0] and [1]. Node's built in queryString (http://nodejs/api/querystring.html#querystring_querystring_stringify_obj_sep_eq) 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.

Share Improve this question edited Feb 3, 2014 at 22:47 user949300 asked Feb 3, 2014 at 18:35 user949300user949300 15.7k7 gold badges38 silver badges68 bronze badges 1
  • Are you doing this with HTTP only or using a module like express? – Matthew Bakaitis Commented Feb 3, 2014 at 20:48
Add a ment  | 

4 Answers 4

Reset to default 16

Stumbled on this issue and never got it to work using restler. I did find that it works using the npm module 'request' Just do

import request from 'request';
let data = { subject: 'a message', recipients:['[email protected]', '[email protected]'] }
// define your data above. I was having issues with the recipients needing to repeat
let options = {
  form: data, qsStringifyOptions: {arrayFormat: 'repeat'}
}
request.post(url, options, function(err, res, body){
   //callback. note request sends 3 params to callback 
})

I wrapped this inside of the Q library to make promises. Worked out well. A bit of a pain because I needed to switch libraries, but hopefully this helps soemone who stumbles on this later.

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 (https://npmjs/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:

foo[0]=value0&foo[1]=value1

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

foo=value0&foo=value1

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 https://gist.github./MorganConrad/8827916)

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';
  Request.prototype.constructor.call(this, 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;
  }

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


module.exports = MyRequest;

you can simply add a hidden input for each piece of data

<input type="hidden" name="anyData" value="data" ></input>

don't forget the input closing tag.

var querystring = require('querystring');
var form = {
//form parameters
}
request.post(http + querystring.stringify(form), callback);

Declare the form object outside of request. Then, call querystring.stringify(form) which returns the desired string, and just append that string to the url. Coding the url this manual way avoids child classes and the update problem.

发布评论

评论列表(0)

  1. 暂无评论