zed_extension_api: Add fetch (#13716)

This PR adds a new `fetch` function to the `zed_extension_api` to allow
fetching a URL through the Wasm host.

Currently we only support GET requests and return the response body as a
string.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-07-01 16:58:00 -04:00 committed by GitHub
parent e7214a429d
commit 3419f5fc42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 56 additions and 1 deletions

View File

@ -1,10 +1,12 @@
use crate::wasm_host::{wit::ToWasmtimeResult, WasmState};
use ::settings::Settings;
use anyhow::{anyhow, bail, Result};
use anyhow::{anyhow, bail, Context, Result};
use async_compression::futures::bufread::GzipDecoder;
use async_tar::Archive;
use async_trait::async_trait;
use futures::AsyncReadExt;
use futures::{io::BufReader, FutureExt as _};
use http::AsyncBody;
use language::{
language_settings::AllLanguageSettings, LanguageServerBinaryStatus, LspAdapterDelegate,
};
@ -101,6 +103,41 @@ impl HostWorktree for WasmState {
#[async_trait]
impl common::Host for WasmState {}
#[async_trait]
impl http_client::Host for WasmState {
async fn fetch(
&mut self,
req: http_client::HttpRequest,
) -> wasmtime::Result<Result<http_client::HttpResponse, String>> {
maybe!(async {
let url = &req.url;
let mut response = self
.host
.http_client
.get(url, AsyncBody::default(), true)
.await?;
if response.status().is_client_error() || response.status().is_server_error() {
bail!("failed to fetch '{url}': status code {}", response.status())
}
let mut body = Vec::new();
response
.body_mut()
.read_to_end(&mut body)
.await
.with_context(|| format!("failed to read response body from '{url}'"))?;
Ok(http_client::HttpResponse {
body: String::from_utf8(body)?,
})
})
.await
.to_wasmtime_result()
}
}
#[async_trait]
impl nodejs::Host for WasmState {
async fn node_binary_path(&mut self) -> wasmtime::Result<Result<String, String>> {

View File

@ -19,6 +19,7 @@ pub use wit::{
github_release_by_tag_name, latest_github_release, GithubRelease, GithubReleaseAsset,
GithubReleaseOptions,
},
zed::extension::http_client::{fetch, HttpRequest, HttpResponse},
zed::extension::nodejs::{
node_binary_path, npm_install_package, npm_package_installed_version,
npm_package_latest_version,

View File

@ -2,6 +2,7 @@ package zed:extension;
world extension {
import github;
import http-client;
import platform;
import nodejs;

View File

@ -0,0 +1,16 @@
interface http-client {
/// An HTTP request.
record http-request {
/// The URL to which the request should be made.
url: string,
}
/// An HTTP response.
record http-response {
/// The response body.
body: string,
}
/// Performs an HTTP request and returns the response.
fetch: func(req: http-request) -> result<http-response, string>;
}