Curl - 节点(子进程)和终端的不同结果

Viv*_*ppo 5 javascript bash curl http node.js

所以我无意中发现了一些奇怪的东西,但不明白为什么会这样。

我在我的终端(iTerm 上是 ZSH)中创建了这个curl:

curl -I https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find\?text\=1%20TX%2077979\&f\=json
Run Code Online (Sandbox Code Playgroud)

响应是:

HTTP/2 200
date: Wed, 28 Oct 2020 17:31:12 GMT
content-type: application/json;charset=UTF-8
content-length: 374
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
server:
etag: dc0a3f17
x-esri-ftiles-cache-compress: true
cache-control: max-age=300
x-cached: MISS
vary: Origin,Accept-Encoding
strict-transport-security: max-age=31536000
Run Code Online (Sandbox Code Playgroud)

但是如果我在节点(v14.14.0)中运行与 exec child_process 相同的curl,如下所示:

const { exec } = require('child_process');
const url = 'https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/find\?text\=1%20TX%2077979\&f\=json';

return exec(`curl -I ${url}`, (err, std) => {
  console.log(std);
});
Run Code Online (Sandbox Code Playgroud)

响应如下所示:

HTTP/2 403 
date: Wed, 28 Oct 2020 17:17:18 GMT
content-type: text/html;charset=utf-8
content-length: 680
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
server: 
Run Code Online (Sandbox Code Playgroud)

谁能给我解释一下吗?

- - - 编辑 - - -

致安德鲁:我使用的网址包含“&”,但它们以“&query=”结尾,这不是强制性的,它仍然返回 HTTP 200 和其他需要的信息,这就是为什么我什至没有注意到。

Viv*_*ppo 1

正如@drew010 所写:

正如您所发现的,如果 URL 包含 & 字符,则需要引用该 URL,因为 shell 将其解释为控制运算符。如果 & 出现在命令或参数中的任何位置并且没有被引用或转义 & 我认为您会一直遇到同样的问题。

好的,根据文档(https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback

传递给 exec 函数的命令字符串由 shell 直接处理,特殊字符(根据 shell 不同)需要进行相应处理:

因此,在以同样的方式执行“echo”之后,我发现 url 的末尾(“&f=json”)已被删除。

在 url 变量插值周围添加引号后,它工作正常。

exec(`curl -I "${url}"`, (err, std) =>
Run Code Online (Sandbox Code Playgroud)

我最初的困惑“为什么它应该做同样的事情时不同”也是我相信“exec”只会将它传递到我正在使用的终端的一部分,正如我之前提到的,它是带有 ZSH 的 iTerm,因为它是设置为我的操作系统上的默认终端。这个假设是错误的,文档中提到了这一点:

shell 用于执行命令的 Shell。请参阅 Shell 要求和默认 Windows shell。默认值:Unix 上的“/bin/sh”

所以它不使用默认的操作系统终端,而只是使用 sh。但可以通过“shell”选项使用您想要的任何内容。