【发布时间】:2019-08-09 20:41:36
【问题描述】:
阅读前注意
这不是what-are-differences-between-xmlhttprequest-and-httprequest 的副本 对于信息,我尝试了this lib,但没有成功,因为它复制了 XMLHttpRequest 的结构,但实际上并没有像它那样工作。
我想知道来自 Node 的 HttpRequest 和来自浏览器的 XMLHttpRequest 之间真正的网络区别是什么。
如果我只是在 chrome 的 devtools 中查看 XMLHttpRequest,我在请求中看不到任何 X-Requested-with 标头。
此外,CloudFlare 的 WAF 背后还有一个在线服务,带有自定义规则。如果我使用XMLHttpRequest 发出请求,它就可以正常工作,但我使用https.request 发出请求,它无法被 CF 防火墙。
我需要使用HttpRequest 来配置代理。
两者之间的网络区别是什么,如何从 HttpRequest 模拟 XMLHttpRequest ?这甚至可能吗? 我看了铬的来源here 却找不到什么有趣的东西。
也许它与 IO 层不同? TCP 握手?
需要建议。谢谢
编辑
这是 XMLHttpRequest(工作)
let req = new XMLHttpRequest();
req.open("post", "https://haapi.ankama.com/json/Ankama/v2/Api/CreateApiKey", true);
req.withCredentials = true;
req.setRequestHeader('Accept', 'application/json');
req.setRequestHeader('Content-Type', 'text/plain;charset=UTF-8');
req.setRequestHeader('Accept-Encoding', 'gzip, deflate, br');
req.onload = function() {
console.log(req.response)
};
req.send("login=smallladybug949&password=Tl9HDKWjusopMWy&long_life_token=true");
与 cURL 相同(不通过 CF 的防火墙)
curl 'URL' \
-H 'origin: null' \
-H 'accept-encoding: gzip, deflate, br' \
-H 'user-agent: Mozilla/5.0 (Linux; Android 6.0.1; Z988 Build/MMB29M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/69.0.3497.100 Mobile Safari/537.36' \
-H 'content-type: text/plain;charset=UTF-8' \
-H 'accept: application/json' \
-H 'authority: URL.com' \
--data-binary 'login=123&password=def' \
--compressed
这里是 HttpRequest(不通过 CF 的防火墙)
let opts = url.parse(URL);
opts.method = post;
opts.headers = {
'Accept': 'application/json',
'Content-Type': 'text/plain;charset=UTF-8',
'Accept-Encoding': 'gzip, deflate, br',
'User-Agent': 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36'
}
let req = https.request(opts, function (res) {
res.setEncoding('utf8');
res.body = "";
res.on('data', (chunk) => {
res.body += chunk;
});
res.on('end', (chunk) => {
try {
res.body = JSON.parse(res.body);
} catch (e) {
return reject(res.body); // error, http 403 / 1020 error from CF (custom FW rule)
}
console.log(res.body); // we'll not reach this
});
});
req.on('error', e => {
console.error('error', e);
});
req.write("login=abc&password=def");
req.end();
编辑 2
经过几次测试,curl 命令可以正常工作,XHR 也可以,但是使用 Postman 或 HttpRequest,它会失败。 这是邮递员与 curl 的视频:https://streamable.com/81s57 视频中的 curl 命令是这样的:
curl -X POST \
https://haapi.ankama.com/json/Ankama/v2/Api/CreateApiKey \
-H 'accept: application/json' \
-H 'accept-encoding: gzip, deflate, br' \
-H 'accept-language: fr' \
-H 'authority: haapi.ankama.com' \
-H 'content-type: text/plain;charset=UTF-8' \
-H 'origin: null' \
-H 'user-agent: Mozilla/5.0 (Linux; Android 8.0.0; SM-G960F Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36' \
-d 'login=smallladybug949&password=Tl9HDKWjusopMWy&long_life_token=true'
(这是一个测试帐户,所以我不需要它,您可以使用它进行测试)。您可以将 --compressed 标志添加到 curl 请求以将其解压缩或通过管道将其发送到 gunzip。
编辑 3(最终)
我发现这是由于滥用(对于 CF)TLS 协议造成的。通过降级使用 OpenSSL/1.1.0f 的 curl,调用就可以正常工作了。但自从 OpenSSL/1.1.0g 之后,它们就没有了。 您可以阅读有关 OpenSSL 更改日志的更多信息here
【问题讨论】:
-
我在发布之前做过,但它没有回答真正的问题,这些是解释的话,但我需要技术细节。网络中的“获取资源”是什么意思?它仍然是套接字连接吗?当然,因为每个连接都有一个套接字,但是 是 使请求被 CF 的防火墙阻止的真正区别。在他们的网站上,他们谈论“如何提出请求”。也许这里面有暗示。
-
@Sw0ut 来自浏览器的 XHR 请求发送各种标头,如“User-Agent”和“Referrer”,但从 Node 服务器发出的请求并非如此,即。 Http请求。服务器上的来源实际用于检测请求来源的安全目的。
-
@AkanshGulati 是的,但我也发送了带有 HttpRequest 的 User-Agent 标头,但它仍然被阻止。我从人类的角度提出了完全相同的要求。相同的 URL,相同的标头,相同的参数。我将编辑我的问题,以添加有关我如何处理双方请求的更多详细信息。
-
@Sw0ut 如果您可以将这两个请求共享为 cUrl,那就太好了,以便可以比较标头、方法类型、正文、查询参数、协议、路径名等所有内容。另外,我希望您了解浏览器针对任何跨域请求发出的飞行前请求。
标签: javascript networking xmlhttprequest httprequest