| use super::utils::generate_hash; |
| use crate::{app::{ |
| constant::{ |
| CONTENT_TYPE_CONNECT_PROTO, CURSOR_API2_HOST, CURSOR_HOST, CURSOR_SETTINGS_URL, |
| HEADER_NAME_GHOST_MODE, TRUE, |
| }, |
| lazy::{ |
| CURSOR_API2_CHAT_URL, CURSOR_API2_CHAT_WEB_URL, CURSOR_API2_STRIPE_URL, CURSOR_USAGE_API_URL, CURSOR_USER_API_URL, REVERSE_PROXY_HOST, USE_REVERSE_PROXY |
| }, |
| }, AppConfig}; |
| use reqwest::header::{ |
| ACCEPT, ACCEPT_ENCODING, ACCEPT_LANGUAGE, CACHE_CONTROL, CONNECTION, CONTENT_TYPE, COOKIE, |
| DNT, HOST, ORIGIN, PRAGMA, REFERER, TE, TRANSFER_ENCODING, USER_AGENT, |
| }; |
| use reqwest::{Client, RequestBuilder}; |
| use std::sync::LazyLock; |
| use uuid::Uuid; |
|
|
| macro_rules! def_const { |
| ($name:ident, $value:expr) => { |
| const $name: &'static str = $value; |
| }; |
| } |
|
|
| def_const!(SEC_FETCH_DEST, "sec-fetch-dest"); |
| def_const!(SEC_FETCH_MODE, "sec-fetch-mode"); |
| def_const!(SEC_FETCH_SITE, "sec-fetch-site"); |
| def_const!(SEC_GPC, "sec-gpc"); |
| def_const!(PRIORITY, "priority"); |
|
|
| def_const!(ONE, "1"); |
| def_const!(ENCODINGS, "gzip,br"); |
| def_const!(VALUE_ACCEPT, "*/*"); |
| def_const!(VALUE_LANGUAGE, "zh-CN"); |
| def_const!(EMPTY, "empty"); |
| def_const!(CORS, "cors"); |
| def_const!(NO_CACHE, "no-cache"); |
| def_const!(UA_WIN, "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"); |
| def_const!(SAME_ORIGIN, "same-origin"); |
| def_const!(KEEP_ALIVE, "keep-alive"); |
| def_const!(TRAILERS, "trailers"); |
| def_const!(U_EQ_4, "u=4"); |
|
|
| def_const!(PROXY_HOST, "x-co"); |
|
|
| pub(crate) static HTTP_CLIENT: LazyLock<parking_lot::RwLock<Client>> = |
| LazyLock::new(|| parking_lot::RwLock::new(AppConfig::get_proxies().get_client())); |
|
|
| |
| |
| |
| pub fn rebuild_http_client() { |
| let new_client = AppConfig::get_proxies().get_client(); |
| let mut client = HTTP_CLIENT.write(); |
| *client = new_client; |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| pub fn build_client(auth_token: &str, checksum: &str, is_search: bool) -> RequestBuilder { |
| let trace_id = Uuid::new_v4().to_string(); |
| let url = if is_search { |
| &*CURSOR_API2_CHAT_WEB_URL |
| } else { |
| &*CURSOR_API2_CHAT_URL |
| }; |
|
|
| let client = if *USE_REVERSE_PROXY { |
| HTTP_CLIENT |
| .read() |
| .post(url) |
| .header(HOST, &*REVERSE_PROXY_HOST) |
| .header(PROXY_HOST, CURSOR_API2_HOST) |
| } else { |
| HTTP_CLIENT |
| .read() |
| .post(url) |
| .header(HOST, CURSOR_API2_HOST) |
| }; |
|
|
| client |
| .header(CONTENT_TYPE, CONTENT_TYPE_CONNECT_PROTO) |
| .bearer_auth(auth_token) |
| .header("connect-accept-encoding", ENCODINGS) |
| .header("connect-protocol-version", ONE) |
| .header(USER_AGENT, "connect-es/1.6.1") |
| .header("x-amzn-trace-id", format!("Root={}", trace_id)) |
| .header("x-client-key", generate_hash()) |
| .header("x-cursor-checksum", checksum) |
| .header("x-cursor-client-version", "0.42.5") |
| .header("x-cursor-timezone", "Asia/Shanghai") |
| .header(HEADER_NAME_GHOST_MODE, TRUE) |
| .header("x-request-id", trace_id) |
| .header(CONNECTION, KEEP_ALIVE) |
| .header(TRANSFER_ENCODING, "chunked") |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| pub fn build_profile_client(auth_token: &str) -> RequestBuilder { |
| let client = if *USE_REVERSE_PROXY { |
| HTTP_CLIENT |
| .read() |
| .get(&*CURSOR_API2_STRIPE_URL) |
| .header(HOST, &*REVERSE_PROXY_HOST) |
| .header(PROXY_HOST, CURSOR_API2_HOST) |
| } else { |
| HTTP_CLIENT |
| .read() |
| .get(&*CURSOR_API2_STRIPE_URL) |
| .header(HOST, CURSOR_API2_HOST) |
| }; |
|
|
| client |
| .header("sec-ch-ua", "\"Not-A.Brand\";v=\"99\", \"Chromium\";v=\"124\"") |
| .header(HEADER_NAME_GHOST_MODE, TRUE) |
| .header("sec-ch-ua-mobile", "?0") |
| .bearer_auth(auth_token) |
| .header( |
| USER_AGENT, |
| "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Cursor/0.42.5 Chrome/124.0.6367.243 Electron/30.4.0 Safari/537.36", |
| ) |
| .header("sec-ch-ua-platform", "\"Windows\"") |
| .header(ACCEPT, VALUE_ACCEPT) |
| .header(ORIGIN, "vscode-file://vscode-app") |
| .header(SEC_FETCH_SITE, "cross-site") |
| .header(SEC_FETCH_MODE, CORS) |
| .header(SEC_FETCH_DEST, EMPTY) |
| .header(ACCEPT_ENCODING, ENCODINGS) |
| .header(ACCEPT_LANGUAGE, VALUE_LANGUAGE) |
| .header(PRIORITY, "u=1, i") |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| pub fn build_usage_client(user_id: &str, auth_token: &str) -> RequestBuilder { |
| let session_token = format!("{}%3A%3A{}", user_id, auth_token); |
|
|
| let client = if *USE_REVERSE_PROXY { |
| HTTP_CLIENT |
| .read() |
| .get(&*CURSOR_USAGE_API_URL) |
| .header(HOST, &*REVERSE_PROXY_HOST) |
| .header(PROXY_HOST, CURSOR_HOST) |
| } else { |
| HTTP_CLIENT |
| .read() |
| .get(&*CURSOR_USAGE_API_URL) |
| .header(HOST, CURSOR_HOST) |
| }; |
|
|
| client |
| .header(USER_AGENT, UA_WIN) |
| .header(ACCEPT, VALUE_ACCEPT) |
| .header(ACCEPT_LANGUAGE, VALUE_LANGUAGE) |
| .header(ACCEPT_ENCODING, ENCODINGS) |
| .header(REFERER, CURSOR_SETTINGS_URL) |
| .header(DNT, ONE) |
| .header(SEC_GPC, ONE) |
| .header(SEC_FETCH_DEST, EMPTY) |
| .header(SEC_FETCH_MODE, CORS) |
| .header(SEC_FETCH_SITE, SAME_ORIGIN) |
| .header(CONNECTION, KEEP_ALIVE) |
| .header(PRAGMA, NO_CACHE) |
| .header(CACHE_CONTROL, NO_CACHE) |
| .header(TE, TRAILERS) |
| .header(PRIORITY, U_EQ_4) |
| .header( |
| COOKIE, |
| &format!("WorkosCursorSessionToken={}", session_token), |
| ) |
| .query(&[("user", user_id)]) |
| } |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| pub fn build_userinfo_client(user_id: &str, auth_token: &str) -> RequestBuilder { |
| let session_token = format!("{}%3A%3A{}", user_id, auth_token); |
|
|
| let client = if *USE_REVERSE_PROXY { |
| HTTP_CLIENT |
| .read() |
| .get(&*CURSOR_USER_API_URL) |
| .header(HOST, &*REVERSE_PROXY_HOST) |
| .header(PROXY_HOST, CURSOR_HOST) |
| } else { |
| HTTP_CLIENT |
| .read() |
| .get(&*CURSOR_USER_API_URL) |
| .header(HOST, CURSOR_HOST) |
| }; |
|
|
| client |
| .header(USER_AGENT, UA_WIN) |
| .header(ACCEPT, VALUE_ACCEPT) |
| .header(ACCEPT_LANGUAGE, VALUE_LANGUAGE) |
| .header(ACCEPT_ENCODING, ENCODINGS) |
| .header(REFERER, CURSOR_SETTINGS_URL) |
| .header(DNT, ONE) |
| .header(SEC_GPC, ONE) |
| .header(SEC_FETCH_DEST, EMPTY) |
| .header(SEC_FETCH_MODE, CORS) |
| .header(SEC_FETCH_SITE, SAME_ORIGIN) |
| .header(CONNECTION, KEEP_ALIVE) |
| .header(PRAGMA, NO_CACHE) |
| .header(CACHE_CONTROL, NO_CACHE) |
| .header(TE, TRAILERS) |
| .header(PRIORITY, U_EQ_4) |
| .header( |
| COOKIE, |
| &format!("WorkosCursorSessionToken={}", session_token), |
| ) |
| .query(&[("user", user_id)]) |
| } |
|
|