如何在 Node.js 请求中发布多个相同名称的值

Posted

技术标签:

【中文标题】如何在 Node.js 请求中发布多个相同名称的值【英文标题】:How to POST multiple values same name in Node.js Request 【发布时间】:2014-02-27 09:21:12 【问题描述】:

我需要使用 node.js 和 Request 以编程方式将多个值提交到 POST(在本例中为美国各州)。

例如,html 表单可能是

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

后跟 50 个选项...,每个州一个

提交的表单数据看起来像

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

如何使用请求来做到这一点?鉴于我有一系列状态 ['CA','WI',我已经尝试过

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

form['stateprov[]'] = states.join(',') 也不行

顺便说一句,Node 人,我真的很想喜欢这个项目,有很多很酷的东西,但你的文档不太好。

后续:我认为问题可能是 Request (https://npmjs.org/package/request) 使用 qs (https://npmjs.org/package/qs) 对表单数据进行编码,并添加了无关的 [0] 和 [1]。 Node 内置的 queryString (http://nodejs.org/api/querystring.html#querystring_querystring_stringify_obj_sep_eq) 可以进行我想要的编码。

跟进#2:与在支持 Request 方面做得很好的 Mikeal Rogers 聊天,他基本上说我不能在 Request 中这样做。由于我没有利用 Request 的许多很酷的特性,我将看看更基本的 http。

【问题讨论】:

您是仅使用 HTTP 还是使用 express 之类的模块? 【参考方案1】:

偶然发现了这个问题,但从未使用 restler 让它工作。我确实发现它可以使用 npm 模块 'request' 就可以了

import request from 'request';
let data =  subject: 'a message', recipients:['person1@gmail.com', 'person2@gmail.com'] 
// 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 
)

我将它封装在 Q 库中以做出承诺。效果很好。有点痛苦,因为我需要切换库,但希望这有助于稍后偶然发现此问题的 soemone。

【讨论】:

你是一个真正的生命救星,qsStringifyOptions: arrayFormat: 'repeat' 选项没有在任何地方记录,它就像一个魅力! 如果有人使用 request-promise qsStringifyOptions: arrayFormat: 'repeat' 到达这里,需要按照请求官方文档 github.com/request/request#requestoptions-callback 中所述的相同级别的 qs 传递 一年多过去了,这个解决方案仍然适用......它就像我一直在努力解决的问题的冠军一样。已经在使用 Request,但不知道 qsStringifyOptions 提供的完整选项变体。谢谢。 很高兴知道隐藏的宝石,qsStringifyOptions: arrayFormat: "brackets"。在发送表单数据中的数组时很有用。 这节省了我的火炮测试!我需要调用一个 API,为同一个参数传递多个值,在 beforeRequest function 中添加 qsStringifyOptions 就可以了。【参考方案2】:

很抱歉回答我自己的问题,但万一其他人遇到这个问题......

迈克·罗杰斯当然是对的。 Request 使用 npm 包 qs (https://npmjs.org/package/qs) 作为他的查询字符串解析器,而且,无论好坏,当它“字符串化”一个数组时,它会添加 '[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('&');

因此,具有多个值的表单如下所示:

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

也许这是你想要的,但这不是想要的,而且这似乎与正常的 HTML 表单行为不匹配。我的 HTML 经验有限,所以这可能是错误的:-)

事实证明,node 的内置 querystring.stringify 做了我想要的,输出

foo=value0&amp;foo=value1

快速破解是在Request.form() 中更改一行(大约是第 974 行)

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

但是,无论何时进行更新,您都必须记住再次执行此操作。不健壮。 “正确”的方法是子类化。我花了一段时间才找到一个小问题——你不能 require('request'),因为这会引入 index.js,它会导出小写工厂 request() 方法。带有new 构造函数 的“真实”大写字母在request.js 中。所以你必须具体:require('request/request.js')

这是代码:(也在https://gist.github.com/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;

【讨论】:

如果有人像我一样偶然发现这一点,看起来 qs 现在有一个 indices: false 选项可以禁用此行为。不确定这是否有用... 事实上,将请求中的qsStringifyOptionsarrayFormat: repeat 结合起来,现在应该可以在不修改请求的情况下做到这一点。 谢谢,总有一天我会试一试的。 useQuerystring: true,这就是你现在所需要的。【参考方案3】:
var querystring = require('querystring');
var form = 
//form parameters

request.post(http + querystring.stringify(form), callback);

在请求之外声明表单对象。然后,调用返回所需字符串的 querystring.stringify(form),并将该字符串附加到 url。以这种手动方式对 url 进行编码可以避免子类和更新问题。

【讨论】:

以上是关于如何在 Node.js 请求中发布多个相同名称的值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 node.js 中同时使用多个代理(代理)

当您不知道页数时,如何使用 Node.js 在 while 循环中向 API 发出多个分页 GET 请求?

为啥在使用 Node.js 的许多文件中存在*** const 或 let 具有相同名称时,Typescript 会出错

如何从Google Cloud Function(Cheerio,Node.js)发出多个http请求

如何防止在表中的多个下拉列表中选择相同的值并 POST 到服务器

在 Node.js 中的单个 HTTP 请求中调用多个 HTTP 请求