如何使用内容类型 ='application/x-www-form-urlencoded' 在 node.js 中发布数据

Posted

技术标签:

【中文标题】如何使用内容类型 =\'application/x-www-form-urlencoded\' 在 node.js 中发布数据【英文标题】:how to post data in node.js with content type ='application/x-www-form-urlencoded'如何使用内容类型 ='application/x-www-form-urlencoded' 在 node.js 中发布数据 【发布时间】:2016-05-30 03:14:19 【问题描述】:

我在使用 Content-type: 'application/x-www-form-urlencoded' 在 node.js 中发布数据时遇到问题

var loginArgs = 
    data: 'username="xyzzzzz"&"password="abc12345#"',

    //data: 
    //    'username': "xyzzzzz",
    //    'password': "abc12345#",
    //,

    headers: 
            'User-Agent': 'MYAPI',
            'Accept': 'application/json',
            'Content-Type':'application/x-www-form-urlencoded'      
       
;

并且发布请求是:

client.post("http:/url/rest/login", loginArgs, function(data, response)
console.log(loginArgs);

if (response.statusCode == 200) 
    console.log('succesfully logged in, session:', data.msg);

它总是返回用户名/密码不正确。

在其余的 api 中说请求正文应该是:

username='provide user name in url encoded
format'&password= "provide password in url encoded format'

【问题讨论】:

How to make an HTTP POST request in node.js?的可能重复 【参考方案1】:

request 支持application/x-www-form-urlencodedmultipart/form-data 表单上传。对于multipart/related,请参阅多部分 API。

application/x-www-form-urlencoded(URL 编码表单)

URL 编码的表单很简单:

const request = require('request');

request.post('http:/url/rest/login', 
  form: 
    username: 'xyzzzzz',
    password: 'abc12345#'
  
)
// or
request.post('http:/url/rest/login').form(
  username: 'xyzzzzz',
  password: 'abc12345#'
)
// or
request.post(
  url: 'http:/url/rest/login',
  form: 
    username: 'xyzzzzz',
    password: 'abc12345#'
  
, function (err, httpResponse, body)  /* ... */ )

见:https://github.com/request/request#forms

或者,使用request-promise

const rp = require('request-promise');
rp.post('http:/url/rest/login', 
  form: 
    username: 'xyzzzzz',
    password: 'abc12345#'
  
).then(...);

见:https://github.com/request/request-promise#api-in-detail

【讨论】:

此评论不再适用。 request 模块被标记为已弃用。 github.com/request/request/issues/3142【参考方案2】:

application/x-www-form-urlencoded 要求您对键和值进行 URL 编码 (MSDN Documentation)。 举例说明:

data:`$encodeURI('username')=$encodeURI('xyzzzzz')&$encodeURI('password')=$encodeURI('abc12345')`

请求库已被弃用,正如@Bram 所评论的那样。

我将编写的示例将使用 NodeJS 附带的标准 HTTPS 库。 你可以这样写(在打字稿中):

import * as https from 'https';
// import * as http from 'http'; // For HTTP instead of HTTPS

export class ApiExample 

    // tslint:disable-next-line: no-empty
    constructor()  

    public async postLogin(username: string, password: string): Promise<any> 
        // application/x-www-form-urlencoded requires the syntax "UrlEncodedKey=UrlEncodedValue&UrlEncodedKey2=UrlEncodedValue2"
        const xFormBody = `$encodeURI('username')=$encodeURI(username)&$encodeURI('password')=$encodeURI(password)`;

        return this.performRequest(xFormBody)
    

    private performRequest(requestBody: string) 
        return new Promise((resolve, reject) => 

            const options: https.RequestOptions = 
                hostname: 'example.url.com',
                port: 443,
                path: '/login',
                method: 'POST',
                headers: 
                    'Content-Type': 'application/x-www-form-urlencoded',
                    'Content-Length': Buffer.byteLength(requestBody)
                
            ;

            // const req = http.request(options, function (res)  // For HTTP
            const req = https.request(options, function (res) 
                // This may need to be modified based on your server's response.
                res.setEncoding('utf8');

                let responseBody = '';

                // Build JSON string from response chunks.
                res.on('data', (chunk) => responseBody = responseBody + chunk);
                res.on('end', function () 
                    const parsedBody = JSON.parse(responseBody + '');

                    // Resolve or reject based on status code.
                    res.statusCode !== 200 ? reject(parsedBody) : resolve(parsedBody);
                );
            );

            // Make sure to write the request body.
            req.write(requestBody);
            req.end();
            req.on('error', function (e)  reject(e); );
        );
    


export default ApiExample;

【讨论】:

【参考方案3】:

如果你使用的是 axios 包,这里是解决方案。

如果标题为Content-type: 'application/x-www-form-urlencoded'

那么你将调用 post API 为

const response: any = await axios.post(URL, bodyData,  
                headers: 
                    'Content-Type': 'application/x-www-form-urlencoded'
                
            );

URL 是您的 API url,例如 http//YOUR_HOST/XYZ...,以及

bodyData 是您要在 post API 中发送的数据,

现在你将如何通过它?

假设你有数据作为对象,所以你必须将它编码为 url,让我告诉你

let data = 
username: name,
password: password

那么你的 bodyData 会是这样的

let bodyData = `username=$name&amp;password=$password`

如果标题是,这是您可以在正文中传递数据的方式 Content-type: 'application/x-www-form-urlencoded'

如果您有大量无法手动编码的数据,则可以使用qs 模块

运行命令npm i qs 并在您的文件中

const qs = require('qs');

...

let data = 
username: name,
password: password,
manyMoreKeys: manyMoreValues
 
 
let bodyData = qs.stringify(data);

【讨论】:

【参考方案4】:

使用节点的 URLSearchParams 类将 js 对象编码为“url 编码”形式,并将字符串作为请求正文传递。 Documentation

【讨论】:

一个代码示例可能会更清楚地解释这一点:``` const a = new URLSearchParams(); a.append('测试', '值'); a.append('test2', 'value2');控制台.log(a.toString()); // 将记录 'test=value&test2=value2' ```【参考方案5】:

如果您使用的是got package

const got = require('got');
const qs = require('qs');

const body = qs.stringify(
    a: 'd',
    b: 'b',
    c: 'c',
);

在异步函数中

const response = await got.post(url,  body );

如果 Content-Type 标头不存在,它将被设置为 application/x-www-form-urlencoded

【讨论】:

【参考方案6】:

我认为got package 具有有效的内置功能:

const got = require('got');

const response = await got.post(url, form: a: 'd', b: 'b', c: 'c');

【讨论】:

以上是关于如何使用内容类型 ='application/x-www-form-urlencoded' 在 node.js 中发布数据的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Spring Boot Web 客户端为内容类型 application/x-www-form-urlencoded 的表单数据发布请求

使用 Firefox 的 HTTP 内容类型“application/x-itunes-itlp”

如何使用 Bubblewrap HTTP 设置内容类型?

使用“application/x-www-form-urlencoded”内容类型请求标头时,未正确发送 HttpClient 后正文参数

使用内容类型为:application/x-www-form-urlencoded 的 POST Fetch 调用时,从服务器返回本机 422 Unprocessable Entity 错误

@RequestBody MultiValueMap 不支持内容类型 'application/x-www-form-urlencoded;charset=UTF-8'