You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Node.js中直接发送包含#字符的未编码URL GET请求(无需依赖第三方NPM包)

问题描述

我知道这一情况较为特殊,但服务器端已完成实现且未集成URI编解码功能,目前无法修改。因此我需要在GET请求的URL查询参数中直接使用未编码的字符。当我请求类似https://example.com/check?id=myAccount&password=qwerty!@#这样的URL时,Node.js的http(s)模块会自动将其修改为https://example.com/check?id=myAccount&password=qwerty!@,导致我无法按预期发送数据。

请问在不使用其他NPM模块的情况下该如何解决?我已查阅Node.js官方文档但未找到答案。我使用的Node.js代码如下:

// Example : https://example.com/check?id=myAccount&password=qwerty!@#
(_url, params) => {
  return new Promise((resolve, reject) => {
    if (params) {
      let queryParams = `?`;
      for (let key in params) {
        const value = params[key];
        queryParams += `${key}=${value}&`;
      }
      queryParams = queryParams.slice(0, -1);
      _url += queryParams;
    }
    const options = {
      method: `GET`,
    }
    const req = https.request(_url, options, (res) => {
      // When I checked it, request URL is changed to https://example.com/check?id=myAccount&password=qwerty!@
      // (Removed "#" automatically)
      // console.log(req)
      let data = ``;
      res.on(`data`, (d) => {
        data += d.toString();
        process.stdout.write(d);
      });
      res.on(`end`, () => {
        // process.stdout.write(d);
        resolve(data);
      });
    });
    req.on(`error`, (e) => {
      console.error(e);
    });
    req.end();
  });
}

解决方案

这个问题的根源在于:当你直接把完整URL传给https.request()时,Node.js会自动按照URL规范解析它——而#在URL里是**片段标识符(fragment identifier)**的起始标记,不属于查询参数的一部分,所以Node.js会把它从查询参数中剥离,这就是你的#消失的原因。

要绕过这个自动解析行为,你需要手动拆分URL的各个部分,直接在options对象中指定hostname、path等字段,而不是传完整URL。这样你可以完全控制path的内容,避免Node.js自动处理特殊字符。

下面是修改后的代码:

const url = require('url'); // Node.js内置模块,无需额外安装
const https = require('https');

const sendRequest = (_url, params) => {
  return new Promise((resolve, reject) => {
    // 先解析基础URL的结构,拆分出必要部分
    const parsedUrl = url.parse(_url);
    
    let path = parsedUrl.path;
    if (params) {
      // 手动拼接查询参数,不做任何编码处理
      let queryParams = `?`;
      for (let key in params) {
        const value = params[key];
        queryParams += `${key}=${value}&`;
      }
      queryParams = queryParams.slice(0, -1);
      path += queryParams;
    }

    const options = {
      method: 'GET',
      hostname: parsedUrl.hostname,
      path: path, // 直接使用手动拼接的路径+参数,不会被自动编码
      protocol: parsedUrl.protocol,
      port: parsedUrl.port || (parsedUrl.protocol === 'https:' ? 443 : 80)
    }

    const req = https.request(options, (res) => {
      let data = '';
      res.on('data', (d) => {
        data += d.toString();
        process.stdout.write(d);
      });
      res.on('end', () => {
        resolve(data);
      });
    });

    req.on('error', (e) => {
      console.error(e);
      reject(e);
    });

    req.end();
  });
}

// 使用示例
sendRequest('https://example.com/check', {
  id: 'myAccount',
  password: 'qwerty!@#'
})
.then(data => console.log('Response:', data))
.catch(err => console.error('Error:', err));

关键说明:

  • 用Node.js内置的url模块解析基础URL,拆分出hostname、protocol、path等部分,避免手动处理这些细节出错。
  • 手动拼接查询参数到path中,直接把这个path传给options,Node.js不会再对它进行自动编码或解析,这样#就能原封不动地发送到服务器。
  • 处理了端口号的默认值(https默认443,http默认80),确保请求能正常连接。

这样修改后,你的请求URL就会保持你想要的原始格式,不会被Node.js自动修改了。

内容的提问来源于stack exchange,提问作者Park

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 04:27:34