POST请求 之 对数据进行编码处理

Posted 前端学长Joshua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POST请求 之 对数据进行编码处理相关的知识,希望对你有一定的参考价值。

POST请求 之 对数据进行编码处理

<!-- TOC -->

  • URLSearchParams

    • URLSearchParams 的读取和转换操作
    • url.searchParams
    • 让 URLSearchParams 作为Fetch的请求体(body)
  • FormData

    • 让 FormData 作为Fetch的请求体(body)
    • 转换为 URLSearchParams
    • 将Fetch的body读取为 FormData
  • 其他可以作为Fetch的body的格式

    • Blobs
    • Strings
    • Buffers
    • Streams
  • 最后的福利:将 FormData 转换为 JSON
  • 参考

<!-- /TOC -->
好,来。我们先来先来看个代码例子:

async function isPositive(text) {
  const response = await fetch(`http://text-processing.com/api/sentiment/`, {
    method: \'POST\',
    body: `text=${text}`,
    headers: {
      \'Content-Type\': \'application/x-www-form-urlencoded\',
    },
  });
  const json = await response.json();
  return json.label === \'pos\';
}

这块代码写得比较糟糕,可能会导致安全问题。 为什么呢?因为:text=${text} 这块地方存在问题:

未转义的文本被添加到具有定义编码的格式中。就是说,这里的text变量,它是没有经过转义(或者说是编码)就直接被写到了请求体中,而在这个请求中,是有要求编码格式的\'Content-Type\': \'application/x-www-form-urlencoded\'

这种写法有点类似于 SQL/html 注入,因为某种旨在作为“值”的东西(指类似text变量的一些值)可以直接与格式进行交互。

所以,我将深入研究正确的方法,同时也会浏览一些相关的、鲜为人知的 API:

URLSearchParams

URLSearchParams 可以用来 处理编码和解码 application/x-www-form-urlencoded 数据。 它非常方便,因为,嗯……

The application/x-www-form-urlencoded format is in many ways an aberrant monstrosity, the result of many years of implementation accidents and compromises leading to a set of requirements necessary for interoperability, but in no way representing good design practices. In particular, readers are cautioned to pay close attention to the twisted details involving repeated (and in some cases nested) conversions between character encodings and byte sequences. Unfortunately the format is in widespread use due to the prevalence of HTML forms. — The URL standard

......所以,是的,非常不建议你自己 对 application/x-www-form-urlencoded 的数据进行编码/解码。

下面是URLSearchParams的工作原理:

const searchParams = new URLSearchParams();
searchParams.set(\'foo\', \'bar\');
searchParams.set(\'hello\', \'world\');

// Logs \'foo=bar&hello=world\'
console.log(searchParams.toString());

URLSearchParams这个构造函数还可以接受一个[key, value]对的数组,或一个产生[key, value]对的迭代器:

const searchParams = new URLSearchParams([
  [\'foo\', \'bar\'],
  [\'hello\', \'world\'],
]);

// Logs \'foo=bar&hello=world\'
console.log(searchParams.toString());

或者是一个对象:

const searchParams = new URLSearchParams({
  foo: \'bar\',
  hello: \'world\',
});

// Logs \'foo=bar&hello=world\'
console.log(searchParams.toString());

或者是一个字符串:

const searchParams = new URLSearchParams(\'foo=bar&hello=world\');

// Logs \'foo=bar&hello=world\'
console.log(searchParams.toString());

URLSearchParams 的读取和转换操作

读取(指对数据进行枚举等读取操作)和转换(指将其转为数组或者对象等) URLSearchParams 的方法还是很多的,MDN 上都有详细说明。

如果在某些场景下,您想处理所有数据,那么它的迭代器就派上用场了:

const searchParams = new URLSearchParams(\'foo=bar&hello=world\');

for (const [key, value] of searchParams) {
  console.log(key, value);
}

这同时意味着您可以轻松地将其转换为[key, value]对数组:

// To [[\'foo\', \'bar\'], [\'hello\', \'world\']]
const keyValuePairs = [...searchParams];

或者将它与支持生成key-value对的迭代器的 API 一起使用,例如 Object.fromEntries,可以把它转换为一个对象:

// To { foo: \'bar\', hello: \'world\' }
const data = Object.fromEntries(searchParams);

但是,请注意,转换为对象有时是有损转换的哦:就是可能会造成某些值得丢失

const searchParams = new URLSearchParams([
  [\'foo\', \'bar\'],
  [\'foo\', \'hello\'],
]);

// Logs "foo=bar&foo=hello"
console.log(searchParams.toString());

// To { foo: \'hello\' }
const data = Object.fromEntries(searchParams);

url.searchParams

URL 对象上有一个 searchParams 属性,非常方便地获取到请求参数:

const url = new URL(\'https://jakearchibald.com/?foo=bar&hello=world\');

// Logs \'world\'
console.log(url.searchParams.get(\'hello\'));

不幸的是,在window.location上没有location.searchParams这个属性。

这是因为 window.location 由于它的某些属性如何跨源工作而变得复杂。 例如设置 otherWindow.location.href 可以跨源工作,但不允许获取它。

但是无论如何,我们都要解决它,让我们能比较容易地从地址栏中获取到请求参数:

// Boo, undefined
location.searchParams;

const url = new URL(location.href);
// Yay, defined!
url.searchParams;

// Or:
const searchParams = new URLSearchParams(location.search);

让 URLSearchParams 作为Fetch的请求体(body)

好的,现在我们进入正题。 文章开头示例中的代码存在一些问题,因为它没有进行转义输入:

const value = \'hello&world\';
const badEncoding = `text=${value}`;

// 

以上是关于POST请求 之 对数据进行编码处理的主要内容,如果未能解决你的问题,请参考以下文章

get/post请求中文出现乱码解决

get请求和post的请求的乱码解决

jmeter请求之get与post的区别?

Python Django之GET请求和POST请求及响应处理

求教golang中http发送post请求gb2312编码的解决方案

3.Python Django之GET请求和POST请求及响应处理