mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-19 18:41:56 +03:00
zed_extension_api: Add HttpRequestBuilder
(#16165)
This PR adds an `HttpRequestBuilder` to the extension API to allow for a more ergonomic way for constructing HTTP requests within extensions. The HTTP client functionality is now also exposed via the `zed_extension_api::http_client` module instead of top-level. Release Notes: - N/A
This commit is contained in:
parent
0dbecee03f
commit
8a9c58e515
@ -1,6 +1,6 @@
|
||||
//! The Zed Rust Extension API allows you write extensions for [Zed](https://zed.dev/) in Rust.
|
||||
|
||||
/// Provides access to Zed settings.
|
||||
pub mod http_client;
|
||||
pub mod settings;
|
||||
|
||||
use core::fmt;
|
||||
@ -19,10 +19,6 @@ pub use wit::{
|
||||
github_release_by_tag_name, latest_github_release, GithubRelease, GithubReleaseAsset,
|
||||
GithubReleaseOptions,
|
||||
},
|
||||
zed::extension::http_client::{
|
||||
fetch, fetch_stream, HttpMethod, HttpRequest, HttpResponse, HttpResponseStream,
|
||||
RedirectPolicy,
|
||||
},
|
||||
zed::extension::nodejs::{
|
||||
node_binary_path, npm_install_package, npm_package_installed_version,
|
||||
npm_package_latest_version,
|
||||
|
95
crates/extension_api/src/http_client.rs
Normal file
95
crates/extension_api/src/http_client.rs
Normal file
@ -0,0 +1,95 @@
|
||||
//! An HTTP client.
|
||||
|
||||
pub use crate::wit::zed::extension::http_client::{
|
||||
fetch, fetch_stream, HttpMethod, HttpRequest, HttpResponse, HttpResponseStream, RedirectPolicy,
|
||||
};
|
||||
|
||||
impl HttpRequest {
|
||||
/// Returns a builder for an [`HttpRequest`].
|
||||
pub fn builder() -> HttpRequestBuilder {
|
||||
HttpRequestBuilder::new()
|
||||
}
|
||||
|
||||
/// Executes the [`HttpRequest`] with [`fetch`].
|
||||
pub fn fetch(&self) -> Result<HttpResponse, String> {
|
||||
fetch(self)
|
||||
}
|
||||
|
||||
/// Executes the [`HttpRequest`] with [`fetch_stream`].
|
||||
pub fn fetch_stream(&self) -> Result<HttpResponseStream, String> {
|
||||
fetch_stream(&self)
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder for an [`HttpRequest`].
|
||||
#[derive(Clone)]
|
||||
pub struct HttpRequestBuilder {
|
||||
method: Option<HttpMethod>,
|
||||
url: Option<String>,
|
||||
headers: Vec<(String, String)>,
|
||||
body: Option<Vec<u8>>,
|
||||
redirect_policy: RedirectPolicy,
|
||||
}
|
||||
|
||||
impl HttpRequestBuilder {
|
||||
/// Returns a new [`HttpRequestBuilder`].
|
||||
pub fn new() -> Self {
|
||||
HttpRequestBuilder {
|
||||
method: None,
|
||||
url: None,
|
||||
headers: Vec::new(),
|
||||
body: None,
|
||||
redirect_policy: RedirectPolicy::NoFollow,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the HTTP method for the request.
|
||||
pub fn method(mut self, method: HttpMethod) -> Self {
|
||||
self.method = Some(method);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the URL for the request.
|
||||
pub fn url(mut self, url: impl Into<String>) -> Self {
|
||||
self.url = Some(url.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a header to the request.
|
||||
pub fn header(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
|
||||
self.headers.push((name.into(), value.into()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds the specified headers to the request.
|
||||
pub fn headers(mut self, headers: impl IntoIterator<Item = (String, String)>) -> Self {
|
||||
self.headers.extend(headers);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the body of the request.
|
||||
pub fn body(mut self, body: impl Into<Vec<u8>>) -> Self {
|
||||
self.body = Some(body.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the redirect policy for the request.
|
||||
pub fn redirect_policy(mut self, policy: RedirectPolicy) -> Self {
|
||||
self.redirect_policy = policy;
|
||||
self
|
||||
}
|
||||
|
||||
/// Builds the [`HttpRequest`].
|
||||
pub fn build(self) -> Result<HttpRequest, String> {
|
||||
let method = self.method.ok_or_else(|| "Method not set".to_string())?;
|
||||
let url = self.url.ok_or_else(|| "URL not set".to_string())?;
|
||||
|
||||
Ok(HttpRequest {
|
||||
method,
|
||||
url,
|
||||
headers: self.headers,
|
||||
body: self.body,
|
||||
redirect_policy: self.redirect_policy,
|
||||
})
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
//! Provides access to Zed settings.
|
||||
|
||||
#[path = "../wit/since_v0.1.0/settings.rs"]
|
||||
mod types;
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
mod hexdocs;
|
||||
|
||||
use std::{fs, io};
|
||||
use zed::http_client::{HttpMethod, HttpRequest, RedirectPolicy};
|
||||
use zed::lsp::CompletionKind;
|
||||
use zed::{
|
||||
CodeLabel, CodeLabelSpan, HttpMethod, HttpRequest, KeyValueStore, LanguageServerId,
|
||||
RedirectPolicy, SlashCommand, SlashCommandArgumentCompletion, SlashCommandOutput,
|
||||
SlashCommandOutputSection,
|
||||
CodeLabel, CodeLabelSpan, KeyValueStore, LanguageServerId, SlashCommand,
|
||||
SlashCommandArgumentCompletion, SlashCommandOutput, SlashCommandOutputSection,
|
||||
};
|
||||
use zed_extension_api::{self as zed, Result};
|
||||
|
||||
@ -194,23 +194,20 @@ impl zed::Extension for GleamExtension {
|
||||
.ok_or_else(|| "missing package name".to_string())?;
|
||||
let module_path = components.map(ToString::to_string).collect::<Vec<_>>();
|
||||
|
||||
let response = zed::fetch(&HttpRequest {
|
||||
method: HttpMethod::Get,
|
||||
url: format!(
|
||||
let response = HttpRequest::builder()
|
||||
.method(HttpMethod::Get)
|
||||
.url(format!(
|
||||
"https://hexdocs.pm/{package_name}{maybe_path}",
|
||||
maybe_path = if !module_path.is_empty() {
|
||||
format!("/{}.html", module_path.join("/"))
|
||||
} else {
|
||||
String::new()
|
||||
}
|
||||
),
|
||||
headers: vec![(
|
||||
"User-Agent".to_string(),
|
||||
"Zed (Gleam Extension)".to_string(),
|
||||
)],
|
||||
body: None,
|
||||
redirect_policy: RedirectPolicy::FollowAll,
|
||||
})?;
|
||||
))
|
||||
.header("User-Agent", "Zed (Gleam Extension)")
|
||||
.redirect_policy(RedirectPolicy::FollowAll)
|
||||
.build()?
|
||||
.fetch()?;
|
||||
|
||||
let (markdown, _modules) =
|
||||
convert_hexdocs_to_markdown(&mut io::Cursor::new(response.body))?;
|
||||
|
@ -11,7 +11,8 @@ use html_to_markdown::{
|
||||
StartTagOutcome, TagHandler,
|
||||
};
|
||||
use zed_extension_api::{
|
||||
self as zed, HttpMethod, HttpRequest, KeyValueStore, RedirectPolicy, Result,
|
||||
http_client::{HttpMethod, HttpRequest, RedirectPolicy},
|
||||
KeyValueStore, Result,
|
||||
};
|
||||
|
||||
pub fn index(package: String, database: &KeyValueStore) -> Result<()> {
|
||||
@ -20,13 +21,13 @@ pub fn index(package: String, database: &KeyValueStore) -> Result<()> {
|
||||
"Zed (Gleam Extension)".to_string(),
|
||||
)];
|
||||
|
||||
let response = zed::fetch(&HttpRequest {
|
||||
method: HttpMethod::Get,
|
||||
url: format!("https://hexdocs.pm/{package}"),
|
||||
headers: headers.clone(),
|
||||
body: None,
|
||||
redirect_policy: RedirectPolicy::FollowAll,
|
||||
})?;
|
||||
let response = HttpRequest::builder()
|
||||
.method(HttpMethod::Get)
|
||||
.url(format!("https://hexdocs.pm/{package}"))
|
||||
.headers(headers.clone())
|
||||
.redirect_policy(RedirectPolicy::FollowAll)
|
||||
.build()?
|
||||
.fetch()?;
|
||||
|
||||
let (package_root_markdown, modules) =
|
||||
convert_hexdocs_to_markdown(&mut io::Cursor::new(&response.body))?;
|
||||
@ -34,13 +35,13 @@ pub fn index(package: String, database: &KeyValueStore) -> Result<()> {
|
||||
database.insert(&package, &package_root_markdown)?;
|
||||
|
||||
for module in modules {
|
||||
let response = zed::fetch(&HttpRequest {
|
||||
method: HttpMethod::Get,
|
||||
url: format!("https://hexdocs.pm/{package}/{module}.html"),
|
||||
headers: headers.clone(),
|
||||
body: None,
|
||||
redirect_policy: RedirectPolicy::FollowAll,
|
||||
})?;
|
||||
let response = HttpRequest::builder()
|
||||
.method(HttpMethod::Get)
|
||||
.url(format!("https://hexdocs.pm/{package}/{module}.html"))
|
||||
.headers(headers.clone())
|
||||
.redirect_policy(RedirectPolicy::FollowAll)
|
||||
.build()?
|
||||
.fetch()?;
|
||||
|
||||
let (markdown, _modules) =
|
||||
convert_hexdocs_to_markdown(&mut io::Cursor::new(&response.body))?;
|
||||
|
Loading…
Reference in New Issue
Block a user