Javascript user-agent (ajax) отличается от отправленного user-agent при запросе веб-сайта
я заметил, что Chrome (64.0.3282.137) на моем телефоне (OnePlus 3, Android 8.0.0) отправляет немного разные пользовательские агенты при запросе веб-страницы в отличие от запроса через ajax.
этот user-agent отправляется при запросе веб-страницы:
Mozilla/5.0 (Linux; Android 8.0.0; ONEPLUS A3003 Build/OPR6.170623.013) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36
этот пользовательский агент отправляется с ajax-вызовом и также возвращается при вызове navigator.userAgent
:
Mozilla/5.0 (Linux; Android 8.0.0; Build/OPR6.170623.013) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36
отличия: ONEPLUS A3003
можете ли вы сказать, почему модель входит в родные вызовы, но не в ajax-вызовы?
дополнительная информация: с"запрос рабочего стола сайта" -функция включена агент пользователя
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Safari/537.36
в обоих случаях.
2 ответов
Я проанализировал исходный код chromium, чтобы получить некоторые идеи. Я смог добраться только до некоторого уровня с моими начинающими способностями на c++.
агент пользователя клиента или платформы обнаружен в этом блоке кода (файл: useragent.cc).
std::string BuildUserAgentFromProduct(const std::string& product) {
std::string os_info;
base::StringAppendF(
&os_info,
"%s%s",
getUserAgentPlatform().c_str(),
BuildOSCpuInfo().c_str());
return BuildUserAgentFromOSAndProduct(os_info, product);
}
вы можете увидеть BuildOSCpuInfo () в блоке кода, который заботится о добавлении ОС realted информации на основе платформ, которые можно найти здесь
std::string android_build_codename = base::SysInfo::GetAndroidBuildCodename();
std::string android_device_name = base::SysInfo::HardwareModelName(); // this line in particular adds the ONEPLUS A3003
но эта функция (BuildUserAgentFromProduct ()) является не используется непосредственно в модуле net, который заботится о отправке http-запросов.
когда я исследовал код для модуля net (http), я вижу, что они получают useragent* и обрабатывают его с помощью ряда манипуляций со строками и функций обрезки пробела. AddHeadersFromString () в http_request_headers.cc является интерфейсом, через который строка useragent добавляется в заголовок запроса.
Примечание*: но я думаю, что данные заголовка не от useragent.cc, потому что я не могу найти вызовы для этой функции в любом месте. Но здесь я могу ошибаться.
* * Я считаю, что это место, где значение для OSInfo изменяется. Любой символ пробела, который не распознается или в неправильном формате, который изначально предназначался, может дать этот результат.
примечание**: Я не мог проверить приведенное выше утверждение и доказать его, потому что строка, используемая в Chromium, имеет обертку вокруг нее во имя StringPiece( * wrapper - это просто термин, который я использую, технически его можно назвать по-другому, чего я не знаю.). И я не знаю, как написать код на c++ для StringPiece.
но очень простой пример, как это может пойти не так, приведен ниже.
int main()
{
std::string s = " ONEPLUS\rA3003\rBuild/OPR6.170623.013";
std::string delimiter = "\r\n"; //this is the delimeter used in chromium source code.
std::string token = s.substr(0, s.find(delimiter,0));
std::cout << token << std::endl;
return 0;
}
https://www.onlinegdb.com/SkTrbFJDz
переход к причине, по которой начальная строка агента пользователя имеет значение, а последующий http-запрос не имеет значения, лежит с архитектура приложения chrome в android. Когда страница загружается изначально, значения фактически устанавливаются приложением chrome (очень большая база кода java, но я думаю, что основной файл, который нам нужно увидеть, - это LoadUrlParams.java), который имеет другую реализацию отправки http-запроса (здесь useragent не обрезается тем же модулем net(http), а заботится о его реализации Java), это происходит только во время самой первой загрузки. Но любые другие последующие вызовы используют браузер модуль net (http).
Ссылка На Файл связи: https://cs.chromium.org/chromium/src/content/common/user_agent.cc?sq=package:chromium&dr=CSs&l=80
Я просто включая этот ответ, чтобы дать одну из причин, по которой могла возникнуть проблема. Если у меня будет еще немного времени, я посмотрю, смогу ли я как-то провести тест и доказать это. Последнее замечание этот ответ не дает никакого решения для устранения проблемы. Это просто дает причину для причины.
[обновление]
один очень дешевый трюк, чтобы увидеть, если навигатор.useragent имеет значение oneplus и устанавливает заголовки ajax в запросе и отправляет его. Это переопределит механизм браузера добавление заголовка агента пользователя.
XMLHttpRequest.setRequestHeader(header, value)
в первом userAgent браузер идентифицирует устройство как мобильное устройство, изменяя userAgent перед выполнением запроса; следовательно,ONEPLUS A3003
. Во втором, однако, из-за спецификации w3 (найти его здесь), вы не можете изменить userAgent; следовательно, пропуск ONEPLUS A3003
.
когда вы используете функцию "запрос рабочего стола", нет необходимости в модификации userAgent браузером, следовательно, вы получаете тот же userAgent.
примечание: что по умолчанию userAgent для этого браузера Chrome:
Mozilla/5.0 (Linux; Android 8.0.0; Build/OPR6.170623.013) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.137 Mobile Safari/537.36