Extract http from util (#11680)

This avoids the CLI linking libssl etc...

Release Notes:

- N/A
This commit is contained in:
Conrad Irwin 2024-05-10 15:50:20 -06:00 committed by GitHub
parent df41435d1a
commit 5515ba6043
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
77 changed files with 419 additions and 336 deletions

49
Cargo.lock generated
View File

@ -224,10 +224,10 @@ version = "0.1.0"
dependencies = [
"anyhow",
"futures 0.3.28",
"http 0.1.0",
"serde",
"serde_json",
"tokio",
"util",
]
[[package]]
@ -344,6 +344,7 @@ dependencies = [
"fs",
"futures 0.3.28",
"gpui",
"http 0.1.0",
"indoc",
"language",
"log",
@ -388,6 +389,7 @@ dependencies = [
"futures 0.3.28",
"fuzzy",
"gpui",
"http 0.1.0",
"language",
"languages",
"log",
@ -889,6 +891,7 @@ dependencies = [
"db",
"editor",
"gpui",
"http 0.1.0",
"isahc",
"log",
"markdown_preview",
@ -1756,6 +1759,7 @@ dependencies = [
"fs",
"futures 0.3.28",
"gpui",
"http 0.1.0",
"language",
"live_kit_client",
"log",
@ -1958,6 +1962,7 @@ dependencies = [
"collections",
"futures 0.3.28",
"gpui",
"http 0.1.0",
"language",
"log",
"rand 0.8.5",
@ -2188,6 +2193,7 @@ dependencies = [
"feature_flags",
"futures 0.3.28",
"gpui",
"http 0.1.0",
"lazy_static",
"log",
"once_cell",
@ -2318,6 +2324,7 @@ dependencies = [
"gpui",
"headless",
"hex",
"http 0.1.0",
"indoc",
"language",
"live_kit_client",
@ -2387,6 +2394,7 @@ dependencies = [
"futures 0.3.28",
"fuzzy",
"gpui",
"http 0.1.0",
"language",
"lazy_static",
"menu",
@ -2556,6 +2564,7 @@ dependencies = [
"fs",
"futures 0.3.28",
"gpui",
"http 0.1.0",
"indoc",
"language",
"lsp",
@ -3414,6 +3423,7 @@ dependencies = [
"fuzzy",
"git",
"gpui",
"http 0.1.0",
"indoc",
"itertools 0.11.0",
"language",
@ -3717,6 +3727,7 @@ dependencies = [
"fs",
"futures 0.3.28",
"gpui",
"http 0.1.0",
"isahc",
"language",
"log",
@ -3864,6 +3875,7 @@ dependencies = [
"editor",
"futures 0.3.28",
"gpui",
"http 0.1.0",
"human_bytes",
"isahc",
"language",
@ -4472,6 +4484,7 @@ dependencies = [
"derive_more",
"git2",
"gpui",
"http 0.1.0",
"lazy_static",
"log",
"parking_lot",
@ -4511,6 +4524,7 @@ dependencies = [
"futures 0.3.28",
"git",
"gpui",
"http 0.1.0",
"isahc",
"pretty_assertions",
"regex",
@ -4518,7 +4532,6 @@ dependencies = [
"serde_json",
"unindent",
"url",
"util",
]
[[package]]
@ -4596,9 +4609,9 @@ version = "0.1.0"
dependencies = [
"anyhow",
"futures 0.3.28",
"http 0.1.0",
"serde",
"serde_json",
"util",
]
[[package]]
@ -4666,6 +4679,7 @@ dependencies = [
"foreign-types 0.5.0",
"futures 0.3.28",
"gpui_macros",
"http 0.1.0",
"image",
"itertools 0.11.0",
"lazy_static",
@ -4984,6 +4998,20 @@ version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d13cdbd5dbb29f9c88095bbdc2590c9cba0d0a1269b983fef6b2cdd7e9f4db1"
[[package]]
name = "http"
version = "0.1.0"
dependencies = [
"anyhow",
"futures 0.3.28",
"futures-lite 1.13.0",
"isahc",
"log",
"serde",
"serde_json",
"url",
]
[[package]]
name = "http"
version = "0.2.9"
@ -5601,6 +5629,7 @@ dependencies = [
"git",
"globset",
"gpui",
"http 0.1.0",
"indoc",
"itertools 0.11.0",
"lazy_static",
@ -5691,6 +5720,7 @@ dependencies = [
"feature_flags",
"futures 0.3.28",
"gpui",
"http 0.1.0",
"language",
"lazy_static",
"log",
@ -6435,6 +6465,7 @@ dependencies = [
"async-trait",
"async_zip",
"futures 0.3.28",
"http 0.1.0",
"log",
"semver",
"serde",
@ -6829,11 +6860,11 @@ version = "0.1.0"
dependencies = [
"anyhow",
"futures 0.3.28",
"http 0.1.0",
"isahc",
"schemars",
"serde",
"serde_json",
"util",
]
[[package]]
@ -7570,6 +7601,7 @@ dependencies = [
"git2",
"globset",
"gpui",
"http 0.1.0",
"itertools 0.11.0",
"language",
"log",
@ -8841,6 +8873,7 @@ dependencies = [
"futures-batch",
"gpui",
"heed",
"http 0.1.0",
"language",
"languages",
"log",
@ -9756,6 +9789,7 @@ dependencies = [
"env_logger",
"futures 0.3.28",
"gpui",
"http 0.1.0",
"language",
"log",
"postage",
@ -9776,6 +9810,7 @@ version = "0.1.0"
dependencies = [
"anyhow",
"futures 0.3.28",
"http 0.1.0",
"serde",
"serde_json",
"smol",
@ -10157,6 +10192,7 @@ dependencies = [
"ctor",
"env_logger",
"gpui",
"http 0.1.0",
"lazy_static",
"log",
"parking_lot",
@ -11205,7 +11241,6 @@ dependencies = [
"futures-lite 1.13.0",
"git2",
"globset",
"isahc",
"lazy_static",
"log",
"rand 0.8.5",
@ -11217,7 +11252,6 @@ dependencies = [
"tempfile",
"tendril",
"unicase",
"url",
]
[[package]]
@ -12619,6 +12653,7 @@ dependencies = [
"fs",
"futures 0.3.28",
"gpui",
"http 0.1.0",
"itertools 0.11.0",
"language",
"lazy_static",
@ -12654,6 +12689,7 @@ dependencies = [
"git",
"git2",
"gpui",
"http 0.1.0",
"ignore",
"itertools 0.11.0",
"language",
@ -12903,6 +12939,7 @@ dependencies = [
"go_to_line",
"gpui",
"headless",
"http 0.1.0",
"image_viewer",
"inline_completion_button",
"install_cli",

View File

@ -41,6 +41,7 @@ members = [
"crates/gpui",
"crates/gpui_macros",
"crates/headless",
"crates/http",
"crates/image_viewer",
"crates/inline_completion_button",
"crates/install_cli",
@ -183,6 +184,7 @@ google_ai = { path = "crates/google_ai" }
gpui = { path = "crates/gpui" }
gpui_macros = { path = "crates/gpui_macros" }
headless = { path = "crates/headless" }
http = { path = "crates/http" }
install_cli = { path = "crates/install_cli" }
image_viewer = { path = "crates/image_viewer" }
inline_completion_button = { path = "crates/inline_completion_button" }

View File

@ -14,9 +14,9 @@ path = "src/anthropic.rs"
[dependencies]
anyhow.workspace = true
futures.workspace = true
http.workspace = true
serde.workspace = true
serde_json.workspace = true
util.workspace = true
[dev-dependencies]
tokio.workspace = true

View File

@ -1,8 +1,8 @@
use anyhow::{anyhow, Result};
use futures::{io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, StreamExt};
use http::{AsyncBody, HttpClient, Method, Request as HttpRequest};
use serde::{Deserialize, Serialize};
use std::{convert::TryFrom, sync::Arc};
use util::http::{AsyncBody, HttpClient, Method, Request as HttpRequest};
#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
pub enum Model {
@ -196,7 +196,7 @@ pub async fn stream_completion(
// #[cfg(test)]
// mod tests {
// use super::*;
// use util::http::IsahcHttpClient;
// use http::IsahcHttpClient;
// #[tokio::test]
// async fn stream_completion_success() {

View File

@ -20,6 +20,7 @@ file_icons.workspace = true
fs.workspace = true
futures.workspace = true
gpui.workspace = true
http.workspace = true
indoc.workspace = true
language.workspace = true
log.workspace = true

View File

@ -5,13 +5,14 @@ use anyhow::{anyhow, Result};
use editor::{Editor, EditorElement, EditorStyle};
use futures::{future::BoxFuture, stream::BoxStream, FutureExt, StreamExt};
use gpui::{AnyView, AppContext, FontStyle, FontWeight, Task, TextStyle, View, WhiteSpace};
use http::HttpClient;
use open_ai::{stream_completion, Request, RequestMessage, Role as OpenAiRole};
use settings::Settings;
use std::time::Duration;
use std::{env, sync::Arc};
use theme::ThemeSettings;
use ui::prelude::*;
use util::{http::HttpClient, ResultExt};
use util::ResultExt;
pub struct OpenAiCompletionProvider {
api_key: Option<String>,

View File

@ -62,4 +62,5 @@ release_channel.workspace = true
settings = { workspace = true, features = ["test-support"] }
theme = { workspace = true, features = ["test-support"] }
util = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }
workspace = { workspace = true, features = ["test-support"] }

View File

@ -18,6 +18,7 @@ client.workspace = true
db.workspace = true
editor.workspace = true
gpui.workspace = true
http.workspace = true
isahc.workspace = true
log.workspace = true
markdown_preview.workspace = true

View File

@ -20,6 +20,7 @@ use smol::{fs, io::AsyncReadExt};
use settings::{Settings, SettingsSources, SettingsStore};
use smol::{fs::File, process::Command};
use http::{HttpClient, HttpClientWithUrl};
use release_channel::{AppCommitSha, AppVersion, ReleaseChannel};
use std::{
env::consts::{ARCH, OS},
@ -29,10 +30,7 @@ use std::{
time::Duration,
};
use update_notification::UpdateNotification;
use util::{
http::{HttpClient, HttpClientWithUrl},
ResultExt,
};
use util::ResultExt;
use workspace::notifications::NotificationId;
use workspace::Workspace;

View File

@ -50,3 +50,4 @@ language = { workspace = true, features = ["test-support"] }
live_kit_client = { workspace = true, features = ["test-support"] }
project = { workspace = true, features = ["test-support"] }
util = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }

View File

@ -40,3 +40,4 @@ rpc = { workspace = true, features = ["test-support"] }
client = { workspace = true, features = ["test-support"] }
settings = { workspace = true, features = ["test-support"] }
util = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }

View File

@ -4,9 +4,9 @@ use super::*;
use client::{test::FakeServer, Client, UserStore};
use clock::FakeSystemClock;
use gpui::{AppContext, Context, Model, TestAppContext};
use http::FakeHttpClient;
use rpc::proto::{self};
use settings::SettingsStore;
use util::http::FakeHttpClient;
#[gpui::test]
fn test_update_channels(cx: &mut AppContext) {

View File

@ -25,6 +25,7 @@ collections.workspace = true
feature_flags.workspace = true
futures.workspace = true
gpui.workspace = true
http.workspace = true
lazy_static.workspace = true
log.workspace = true
once_cell.workspace = true
@ -56,3 +57,4 @@ gpui = { workspace = true, features = ["test-support"] }
rpc = { workspace = true, features = ["test-support"] }
settings = { workspace = true, features = ["test-support"] }
util = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }

View File

@ -20,6 +20,7 @@ use gpui::{
actions, AnyModel, AnyWeakModel, AppContext, AsyncAppContext, BorrowAppContext, Global, Model,
Task, WeakModel,
};
use http::{HttpClient, HttpClientWithUrl};
use lazy_static::lazy_static;
use parking_lot::RwLock;
use postage::watch;
@ -47,7 +48,6 @@ use std::{
use telemetry::Telemetry;
use thiserror::Error;
use url::Url;
use util::http::{HttpClient, HttpClientWithUrl};
use util::{ResultExt, TryFutureExt};
pub use rpc::*;
@ -204,7 +204,7 @@ pub enum EstablishConnectionError {
#[error("{0}")]
Other(#[from] anyhow::Error),
#[error("{0}")]
Http(#[from] util::http::Error),
Http(#[from] http::Error),
#[error("{0}")]
Io(#[from] std::io::Error),
#[error("{0}")]
@ -1679,10 +1679,10 @@ mod tests {
use clock::FakeSystemClock;
use gpui::{BackgroundExecutor, Context, TestAppContext};
use http::FakeHttpClient;
use parking_lot::Mutex;
use settings::SettingsStore;
use std::future;
use util::http::FakeHttpClient;
#[gpui::test(iterations = 10)]
async fn test_reconnection(cx: &mut TestAppContext) {

View File

@ -0,0 +1 @@

View File

@ -5,6 +5,7 @@ use chrono::{DateTime, Utc};
use clock::SystemClock;
use futures::Future;
use gpui::{AppContext, AppMetadata, BackgroundExecutor, Task};
use http::{self, HttpClient, HttpClientWithUrl, Method};
use once_cell::sync::Lazy;
use parking_lot::Mutex;
use release_channel::ReleaseChannel;
@ -19,7 +20,6 @@ use telemetry_events::{
SettingEvent,
};
use tempfile::NamedTempFile;
use util::http::{self, HttpClient, HttpClientWithUrl, Method};
#[cfg(not(debug_assertions))]
use util::ResultExt;
use util::TryFutureExt;
@ -497,7 +497,7 @@ mod tests {
use chrono::TimeZone;
use clock::FakeSystemClock;
use gpui::TestAppContext;
use util::http::FakeHttpClient;
use http::FakeHttpClient;
#[gpui::test]
fn test_telemetry_flush_on_max_queue_size(cx: &mut TestAppContext) {

View File

@ -35,6 +35,7 @@ envy = "0.4.2"
futures.workspace = true
google_ai.workspace = true
hex.workspace = true
http.workspace = true
live_kit_server.workspace = true
log.workspace = true
nanoid.workspace = true

View File

@ -42,6 +42,7 @@ use futures::{
stream::FuturesUnordered,
FutureExt, SinkExt, StreamExt, TryStreamExt,
};
use http::IsahcHttpClient;
use prometheus::{register_int_gauge, IntGauge};
use rpc::{
proto::{
@ -73,7 +74,6 @@ use tracing::{
field::{self},
info_span, instrument, Instrument,
};
use util::http::IsahcHttpClient;
use self::connection_pool::VersionedMessage;

View File

@ -19,6 +19,7 @@ use fs::FakeFs;
use futures::{channel::oneshot, StreamExt as _};
use git::GitHostingProviderRegistry;
use gpui::{BackgroundExecutor, Context, Model, Task, TestAppContext, View, VisualTestContext};
use http::FakeHttpClient;
use language::LanguageRegistry;
use node_runtime::FakeNodeRuntime;
use notifications::NotificationStore;
@ -41,7 +42,6 @@ use std::{
Arc,
},
};
use util::http::FakeHttpClient;
use workspace::{Workspace, WorkspaceId, WorkspaceStore};
pub struct TestServer {

View File

@ -25,6 +25,7 @@ test-support = [
"settings/test-support",
"util/test-support",
"workspace/test-support",
"http/test-support",
]
[dependencies]
@ -84,4 +85,5 @@ rpc = { workspace = true, features = ["test-support"] }
settings = { workspace = true, features = ["test-support"] }
tree-sitter-markdown.workspace = true
util = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }
workspace = { workspace = true, features = ["test-support"] }

View File

@ -557,11 +557,12 @@ mod tests {
use client::{Client, User, UserStore};
use clock::FakeSystemClock;
use gpui::TestAppContext;
use http::FakeHttpClient;
use language::{Language, LanguageConfig};
use project::Project;
use rpc::proto;
use settings::SettingsStore;
use util::{http::FakeHttpClient, test::marked_text_ranges};
use util::test::marked_text_ranges;
#[gpui::test]
async fn test_message_editor(cx: &mut TestAppContext) {

View File

@ -32,6 +32,7 @@ command_palette_hooks.workspace = true
editor.workspace = true
futures.workspace = true
gpui.workspace = true
http.workspace = true
language.workspace = true
lsp.workspace = true
menu.workspace = true
@ -63,3 +64,4 @@ rpc = { workspace = true, features = ["test-support"] }
settings = { workspace = true, features = ["test-support"] }
theme = { workspace = true, features = ["test-support"] }
util = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }

View File

@ -12,6 +12,8 @@ use gpui::{
actions, AppContext, AsyncAppContext, Context, Entity, EntityId, EventEmitter, Global, Model,
ModelContext, Task, WeakModel,
};
use http::github::latest_github_release;
use http::HttpClient;
use language::{
language_settings::{all_language_settings, language_settings, InlineCompletionProvider},
point_from_lsp, point_to_lsp, Anchor, Bias, Buffer, BufferSnapshot, Language, PointUtf16,
@ -31,9 +33,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
use util::{
fs::remove_matching, github::latest_github_release, http::HttpClient, maybe, paths, ResultExt,
};
use util::{fs::remove_matching, maybe, paths, ResultExt};
pub use copilot_completion_provider::CopilotCompletionProvider;
pub use sign_in::CopilotCodeVerification;
@ -393,7 +393,7 @@ impl Copilot {
Default::default(),
cx.to_async(),
);
let http = util::http::FakeHttpClient::create(|_| async { unreachable!() });
let http = http::FakeHttpClient::create(|_| async { unreachable!() });
let node_runtime = FakeNodeRuntime::new();
let this = cx.new_model(|cx| Self {
server_id: LanguageServerId(0),

View File

@ -39,6 +39,7 @@ futures.workspace = true
fuzzy.workspace = true
git.workspace = true
gpui.workspace = true
http.workspace = true
indoc.workspace = true
itertools.workspace = true
language.workspace = true
@ -91,3 +92,4 @@ tree-sitter-typescript.workspace = true
unindent.workspace = true
util = { workspace = true, features = ["test-support"] }
workspace = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }

View File

@ -7,13 +7,13 @@ use git::{
parse_git_remote_url, GitHostingProvider, GitHostingProviderRegistry, Oid, PullRequest,
};
use gpui::{Model, ModelContext, Subscription, Task};
use http::HttpClient;
use language::{markdown, Bias, Buffer, BufferSnapshot, Edit, LanguageRegistry, ParsedMarkdown};
use multi_buffer::MultiBufferRow;
use project::{Item, Project};
use smallvec::SmallVec;
use sum_tree::SumTree;
use url::Url;
use util::http::HttpClient;
#[derive(Clone, Debug, Default)]
pub struct GitBlameEntry {

View File

@ -23,6 +23,7 @@ collections.workspace = true
fs.workspace = true
futures.workspace = true
gpui.workspace = true
http.workspace = true
isahc.workspace = true
language.workspace = true
log.workspace = true

View File

@ -6,6 +6,7 @@ use async_compression::futures::bufread::GzipDecoder;
use async_tar::Archive;
use futures::io::BufReader;
use futures::AsyncReadExt;
use http::{self, AsyncBody, HttpClient};
use serde::Deserialize;
use std::{
env, fs, mem,
@ -13,7 +14,6 @@ use std::{
process::{Command, Stdio},
sync::Arc,
};
use util::http::{self, AsyncBody, HttpClient};
use wasm_encoder::{ComponentSectionId, Encode as _, RawSection, Section as _};
use wasmparser::Parser;
use wit_component::ComponentEncoder;

View File

@ -28,6 +28,7 @@ use gpui::{
actions, AppContext, AsyncAppContext, Context, EventEmitter, Global, Model, ModelContext, Task,
WeakModel,
};
use http::{AsyncBody, HttpClient, HttpClientWithUrl};
use language::{
ContextProviderWithTasks, LanguageConfig, LanguageMatcher, LanguageQueries, LanguageRegistry,
QUERY_FILENAME_PREFIXES,
@ -46,12 +47,7 @@ use std::{
};
use theme::{ThemeRegistry, ThemeSettings};
use url::Url;
use util::{
http::{AsyncBody, HttpClient, HttpClientWithUrl},
maybe,
paths::EXTENSIONS_DIR,
ResultExt,
};
use util::{maybe, paths::EXTENSIONS_DIR, ResultExt};
use wasm_host::{
wit::{is_supported_wasm_api_version, wasm_api_version_range},
WasmExtension, WasmHost,

View File

@ -10,6 +10,7 @@ use collections::BTreeMap;
use fs::{FakeFs, Fs, RealFs};
use futures::{io::BufReader, AsyncReadExt, StreamExt};
use gpui::{Context, TestAppContext};
use http::{FakeHttpClient, Response};
use language::{LanguageMatcher, LanguageRegistry, LanguageServerBinaryStatus, LanguageServerName};
use node_runtime::FakeNodeRuntime;
use parking_lot::Mutex;
@ -22,10 +23,7 @@ use std::{
sync::Arc,
};
use theme::ThemeRegistry;
use util::{
http::{FakeHttpClient, Response},
test::temp_tree,
};
use util::test::temp_tree;
#[cfg(test)]
#[ctor::ctor]

View File

@ -13,6 +13,7 @@ use futures::{
Future, FutureExt, StreamExt as _,
};
use gpui::{AppContext, AsyncAppContext, BackgroundExecutor, Task};
use http::HttpClient;
use language::LanguageRegistry;
use node_runtime::NodeRuntime;
use semantic_version::SemanticVersion;
@ -20,7 +21,6 @@ use std::{
path::{Path, PathBuf},
sync::{Arc, OnceLock},
};
use util::http::HttpClient;
use wasmtime::{
component::{Component, ResourceTable},
Engine, Store,

View File

@ -155,7 +155,7 @@ impl github::Host for WasmState {
options: github::GithubReleaseOptions,
) -> wasmtime::Result<Result<github::GithubRelease, String>> {
maybe!(async {
let release = util::github::latest_github_release(
let release = http::github::latest_github_release(
&repo,
options.require_assets,
options.pre_release,

View File

@ -24,6 +24,7 @@ futures.workspace = true
gpui.workspace = true
human_bytes = "0.4.1"
isahc.workspace = true
http.workspace = true
language.workspace = true
log.workspace = true
menu.workspace = true

View File

@ -10,13 +10,14 @@ use gpui::{
div, rems, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Model,
PromptLevel, Render, Task, View, ViewContext,
};
use http::HttpClient;
use isahc::Request;
use language::Buffer;
use project::Project;
use regex::Regex;
use serde_derive::Serialize;
use ui::{prelude::*, Button, ButtonStyle, IconPosition, Tooltip};
use util::{http::HttpClient, ResultExt};
use util::ResultExt;
use workspace::notifications::NotificationId;
use workspace::{DismissDecision, ModalView, Toast, Workspace};

View File

@ -19,6 +19,7 @@ collections.workspace = true
derive_more.workspace = true
git2.workspace = true
gpui.workspace = true
http.workspace = true
lazy_static.workspace = true
log.workspace = true
parking_lot.workspace = true

View File

@ -5,9 +5,9 @@ use async_trait::async_trait;
use collections::BTreeMap;
use derive_more::{Deref, DerefMut};
use gpui::{AppContext, Global};
use http::HttpClient;
use parking_lot::RwLock;
use url::Url;
use util::http::HttpClient;
use crate::Oid;

View File

@ -17,12 +17,12 @@ async-trait.workspace = true
futures.workspace = true
git.workspace = true
gpui.workspace = true
http.workspace = true
isahc.workspace = true
regex.workspace = true
serde.workspace = true
serde_json.workspace = true
url.workspace = true
util.workspace = true
[dev-dependencies]
unindent.workspace = true

View File

@ -3,11 +3,11 @@ use std::sync::Arc;
use anyhow::{bail, Context, Result};
use async_trait::async_trait;
use futures::AsyncReadExt;
use http::HttpClient;
use isahc::config::Configurable;
use isahc::{AsyncBody, Request};
use serde::Deserialize;
use url::Url;
use util::http::HttpClient;
use git::{
BuildCommitPermalinkParams, BuildPermalinkParams, GitHostingProvider, Oid, ParsedGitRemote,

View File

@ -3,12 +3,12 @@ use std::sync::{Arc, OnceLock};
use anyhow::{bail, Context, Result};
use async_trait::async_trait;
use futures::AsyncReadExt;
use http::HttpClient;
use isahc::config::Configurable;
use isahc::{AsyncBody, Request};
use regex::Regex;
use serde::Deserialize;
use url::Url;
use util::http::HttpClient;
use git::{
BuildCommitPermalinkParams, BuildPermalinkParams, GitHostingProvider, Oid, ParsedGitRemote,

View File

@ -11,6 +11,6 @@ path = "src/google_ai.rs"
[dependencies]
anyhow.workspace = true
futures.workspace = true
http.workspace = true
serde.workspace = true
serde_json.workspace = true
util.workspace = true

View File

@ -2,8 +2,8 @@ use std::sync::Arc;
use anyhow::{anyhow, Result};
use futures::{io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, StreamExt};
use http::HttpClient;
use serde::{Deserialize, Serialize};
use util::http::HttpClient;
pub const API_URL: &str = "https://generativelanguage.googleapis.com";

View File

@ -12,7 +12,7 @@ workspace = true
[features]
default = []
test-support = ["backtrace", "collections/test-support", "util/test-support"]
test-support = ["backtrace", "collections/test-support", "util/test-support", "http/test-support"]
runtime_shaders = []
macos-blade = ["blade-graphics", "blade-macros", "bytemuck"]
@ -35,6 +35,7 @@ etagere = "0.2"
futures.workspace = true
font-kit = { git = "https://github.com/zed-industries/font-kit", rev = "5a5c4d4" }
gpui_macros.workspace = true
http.workspace = true
image = "0.23"
itertools.workspace = true
lazy_static.workspace = true
@ -72,6 +73,7 @@ waker-fn = "1.1.0"
backtrace = "0.3"
collections = { workspace = true, features = ["test-support"] }
util = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }
[target.'cfg(target_os = "macos")'.build-dependencies]
bindgen = "0.65.1"

View File

@ -19,13 +19,11 @@ use time::UtcOffset;
pub use async_context::*;
use collections::{FxHashMap, FxHashSet, VecDeque};
pub use entity_map::*;
use http::{self, HttpClient};
pub use model_context::*;
#[cfg(any(test, feature = "test-support"))]
pub use test_context::*;
use util::{
http::{self, HttpClient},
ResultExt,
};
use util::ResultExt;
use crate::{
current_platform, init_app_menus, Action, ActionRegistry, Any, AnyView, AnyWindowHandle,

View File

@ -104,7 +104,7 @@ impl TestAppContext {
let foreground_executor = ForegroundExecutor::new(arc_dispatcher);
let platform = TestPlatform::new(background_executor.clone(), foreground_executor.clone());
let asset_source = Arc::new(());
let http_client = util::http::FakeHttpClient::with_404_response();
let http_client = http::FakeHttpClient::with_404_response();
let text_system = Arc::new(TextSystem::new(platform.text_system()));
Self {

View File

@ -13,8 +13,9 @@ use image::{ImageBuffer, ImageError};
#[cfg(target_os = "macos")]
use media::core_video::CVImageBuffer;
use http;
use thiserror::Error;
use util::{http, ResultExt};
use util::ResultExt;
/// A source of image content.
#[derive(Clone, Debug)]

26
crates/http/Cargo.toml Normal file
View File

@ -0,0 +1,26 @@
[package]
name = "http"
version = "0.1.0"
edition = "2021"
publish = false
license = "Apache-2.0"
[lints]
workspace = true
[features]
test-support = []
[lib]
path = "src/http.rs"
doctest = true
[dependencies]
anyhow.workspace = true
futures.workspace = true
isahc.workspace = true
log.workspace = true
serde.workspace = true
serde_json.workspace = true
futures-lite.workspace = true
url.workspace = true

View File

@ -1,4 +1,4 @@
use crate::http::HttpClient;
use crate::HttpClient;
use anyhow::{anyhow, bail, Context, Result};
use futures::AsyncReadExt;
use serde::Deserialize;

242
crates/http/src/http.rs Normal file
View File

@ -0,0 +1,242 @@
pub mod github;
pub use anyhow::{anyhow, Result};
use futures::future::BoxFuture;
use futures_lite::FutureExt;
use isahc::config::{Configurable, RedirectPolicy};
pub use isahc::{
http::{Method, StatusCode, Uri},
AsyncBody, Error, HttpClient as IsahcHttpClient, Request, Response,
};
#[cfg(feature = "test-support")]
use std::fmt;
use std::{
sync::{Arc, Mutex},
time::Duration,
};
pub use url::Url;
fn http_proxy_from_env() -> Option<isahc::http::Uri> {
macro_rules! try_env {
($($env:literal),+) => {
$(
if let Ok(env) = std::env::var($env) {
return env.parse::<isahc::http::Uri>().ok();
}
)+
};
}
try_env!(
"ALL_PROXY",
"all_proxy",
"HTTPS_PROXY",
"https_proxy",
"HTTP_PROXY",
"http_proxy"
);
None
}
/// An [`HttpClient`] that has a base URL.
pub struct HttpClientWithUrl {
base_url: Mutex<String>,
client: Arc<dyn HttpClient>,
}
impl HttpClientWithUrl {
/// Returns a new [`HttpClientWithUrl`] with the given base URL.
pub fn new(base_url: impl Into<String>) -> Self {
Self {
base_url: Mutex::new(base_url.into()),
client: client(),
}
}
/// Returns the base URL.
pub fn base_url(&self) -> String {
self.base_url
.lock()
.map_or_else(|_| Default::default(), |url| url.clone())
}
/// Sets the base URL.
pub fn set_base_url(&self, base_url: impl Into<String>) {
let base_url = base_url.into();
self.base_url
.lock()
.map(|mut url| {
*url = base_url;
})
.ok();
}
/// Builds a URL using the given path.
pub fn build_url(&self, path: &str) -> String {
format!("{}{}", self.base_url(), path)
}
/// Builds a Zed API URL using the given path.
pub fn build_zed_api_url(&self, path: &str, query: &[(&str, &str)]) -> Result<Url> {
let base_url = self.base_url();
let base_api_url = match base_url.as_ref() {
"https://zed.dev" => "https://api.zed.dev",
"https://staging.zed.dev" => "https://api-staging.zed.dev",
"http://localhost:3000" => "http://localhost:8080",
other => other,
};
Ok(Url::parse_with_params(
&format!("{}{}", base_api_url, path),
query,
)?)
}
}
impl HttpClient for Arc<HttpClientWithUrl> {
fn send(
&self,
req: Request<AsyncBody>,
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
self.client.send(req)
}
}
impl HttpClient for HttpClientWithUrl {
fn send(
&self,
req: Request<AsyncBody>,
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
self.client.send(req)
}
}
pub trait HttpClient: Send + Sync {
fn send(
&self,
req: Request<AsyncBody>,
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>>;
fn get<'a>(
&'a self,
uri: &str,
body: AsyncBody,
follow_redirects: bool,
) -> BoxFuture<'a, Result<Response<AsyncBody>, Error>> {
let request = isahc::Request::builder()
.redirect_policy(if follow_redirects {
RedirectPolicy::Follow
} else {
RedirectPolicy::None
})
.method(Method::GET)
.uri(uri)
.body(body);
match request {
Ok(request) => self.send(request),
Err(error) => async move { Err(error.into()) }.boxed(),
}
}
fn post_json<'a>(
&'a self,
uri: &str,
body: AsyncBody,
) -> BoxFuture<'a, Result<Response<AsyncBody>, Error>> {
let request = isahc::Request::builder()
.method(Method::POST)
.uri(uri)
.header("Content-Type", "application/json")
.body(body);
match request {
Ok(request) => self.send(request),
Err(error) => async move { Err(error.into()) }.boxed(),
}
}
}
pub fn client() -> Arc<dyn HttpClient> {
Arc::new(
isahc::HttpClient::builder()
.connect_timeout(Duration::from_secs(5))
.low_speed_timeout(100, Duration::from_secs(5))
.proxy(http_proxy_from_env())
.build()
.unwrap(),
)
}
impl HttpClient for isahc::HttpClient {
fn send(
&self,
req: Request<AsyncBody>,
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
let client = self.clone();
Box::pin(async move { client.send_async(req).await })
}
}
#[cfg(feature = "test-support")]
type FakeHttpHandler = Box<
dyn Fn(Request<AsyncBody>) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>>
+ Send
+ Sync
+ 'static,
>;
#[cfg(feature = "test-support")]
pub struct FakeHttpClient {
handler: FakeHttpHandler,
}
#[cfg(feature = "test-support")]
impl FakeHttpClient {
pub fn create<Fut, F>(handler: F) -> Arc<HttpClientWithUrl>
where
Fut: futures::Future<Output = Result<Response<AsyncBody>, Error>> + Send + 'static,
F: Fn(Request<AsyncBody>) -> Fut + Send + Sync + 'static,
{
Arc::new(HttpClientWithUrl {
base_url: Mutex::new("http://test.example".into()),
client: Arc::new(Self {
handler: Box::new(move |req| Box::pin(handler(req))),
}),
})
}
pub fn with_404_response() -> Arc<HttpClientWithUrl> {
Self::create(|_| async move {
Ok(Response::builder()
.status(404)
.body(Default::default())
.unwrap())
})
}
pub fn with_200_response() -> Arc<HttpClientWithUrl> {
Self::create(|_| async move {
Ok(Response::builder()
.status(200)
.body(Default::default())
.unwrap())
})
}
}
#[cfg(feature = "test-support")]
impl fmt::Debug for FakeHttpClient {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FakeHttpClient").finish()
}
}
#[cfg(feature = "test-support")]
impl HttpClient for FakeHttpClient {
fn send(
&self,
req: Request<AsyncBody>,
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
let future = (self.handler)(req);
Box::pin(async move { future.await.map(Into::into) })
}
}

View File

@ -34,6 +34,7 @@ fuzzy.workspace = true
git.workspace = true
globset.workspace = true
gpui.workspace = true
http.workspace = true
itertools.workspace = true
lazy_static.workspace = true
log.workspace = true
@ -82,3 +83,4 @@ tree-sitter-rust.workspace = true
tree-sitter-typescript.workspace = true
unindent.workspace = true
util = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }

View File

@ -27,6 +27,7 @@ use collections::{HashMap, HashSet};
use futures::Future;
use gpui::{AppContext, AsyncAppContext, Model, Task};
pub use highlight_map::HighlightMap;
use http::HttpClient;
use lazy_static::lazy_static;
use lsp::{CodeActionKind, LanguageServerBinary};
use parking_lot::Mutex;
@ -62,7 +63,6 @@ pub use task_context::{
};
use theme::SyntaxTheme;
use tree_sitter::{self, wasmtime, Query, QueryCursor, WasmStore};
use util::http::HttpClient;
pub use buffer::Operation;
pub use buffer::*;

View File

@ -17,6 +17,7 @@ collections.workspace = true
feature_flags.workspace = true
futures.workspace = true
gpui.workspace = true
http.workspace = true
language.workspace = true
lazy_static.workspace = true
log.workspace = true

View File

@ -2,17 +2,14 @@ use anyhow::{anyhow, bail, Context, Result};
use async_trait::async_trait;
use futures::StreamExt;
use gpui::AsyncAppContext;
use http::github::{latest_github_release, GitHubLspBinaryVersion};
pub use language::*;
use lsp::LanguageServerBinary;
use project::project_settings::{BinarySettings, ProjectSettings};
use settings::Settings;
use smol::fs::{self, File};
use std::{any::Any, env::consts, path::PathBuf, sync::Arc};
use util::{
fs::remove_matching,
github::{latest_github_release, GitHubLspBinaryVersion},
maybe, ResultExt,
};
use util::{fs::remove_matching, maybe, ResultExt};
pub struct CLspAdapter;

View File

@ -2,6 +2,7 @@ use anyhow::{anyhow, Context, Result};
use async_trait::async_trait;
use futures::StreamExt;
use gpui::{AsyncAppContext, Task};
use http::github::latest_github_release;
pub use language::*;
use lazy_static::lazy_static;
use lsp::LanguageServerBinary;
@ -21,7 +22,7 @@ use std::{
Arc,
},
};
use util::{fs::remove_matching, github::latest_github_release, maybe, ResultExt};
use util::{fs::remove_matching, maybe, ResultExt};
fn server_binary_arguments() -> Vec<OsString> {
vec!["-mode=stdio".into()]

View File

@ -3,6 +3,7 @@ use async_compression::futures::bufread::GzipDecoder;
use async_trait::async_trait;
use futures::{io::BufReader, StreamExt};
use gpui::AsyncAppContext;
use http::github::{latest_github_release, GitHubLspBinaryVersion};
pub use language::*;
use lazy_static::lazy_static;
use lsp::LanguageServerBinary;
@ -18,11 +19,7 @@ use std::{
sync::Arc,
};
use task::{TaskTemplate, TaskTemplates, TaskVariables, VariableName};
use util::{
fs::remove_matching,
github::{latest_github_release, GitHubLspBinaryVersion},
maybe, ResultExt,
};
use util::{fs::remove_matching, maybe, ResultExt};
pub struct RustLspAdapter;

View File

@ -4,6 +4,7 @@ use async_tar::Archive;
use async_trait::async_trait;
use collections::HashMap;
use gpui::AsyncAppContext;
use http::github::{build_tarball_url, GitHubLspBinaryVersion};
use language::{LanguageServerName, LspAdapter, LspAdapterDelegate};
use lsp::{CodeActionKind, LanguageServerBinary};
use node_runtime::NodeRuntime;
@ -17,11 +18,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
use util::{
fs::remove_matching,
github::{build_tarball_url, GitHubLspBinaryVersion},
maybe, ResultExt,
};
use util::{fs::remove_matching, maybe, ResultExt};
fn typescript_server_binary_arguments(server_path: &Path) -> Vec<OsString> {
vec![server_path.into(), "--stdio".into()]

View File

@ -22,6 +22,7 @@ async-tar.workspace = true
async-trait.workspace = true
async_zip.workspace = true
futures.workspace = true
http.workspace = true
log.workspace = true
semver.workspace = true
serde.workspace = true

View File

@ -4,6 +4,7 @@ use anyhow::{anyhow, bail, Context, Result};
use async_compression::futures::bufread::GzipDecoder;
use async_tar::Archive;
use futures::AsyncReadExt;
use http::HttpClient;
use semver::Version;
use serde::Deserialize;
use smol::io::BufReader;
@ -15,7 +16,6 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
use util::http::HttpClient;
use util::ResultExt;
#[cfg(windows)]

View File

@ -15,8 +15,8 @@ schemars = ["dep:schemars"]
[dependencies]
anyhow.workspace = true
futures.workspace = true
http.workspace = true
isahc.workspace = true
schemars = { workspace = true, optional = true }
serde.workspace = true
serde_json.workspace = true
util.workspace = true

View File

@ -1,11 +1,11 @@
use anyhow::{anyhow, Context, Result};
use futures::{io::BufReader, stream::BoxStream, AsyncBufReadExt, AsyncReadExt, StreamExt};
use http::{AsyncBody, HttpClient, Method, Request as HttpRequest};
use isahc::config::Configurable;
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use std::time::Duration;
use std::{convert::TryFrom, future::Future};
use util::http::{AsyncBody, HttpClient, Method, Request as HttpRequest};
pub const OPEN_AI_API_URL: &str = "https://api.openai.com/v1";

View File

@ -36,6 +36,7 @@ fuzzy.workspace = true
git.workspace = true
globset.workspace = true
gpui.workspace = true
http.workspace = true
itertools.workspace = true
language.workspace = true
log.workspace = true

View File

@ -69,6 +69,7 @@ use rand::prelude::*;
use search_history::SearchHistory;
use worktree::LocalSnapshot;
use http::{HttpClient, Url};
use rpc::{ErrorCode, ErrorExt as _};
use search::SearchQuery;
use serde::Serialize;
@ -99,9 +100,7 @@ use task::static_source::{StaticSource, TrackedFile};
use terminals::Terminals;
use text::{Anchor, BufferId, LineEnding};
use util::{
debug_panic, defer,
http::{HttpClient, Url},
maybe, merge_json_value_into, parse_env_output,
debug_panic, defer, maybe, merge_json_value_into, parse_env_output,
paths::{
LOCAL_SETTINGS_RELATIVE_PATH, LOCAL_TASKS_RELATIVE_PATH, LOCAL_VSCODE_TASKS_RELATIVE_PATH,
},
@ -1003,7 +1002,7 @@ impl Project {
let fs = Arc::new(RealFs::default());
let languages = LanguageRegistry::test(cx.background_executor().clone());
let clock = Arc::new(FakeSystemClock::default());
let http_client = util::http::FakeHttpClient::with_404_response();
let http_client = http::FakeHttpClient::with_404_response();
let client = cx
.update(|cx| client::Client::new(clock, http_client.clone(), cx))
.unwrap();
@ -1047,7 +1046,7 @@ impl Project {
let languages = LanguageRegistry::test(cx.executor());
let clock = Arc::new(FakeSystemClock::default());
let http_client = util::http::FakeHttpClient::with_404_response();
let http_client = http::FakeHttpClient::with_404_response();
let client = cx.update(|cx| client::Client::new(clock, http_client.clone(), cx));
let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
let project = cx.update(|cx| {

View File

@ -29,6 +29,7 @@ gpui.workspace = true
language.workspace = true
log.workspace = true
heed.workspace = true
http.workspace = true
open_ai.workspace = true
parking_lot.workspace = true
project.workspace = true
@ -58,3 +59,4 @@ tempfile.workspace = true
util = { workspace = true, features = ["test-support"] }
worktree = { workspace = true, features = ["test-support"] }
workspace = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }

View File

@ -1,6 +1,7 @@
use client::Client;
use futures::channel::oneshot;
use gpui::App;
use http::HttpClientWithUrl;
use language::language_settings::AllLanguageSettings;
use project::Project;
use semantic_index::{OpenAiEmbeddingModel, OpenAiEmbeddingProvider, SemanticIndex};
@ -9,7 +10,6 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
use util::http::HttpClientWithUrl;
fn main() {
env_logger::init();

View File

@ -1,8 +1,8 @@
use anyhow::{Context as _, Result};
use futures::{future::BoxFuture, AsyncReadExt, FutureExt};
use http::HttpClient;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use util::http::HttpClient;
use crate::{Embedding, EmbeddingProvider, TextToEmbed};

View File

@ -1,9 +1,9 @@
use crate::{Embedding, EmbeddingProvider, TextToEmbed};
use anyhow::Result;
use futures::{future::BoxFuture, FutureExt};
use http::HttpClient;
pub use open_ai::OpenAiEmbeddingModel;
use std::sync::Arc;
use util::http::HttpClient;
pub struct OpenAiEmbeddingProvider {
client: Arc<dyn HttpClient>,

View File

@ -39,3 +39,4 @@ project = { workspace = true, features = ["test-support"] }
settings = { workspace = true, features = ["test-support"] }
theme = { workspace = true, features = ["test-support"] }
util = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }

View File

@ -15,6 +15,7 @@ doctest = false
[dependencies]
anyhow.workspace = true
futures.workspace = true
http.workspace = true
serde.workspace = true
serde_json.workspace = true
smol.workspace = true

View File

@ -1,12 +1,12 @@
use anyhow::{anyhow, Context, Result};
use futures::io::BufReader;
use futures::{AsyncReadExt, Future};
use http::{AsyncBody, HttpClient, Request as HttpRequest};
use serde::{Deserialize, Serialize};
use smol::fs::{self, File};
use smol::stream::StreamExt;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use util::http::{AsyncBody, HttpClient, Request as HttpRequest};
use util::paths::SUPERMAVEN_DIR;
#[derive(Serialize)]

View File

@ -37,3 +37,4 @@ env_logger.workspace = true
gpui = { workspace = true, features = ["test-support"] }
rand.workspace = true
util = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }

View File

@ -22,7 +22,6 @@ dirs = "3.0"
futures.workspace = true
git2 = { workspace = true, optional = true }
globset.workspace = true
isahc.workspace = true
lazy_static.workspace = true
log.workspace = true
rand.workspace = true
@ -35,7 +34,6 @@ futures-lite.workspace = true
take-until = "0.2.0"
tempfile = { workspace = true, optional = true }
unicase.workspace = true
url.workspace = true
[target.'cfg(windows)'.dependencies]
tendril = "0.4.3"

View File

@ -1,219 +1 @@
use crate::http_proxy_from_env;
pub use anyhow::{anyhow, Result};
use futures::future::BoxFuture;
use futures_lite::FutureExt;
use isahc::config::{Configurable, RedirectPolicy};
pub use isahc::{
http::{Method, StatusCode, Uri},
AsyncBody, Error, HttpClient as IsahcHttpClient, Request, Response,
};
#[cfg(feature = "test-support")]
use std::fmt;
use std::{
sync::{Arc, Mutex},
time::Duration,
};
pub use url::Url;
/// An [`HttpClient`] that has a base URL.
pub struct HttpClientWithUrl {
base_url: Mutex<String>,
client: Arc<dyn HttpClient>,
}
impl HttpClientWithUrl {
/// Returns a new [`HttpClientWithUrl`] with the given base URL.
pub fn new(base_url: impl Into<String>) -> Self {
Self {
base_url: Mutex::new(base_url.into()),
client: client(),
}
}
/// Returns the base URL.
pub fn base_url(&self) -> String {
self.base_url
.lock()
.map_or_else(|_| Default::default(), |url| url.clone())
}
/// Sets the base URL.
pub fn set_base_url(&self, base_url: impl Into<String>) {
let base_url = base_url.into();
self.base_url
.lock()
.map(|mut url| {
*url = base_url;
})
.ok();
}
/// Builds a URL using the given path.
pub fn build_url(&self, path: &str) -> String {
format!("{}{}", self.base_url(), path)
}
/// Builds a Zed API URL using the given path.
pub fn build_zed_api_url(&self, path: &str, query: &[(&str, &str)]) -> Result<Url> {
let base_url = self.base_url();
let base_api_url = match base_url.as_ref() {
"https://zed.dev" => "https://api.zed.dev",
"https://staging.zed.dev" => "https://api-staging.zed.dev",
"http://localhost:3000" => "http://localhost:8080",
other => other,
};
Ok(Url::parse_with_params(
&format!("{}{}", base_api_url, path),
query,
)?)
}
}
impl HttpClient for Arc<HttpClientWithUrl> {
fn send(
&self,
req: Request<AsyncBody>,
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
self.client.send(req)
}
}
impl HttpClient for HttpClientWithUrl {
fn send(
&self,
req: Request<AsyncBody>,
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
self.client.send(req)
}
}
pub trait HttpClient: Send + Sync {
fn send(
&self,
req: Request<AsyncBody>,
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>>;
fn get<'a>(
&'a self,
uri: &str,
body: AsyncBody,
follow_redirects: bool,
) -> BoxFuture<'a, Result<Response<AsyncBody>, Error>> {
let request = isahc::Request::builder()
.redirect_policy(if follow_redirects {
RedirectPolicy::Follow
} else {
RedirectPolicy::None
})
.method(Method::GET)
.uri(uri)
.body(body);
match request {
Ok(request) => self.send(request),
Err(error) => async move { Err(error.into()) }.boxed(),
}
}
fn post_json<'a>(
&'a self,
uri: &str,
body: AsyncBody,
) -> BoxFuture<'a, Result<Response<AsyncBody>, Error>> {
let request = isahc::Request::builder()
.method(Method::POST)
.uri(uri)
.header("Content-Type", "application/json")
.body(body);
match request {
Ok(request) => self.send(request),
Err(error) => async move { Err(error.into()) }.boxed(),
}
}
}
pub fn client() -> Arc<dyn HttpClient> {
Arc::new(
isahc::HttpClient::builder()
.connect_timeout(Duration::from_secs(5))
.low_speed_timeout(100, Duration::from_secs(5))
.proxy(http_proxy_from_env())
.build()
.unwrap(),
)
}
impl HttpClient for isahc::HttpClient {
fn send(
&self,
req: Request<AsyncBody>,
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
let client = self.clone();
Box::pin(async move { client.send_async(req).await })
}
}
#[cfg(feature = "test-support")]
type FakeHttpHandler = Box<
dyn Fn(Request<AsyncBody>) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>>
+ Send
+ Sync
+ 'static,
>;
#[cfg(feature = "test-support")]
pub struct FakeHttpClient {
handler: FakeHttpHandler,
}
#[cfg(feature = "test-support")]
impl FakeHttpClient {
pub fn create<Fut, F>(handler: F) -> Arc<HttpClientWithUrl>
where
Fut: futures::Future<Output = Result<Response<AsyncBody>, Error>> + Send + 'static,
F: Fn(Request<AsyncBody>) -> Fut + Send + Sync + 'static,
{
Arc::new(HttpClientWithUrl {
base_url: Mutex::new("http://test.example".into()),
client: Arc::new(Self {
handler: Box::new(move |req| Box::pin(handler(req))),
}),
})
}
pub fn with_404_response() -> Arc<HttpClientWithUrl> {
Self::create(|_| async move {
Ok(Response::builder()
.status(404)
.body(Default::default())
.unwrap())
})
}
pub fn with_200_response() -> Arc<HttpClientWithUrl> {
Self::create(|_| async move {
Ok(Response::builder()
.status(200)
.body(Default::default())
.unwrap())
})
}
}
#[cfg(feature = "test-support")]
impl fmt::Debug for FakeHttpClient {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("FakeHttpClient").finish()
}
}
#[cfg(feature = "test-support")]
impl HttpClient for FakeHttpClient {
fn send(
&self,
req: Request<AsyncBody>,
) -> BoxFuture<'static, Result<Response<AsyncBody>, Error>> {
let future = (self.handler)(req);
Box::pin(async move { future.await.map(Into::into) })
}
}

View File

@ -1,7 +1,5 @@
pub mod arc_cow;
pub mod fs;
pub mod github;
pub mod http;
pub mod paths;
pub mod serde;
#[cfg(any(test, feature = "test-support"))]
@ -43,28 +41,6 @@ pub fn truncate(s: &str, max_chars: usize) -> &str {
}
}
pub fn http_proxy_from_env() -> Option<isahc::http::Uri> {
macro_rules! try_env {
($($env:literal),+) => {
$(
if let Ok(env) = std::env::var($env) {
return env.parse::<isahc::http::Uri>().ok();
}
)+
};
}
try_env!(
"ALL_PROXY",
"all_proxy",
"HTTPS_PROXY",
"https_proxy",
"HTTP_PROXY",
"http_proxy"
);
None
}
/// Removes characters from the end of the string if its length is greater than `max_chars` and
/// appends "..." to the string. Returns string unchanged if its length is smaller than max_chars.
pub fn truncate_and_trailoff(s: &str, max_chars: usize) -> String {

View File

@ -16,6 +16,7 @@ doctest = false
test-support = [
"call/test-support",
"client/test-support",
"http/test-support",
"db/test-support",
"project/test-support",
"settings/test-support",
@ -37,6 +38,7 @@ derive_more.workspace = true
fs.workspace = true
futures.workspace = true
gpui.workspace = true
http.workspace = true
itertools.workspace = true
language.workspace = true
lazy_static.workspace = true
@ -67,3 +69,4 @@ fs = { workspace = true, features = ["test-support"] }
gpui = { workspace = true, features = ["test-support"] }
project = { workspace = true, features = ["test-support"] }
settings = { workspace = true, features = ["test-support"] }
http = { workspace = true, features = ["test-support"] }

View File

@ -463,7 +463,7 @@ impl AppState {
let fs = fs::FakeFs::new(cx.background_executor().clone());
let languages = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
let clock = Arc::new(clock::FakeSystemClock::default());
let http_client = util::http::FakeHttpClient::with_404_response();
let http_client = http::FakeHttpClient::with_404_response();
let client = Client::new(clock, http_client.clone(), cx);
let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));

View File

@ -19,6 +19,7 @@ test-support = [
"settings/test-support",
"text/test-support",
"gpui/test-support",
"http/test-support",
]
[dependencies]
@ -53,6 +54,7 @@ clock = {workspace = true, features = ["test-support"]}
collections = { workspace = true, features = ["test-support"] }
git2.workspace = true
gpui = {workspace = true, features = ["test-support"]}
http.workspace = true
rand.workspace = true
settings = {workspace = true, features = ["test-support"]}
pretty_assertions.workspace = true

View File

@ -8,6 +8,7 @@ use clock::FakeSystemClock;
use fs::{FakeFs, Fs, RealFs, RemoveOptions};
use git::{repository::GitFileStatus, GITIGNORE};
use gpui::{BorrowAppContext, ModelContext, Task, TestAppContext};
use http::FakeHttpClient;
use parking_lot::Mutex;
use postage::stream::Stream;
use pretty_assertions::assert_eq;
@ -21,7 +22,7 @@ use std::{
path::{Path, PathBuf},
sync::Arc,
};
use util::{http::FakeHttpClient, test::temp_tree, ResultExt};
use util::{test::temp_tree, ResultExt};
#[gpui::test]
async fn test_traversal(cx: &mut TestAppContext) {

View File

@ -50,6 +50,7 @@ git_hosting_providers.workspace = true
go_to_line.workspace = true
gpui.workspace = true
headless.workspace = true
http.workspace = true
image_viewer.workspace = true
inline_completion_button.workspace = true
install_cli.workspace = true

View File

@ -5,6 +5,7 @@ use db::kvp::KEY_VALUE_STORE;
use gpui::{App, AppContext, SemanticVersion};
use isahc::config::Configurable;
use http::{self, HttpClient, HttpClientWithUrl};
use paths::{CRASHES_DIR, CRASHES_RETIRED_DIR};
use release_channel::ReleaseChannel;
use release_channel::RELEASE_CHANNEL;
@ -17,10 +18,7 @@ use std::{
sync::{atomic::Ordering, Arc},
};
use std::{io::Write, panic, sync::atomic::AtomicU32, thread};
use util::{
http::{self, HttpClient, HttpClientWithUrl},
paths, ResultExt,
};
use util::{paths, ResultExt};
use crate::stdout_is_a_pty;
@ -198,13 +196,13 @@ pub fn monitor_main_thread_hangs(
use parking_lot::Mutex;
use http::Method;
use std::{
ffi::c_int,
sync::{mpsc, OnceLock},
time::Duration,
};
use telemetry_events::{BacktraceFrame, HangReport};
use util::http::Method;
use nix::sys::pthread;