无法从 Web 浏览器复制 GET 请求

Unable to replicate GET request from web browser

提问人:StuffHappens 提问时间:11/12/2023 最后编辑:StuffHappens 更新时间:11/17/2023 访问量:154

问:

我正在尝试从 Chrome 浏览器复制请求。 当我打开 url https://ticket.bolshoi.ru/shows 时,有一个 GET 请求 https://ticket.bolshoi.ru/api/v1/client/shows 女巫返回 json。 我从 DevTools 复制了 cURL 请求。这是我得到的:

curl 'https://ticket.bolshoi.ru/api/v1/client/shows' \
  -H 'Accept: application/json, text/plain, */*' \
  -H 'Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7' \
  -H 'Connection: keep-alive' \
  -H 'Cookie: skipped for security reason' \
  -H 'Referer: https://ticket.bolshoi.ru/shows' \
  -H 'Sec-Fetch-Dest: empty' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' \
  -H 'sec-ch-ua: "Chromium";v="118", "Google Chrome";v="118", "Not=A?Brand";v="99"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "Windows"' \
  --compressed

但是当我在 bash shell 中运行此命令时,我得到一个 html 页面作为响应,而不是 json。 为什么会这样?如何复制请求?

更新这是我向命令添加键的输出-Lkvcurl

    *   Trying 185.169.155.232:443...
    * Connected to ticket.bolshoi.ru (185.169.155.232) port 443 (#0)
    * ALPN, offering h2
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *  CAfile: /Users/xxx/opt/anaconda3/ssl/cacert.pem
    *  CApath: none
    * TLSv1.3 (OUT), TLS handshake, Client hello (1):
    * TLSv1.3 (IN), TLS handshake, Server hello (2):
    * TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
    * TLSv1.3 (IN), TLS handshake, Certificate (11):
    * TLSv1.3 (IN), TLS handshake, CERT verify (15):
    * TLSv1.3 (IN), TLS handshake, Finished (20):
    * TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
    * TLSv1.3 (OUT), TLS handshake, Finished (20):
    * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
    * ALPN, server accepted to use http/1.1
    * Server certificate:
    *  subject: CN=ticket.bolshoi.ru
    *  start date: Oct 11 23:02:07 2023 GMT
    *  expire date: Jan  9 23:02:06 2024 GMT
    *  issuer: C=US; O=Let's Encrypt; CN=R3
    *  SSL certificate verify ok.
    > GET /shows HTTP/1.1
    > Host: ticket.bolshoi.ru
    > Accept-Encoding: deflate, gzip
    > Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
    > Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
    > Cache-Control: no-cache
    > Connection: keep-alive
    > Cookie: spid=xxx; lang=xxx; sails.sid=xxx; spsc=xxx
    > Pragma: no-cache
    > Sec-Fetch-Dest: document
    > Sec-Fetch-Mode: navigate
    > Sec-Fetch-Site: cross-site
    > Sec-Fetch-User: ?1
    > Upgrade-Insecure-Requests: 1
    > User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
    > sec-ch-ua: "Chromium";v="118", "Google Chrome";v="118", "Not=A?Brand";v="99"
    > sec-ch-ua-mobile: ?0
    > sec-ch-ua-platform: "macOS"
    > 
    * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
    * TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
    * old SSL session ID is stale, removing
    * Mark bundle as not supporting multiuse
    < HTTP/1.1 200 OK
    < Server: nginx
    < Date: Wed, 15 Nov 2023 19:09:06 GMT
    < Transfer-Encoding: chunked
    < Connection: keep-alive
    < Keep-Alive: timeout=15
    < access-control-allow-origin: *
    < cache-control: no-cache
    < expires: Wed, 15 Nov 2023 19:0905 GMT
    < pragma: no-cache
    < content-type: text/html
    < X-SP-CRID: xxx:1
    < 
    <!DOCTYPE html>
    ...
</html>
* Connection #0 to host ticket.bolshoi.ru left intact

更新了 2.
以下是来自网络浏览器的一些屏幕截图:
enter image description here enter image description here

google-chrome http curl 开发工具

评论

1赞 shellter 11/14/2023
也许 stackoverflow.com/questions/77465413/ 中的答案/评论会给你一些想法。祝你好运。
2赞 VonC 11/15/2023
您能否添加选项 ,以获取更多详细信息(并使用 )进行任何重定向?-Lkv-L
0赞 StuffHappens 11/16/2023
谢谢你的评论。更新了我的问题

答:

5赞 VonC 11/16/2023 #1

命令的详细输出确认已成功连接到端口 443,这意味着基本连接没有问题。curlticket.bolshoi.ru

请求标头似乎设置得当。但是,标头设置为接受 HTML()、XML、图像和其他类型,但不显式接受 JSON。这可能就是服务器使用 HTML 页面而不是 JSON 响应进行响应的原因。Accepttext/html

响应标头指示服务器正在使用内容类型进行响应,该内容类型与您收到的 HTML 响应(而不是 JSON)匹配。text/html

因此,请尝试更改 cURL 请求中的标头,以显式请求 JSON。
例如:。这会通知服务器您正在等待 JSON 响应。
Accept-H 'Accept: application/json'

假设 cURL 命令 () 中的 URL 是获取 JSON 数据的正确端点,则 cURL 命令的更新版本为:https://ticket.bolshoi.ru/api/v1/client/shows

curl 'https://ticket.bolshoi.ru/api/v1/client/shows' \
  -H 'Accept: application/json' \
  -H 'Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7' \
  -H 'Connection: keep-alive' \
  -H 'Cookie: [Your Cookie Data]' \
  -H 'Referer: https://ticket.bolshoi.ru/shows' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' \
  -Lkv

尝试过这个,但没有成功。响应仍为 HTML 页面。

如果同一 URL 在通过浏览器访问时返回 JSON,请考虑浏览器可能正在发送 cURL 命令中未包含的其他会话数据或 Cookie。有时,API 会根据特定于会话的数据提供不同的内容。如果您还没有,请尝试从浏览器请求中复制所有 cookie,并将它们包含在您的 cURL 命令中。

服务器可能会区分浏览器(通常可以处理 HTML 和 JavaScript)发出的请求和非浏览器客户端(如 cURL)发出的请求(通常需要 JSON 等原始数据)。这种区分可以基于除 以外的标头,例如 。尝试在 cURL 命令中更改 以模拟不同的浏览器,并查看响应是否更改。AcceptUser-AgentUser-Agent

使用浏览器开发者工具中的网络检查器来检查访问 URL 时发出的确切请求。这可以深入了解浏览器请求和 cURL 命令之间的任何差异。
确保浏览器发送的所有标头都复制到 cURL 请求中,而不仅仅是标头。这包括 cookie、user-agent 和任何其他可能影响服务器响应的标头。
Accept

如果页面执行 JavaScript 来获取 JSON 数据,则 cURL 命令不会复制此行为,因为它不执行 JavaScript。如果 JSON 数据在初始页面加载后通过 JavaScript 动态加载,则这一点尤其重要。https://ticket.bolshoi.ru/shows


您提供的屏幕截图显示了返回 JSON 的成功浏览器请求,如响应标头所示。https://ticket.bolshoi.ru/api/v1/client/showsContent-Typeapplication/json;charset=UTF-8

它还显示服务器正在使用内容编码。确保可以使用 处理 gzip 响应。gzipcurl--compressed

响应标头指示 和 。虽然默认情况下不缓存,但确保连接持久性可以更准确地反映浏览器行为。no-cache, no-store, must-revalidatekeep-alivecurl-H 'Connection: keep-alive'

服务器可以根据字符串提供不同的内容。匹配命令中的 from the browser 请求(如果尚未这样做)。User-AgentUser-Agentcurl

如果浏览器会话中涉及的命令中不存在的 cookie,则服务器可能需要这样做才能正确响应。您可以尝试在命令中包含来自浏览器请求的所有 cookie。curlcurl

虽然屏幕截图中未显示,但有时服务器会检查 和 标头以处理请求。如果您的浏览器请求包含这些内容,则还应将它们包含在您的命令中。RefererOrigincurl

下面是一个命令模板,您可以修改以包含浏览器请求中的所有相关标头:curl

curl 'https://ticket.bolshoi.ru/api/v1/client/shows' \
  -H 'Accept: application/json' \
  -H 'Accept-Encoding: gzip, deflate, br' \
  -H 'Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Cookie: [all cookies from browser]' \
  -H 'Host: ticket.bolshoi.ru' \
  -H 'Referer: [referer from the browser]' \
  -H 'User-Agent: [user-agent from the browser]' \
  -H 'X-Requested-With: XMLHttpRequest' \
  --compressed \
  -Lkv

将占位符(例如,、、)替换为浏览器请求中的实际值。
该标志将跟随重定向,将忽略 SSL 验证(谨慎使用),并将提供详细的输出以进行调试。
[all cookies from browser][referer from the browser][user-agent from the browser]-L-k-v

评论

0赞 StuffHappens 11/16/2023
尝试过这个,但没有成功。响应仍然是 html 页面。
1赞 VonC 11/16/2023
@StuffHappens 这就是为什么我假设/询问该端点是否返回 JSON。您是否确认 ticket.bolshoi.ru/api/v1/client/shows 在浏览器中返回 JSON?
0赞 StuffHappens 11/17/2023
我添加了 Web 浏览器的屏幕截图,您可以在其中看到响应是 json。我从 Chrome 开发工具复制了请求,它复制了所有标头(Accept、User-Agent 等)和所有 cookie。所以我敢肯定,Web 浏览器请求和 cURL 请求中的标头是相同的。我不知道为什么结果会有所不同。
0赞 VonC 11/17/2023
@StuffHappens OK。我已经编辑了答案以解决您的评论。您可能已经包含了我提到的大部分内容,但是,为了以防万一,请仔细检查这些选项。
0赞 lprakashv 11/21/2023
您确定@StuffHappens已将标头与浏览器中的正确 cookie 一起使用吗?Cookie: [all cookies from browser]