[axios]获取请求参数 URI 编码

2024-08-22 17 views
9
 概括

buildURL.js 中的函数 encode(val) 将空格编码为 '+' 这是错误的,因为并非所有 http 服务器都会解码 '+'

我注释掉了一行并且它对我有用。

函数编码(val){返回encodeURIComponent(val)。替换(/%40 / gi,'@')。替换(/%3A / gi,':')。替换(/%24 / g,'$')。替换(/%2C / gi,',')。//替换(/%20 / g,'+')。替换(/%5B / gi,'[')。替换(/%5D / gi,']');}

 语境
  • axios 版本:例如:v0.16.0
  • 环境:例如:node v6.9.4,chrome 54,windows 7

回答

5

在注释掉此行之前,您能否提供编码失败的数据示例?

7

视图:{类型:“Номенклатура”,父级:'00000000-0000-0000-0000-000000000000',组:true,元素:false,过滤器:'Таблица.ЭтоГруппа ИЛИ ИТлица.Ост атокОбщий <> 0' }

过滤器值字符串中的空格是 utf-8 西里尔字母和拉丁符号的混合

2

该问题是否仅发生在filter价值上?

您能提供注释掉该行之前和之后的最终 URL 吗?

4

之前: http://localhost:3000/api/backend?r=%7B%22r%22:%7B%22type%22:%22%D0%9D%D0%BE%D0%BC%D0%B5%D0%BD%D0%BA%D0%BB%D0%B0%D1%82%D1%83%D1%80%D0%B0%22,%22parent%22:%2200000000-0000-0000-0000-00 0000000000%22,%22groups%22:true,%22elements%22:false,%22filter%22:%22%D0%A2%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D0%B0.%D0%AD%D1%82%D0%BE%D0%93%D1%80%D1%83%D0%BF%D0%BF%D0%B0+%D0%98%D0%9B%D0 %98+%D0%A2%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D0%B0.%D0%9E%D1%81%D1%82%D0%B0%D1%82%D0%BE%D0%BA%D0%9E%D0%B1%D1%89%D0%B8%D0%B9+%3C%3E+0%22,%22cols%22:[%22%D0%9A%D0%BE%D0%B4%22,%22%D0%9D%D0% B0%D0%B8%D0%BC%D0%B5%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%22,%22%D0%90%D1%80%D1%82%D0%B8%D0%BA%D1%83%D0%BB%22,%22%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D0%B8%D1%82%D0%B 5%D0%BB%D1%8C%22,%22%D0%9E%D1%81%D1%82%D0%B0%D1%82%D0%BE%D0%BA%D0%9E%D0%B1%D1%89%D0%B8%D0%B9%22,%22%D0%9D%D0%B0%D0%B8%D0%BC%D0%B5%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%9F%D0%B E%D0%BB%D0%BD%D0%BE%D0%B5%22,%22%D0%94%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5%D0%9D%D0%BE%D0%BC %D0%B5%D0%BD%D0%BA%D0%BB%D0%B0%D1%82%D1%83%D1%80%D1%8B%22,%22%D0%94%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD% D0%B8%D0%B5%D0%9D%D0%BE%D0%BC%D0%B5%D0%BD%D0%BA%D0%BB%D0%B0%D1%82%D1%83%D1%80%D1%8B%D0%92%D0%A4%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B5HTML%22]%7D,%22m%22:%22dict%22,%22f%22:%22list%22%7D

之后: http://localhost:3000/api/backend?r=%7B%22r%22:%7B%22type%22:%22%D0%9D%D0%BE%D0%BC%D0%B5%D0%BD%D0%BA%D0%BB%D0%B0%D1%82%D1%83%D1%80%D0%B0%22,%22parent%22:%2200000000-0000-0000-0000-000 000000000%22,%22groups%22:true,%22elements%22:false,%22filter%22:%22%D0%A2%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D0%B0.%D0%AD%D1%82%D0%BE%D0%93%D1%80%D1%83%D0%BF%D0%BF%D0%B0%20%D0%98%D0%9B%D0 %98%20%D0%A2%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D0%B0.%D0%9E%D1%81%D1%82%D0%B0%D1%82%D0%BE%D0%BA%D0%9E%D0%B1%D1%89%D0%B8%D0%B9%20%3C%3E%200%22,%22cols%22:[%22%D0%9A%D0%BE%D0%B4%22,%22%D0%9 D%D0%B0%D0%B8%D0%BC%D0%B5%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%22,%22%D0%90%D1%80%D1%82%D0%B8%D0%BA%D1%83%D0%BB%22,%22%D0%9F%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%BE%D0%B4%D0%B8%D1%82% D0%B5%D0%BB%D1%8C%22,%22%D0%9E%D1%81%D1%82%D0%B0%D1%82%D0%BE%D0%BA%D0%9E%D0%B1%D1%89%D0%B8%D0%B9%22,%22%D0%9D%D0%B0%D0%B8%D0%BC%D0%B5%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5%D0%9F%D 0%BE%D0%BB%D0%BD%D0%BE%D0%B5%22,%22%D0%94%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5%D0%9D%D0%BE%D0% %D0%B5%D0%BD%D0%BA%D0%BB%D0%B0%D1%82%D1%83%D1%80%D1%8B%22,%22%D0%94%D0%BE%D0%BF%D0%BE%D0%BB%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5%D0%9E%D0%BF%D0%B8%D1%81%D0%B0%D0%BD %D0%B8%D0%B5%D0%9D%D0%BE%D0%BC%D0%B5%D0%BD%D0%BA%D0%BB%D0%B0%D1%82%D1%83%D1%80%D1%8B%D0%92%D0%A4%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B5HTML%22]%7D,%22m%22:%22dict%22,%22f%22:%22list%22%7D

0

谢谢。您有关于服务器不接受该+字符作为空格的任何信息吗?

6

服务器:Apache/2.4.27 (Win64) OpenSSL/1.1.0f

我为无意中误导您而道歉。问题不在于 HTTP 服务器。问题在于应用程序的库。并非所有库应用程序都遵循 www.w3.org 的建议。具有讽刺意味的是,使用 %2B 代替 + 的变体可以实现与所有库的更高兼容性。

2

我认为你的意思是%20

查看 URI 的 RFC-3986 标准,2.3 中有以下信息:

      reserved    = gen-delims / sub-delims

      gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"

      sub-delims  = "!" / "$" / "&" / "'" / "(" / ")"
                  / "*" / "+" / "," / ";" / "="

gen-delims 保留在 URI 路径中,sub-delims 保留在参数之后?,并在后来的标准中[添加]。因此+不应该是问题,因为它在标准范围内,但我清楚地看到它是问题。

6

我猜你的意思是 %20?是的,我错了。

1

我遇到了类似的问题,我正在向旧服务器发出 GET 请求,但该服务器不接受+空格并且需要%20。有没有办法配置编码或跳过它?

3

paramsSerializer为了回答我自己的问题,我在配置参数中找到了有关的内容,然后paramsSerializer在代码中 找到了默认实现https://github.com/axios/axios/blob/ae218d0131ecbd683310272c10b0273fd1d97de4/lib/helpers/buildURL.js#L5-L13

https://github.com/axios/axios/blob/ae218d0131ecbd683310272c10b0273fd1d97de4/lib/helpers/buildURL.js#L35-L58 这促使我实现了自己的版本,覆盖编码器并绕过一些实用函数,因为我正在使用 TS 和 nodejs,并且我可以使用一些内置的替代方案:


function encode(val: any) {
  return encodeURIComponent(val)
    .replace(/%40/gi, '@')
    .replace(/%3A/gi, ':')
    .replace(/%24/g, '$')
    .replace(/%2C/gi, ',')
    .replace(/%5B/gi, '[')
    .replace(/%5D/gi, ']');
}

function customSerializer(params: any): string {
  return Object.keys(params)
    .map((key: any) => {
      var val: any = params[key];
      if (val === null || typeof val === 'undefined') {
        return;
      }
      var keyName = key;
      if (Array.isArray(val)) {
        keyName = key + '[]';
      } else {
        val = [val];
      }
      return val
        .map((v: any) => {
          if (Object.prototype.toString.call(v) === '[object Date]') {
            v = v.toISOString();
          } else if (v !== null && typeof v === 'object') {
            v = JSON.stringify(v);
          }
          return encode(key) + '=' + encode(v);
        })
        .join('&');
    })
    .join('&');
}
3

我刚刚意识到你设置了它,而不是 Axios 本身。抱歉,我对事情的运作方式有误解。你可以忽略我的评论,问题实际上是 Qs.stringify。

由于您可以设置自定义序列化程序,因此这个问题无论如何都不是 Axios 的问题。如果我浪费了您的时间,我很抱歉。我认为您实际上可以关闭它,因为它根本不是 Axios 错误。

8

同样的问题

8

[和有同样的问题]...

5

创建 PR #2563 来修复此问题和其他类似问题。

9

在这一点上,我不认为应该按照前面提到的那样实现,如果您想使用其他格式,您可以按如下方式设置自定义 paramsSerializer:

axios.defaults.paramsSerializer: function(params) {
  // return a query string
}

使用 qs 库:

axios.defaults.paramsSerializer: function(params) {
  return qs.stringify(params, { indices: false }); // param=value1&param=value2
}
2

在这一点上,我不认为应该按照前面提到的那样实现,如果您想使用其他格式,您可以按如下方式设置自定义 paramsSerializer:

确实,我们可以使用自定义 paramsSerializer 来使用 RFC 3986,但是我认为它应该是默认的,因为最新的 Web 服务器不会接受 RFC 1738 编码的参数,但是旧服务器应该接受 RFC 3986(至少空格的 %20 编码是向后兼容的)。

每次使用 axios 时都必须使用自定义 paramsSerializer,因此在我看来这很容易出错。