Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
748 changes: 392 additions & 356 deletions Cargo.lock

Large diffs are not rendered by default.

17 changes: 9 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ spin-trigger = { path = "crates/trigger" }
spin-trigger-http = { path = "crates/trigger-http" }
spin-trigger-redis = { path = "crates/trigger-redis" }
terminal = { path = "crates/terminal" }
rand.workspace = true

[target.'cfg(target_os = "linux")'.dependencies]
# This needs to be an explicit dependency to enable
Expand Down Expand Up @@ -173,16 +174,16 @@ tower-service = "0.3.3"
tracing = { version = "0.1.41", features = ["log"] }
url = "2.5.7"
walkdir = "2"
wasm-encoder = "0.239.0"
wasm-metadata = "0.239.0"
wasm-encoder = "0.240.0"
wasm-metadata = "0.240.0"
wasm-pkg-client = "0.11"
wasm-pkg-common = "0.11"
wasmparser = "0.239.0"
wasmtime = { version = "37.0.1", features = ["component-model-async"] }
wasmtime-wasi = { version = "37.0.1", features = ["p3"] }
wasmtime-wasi-http = { version = "37.0.1", features = ["p3"] }
wit-component = "0.239.0"
wit-parser = "0.239.0"
wasmparser = "0.240.0"
wasmtime = { git = "https://github.com/bytecodealliance/wasmtime", branch = "release-39.0.0", features = ["component-model-async"] }
wasmtime-wasi = { git = "https://github.com/bytecodealliance/wasmtime", branch = "release-39.0.0", features = ["p3"] }
wasmtime-wasi-http = { git = "https://github.com/bytecodealliance/wasmtime", branch = "release-39.0.0", features = ["p3", "component-model-async"] }
wit-component = "0.240.0"
wit-parser = "0.240.0"

spin-componentize = { path = "crates/componentize" }

Expand Down
5 changes: 5 additions & 0 deletions crates/core/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ impl<T: 'static> Store<T> {
pub fn data_mut(&mut self) -> &mut T {
self.inner.data_mut()
}

/// Convert `self` to the inner [`wasmtime::Store`].
pub fn into_inner(self) -> wasmtime::Store<T> {
self.inner
}
}

impl<T: 'static> AsRef<wasmtime::Store<T>> for Store<T> {
Expand Down
2 changes: 1 addition & 1 deletion crates/factor-outbound-http/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub use wasmtime_wasi_http::{
HttpResult,
};

pub use wasi::{p2_to_p3_error_code, p3_to_p2_error_code};
pub use wasi::{p2_to_p3_error_code, p3_to_p2_error_code, MutexBody};

#[derive(Default)]
pub struct OutboundHttpFactor {
Expand Down
41 changes: 36 additions & 5 deletions crates/factor-outbound-http/src/wasi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ use std::{
future::Future,
io::IoSlice,
net::SocketAddr,
ops::DerefMut,
pin::Pin,
sync::Arc,
sync::{Arc, Mutex},
task::{self, Context, Poll},
time::Duration,
};

use bytes::Bytes;
use http::{header::HOST, uri::Scheme, Uri};
use http_body::{Body, Frame, SizeHint};
use http_body_util::{combinators::BoxBody, BodyExt};
use http_body_util::{combinators::UnsyncBoxBody, BodyExt};
use hyper_util::{
client::legacy::{
connect::{Connected, Connection},
Expand Down Expand Up @@ -51,6 +52,34 @@ use crate::{

const DEFAULT_TIMEOUT: Duration = Duration::from_secs(600);

pub struct MutexBody<T>(Mutex<T>);

impl<T> MutexBody<T> {
pub fn new(body: T) -> Self {
Self(Mutex::new(body))
}
}

impl<T: Body + Unpin> Body for MutexBody<T> {
type Data = T::Data;
type Error = T::Error;

fn poll_frame(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
Pin::new(self.0.lock().unwrap().deref_mut()).poll_frame(cx)
}

fn is_end_stream(&self) -> bool {
self.0.lock().unwrap().is_end_stream()
}

fn size_hint(&self) -> SizeHint {
self.0.lock().unwrap().size_hint()
}
}

pub(crate) struct HasHttp;

impl HasData for HasHttp {
Expand All @@ -60,14 +89,14 @@ impl HasData for HasHttp {
impl p3::WasiHttpCtx for InstanceState {
fn send_request(
&mut self,
request: http::Request<BoxBody<Bytes, p3_types::ErrorCode>>,
request: http::Request<UnsyncBoxBody<Bytes, p3_types::ErrorCode>>,
options: Option<p3::RequestOptions>,
fut: Box<dyn Future<Output = Result<(), p3_types::ErrorCode>> + Send>,
) -> Box<
dyn Future<
Output = Result<
(
http::Response<BoxBody<Bytes, p3_types::ErrorCode>>,
http::Response<UnsyncBoxBody<Bytes, p3_types::ErrorCode>>,
Box<dyn Future<Output = Result<(), p3_types::ErrorCode>> + Send>,
),
TrappableError<p3_types::ErrorCode>,
Expand All @@ -84,6 +113,8 @@ impl p3::WasiHttpCtx for InstanceState {
// connection).
_ = fut;

let request = request.map(|body| MutexBody::new(body).boxed());

let request_sender = RequestSender {
allowed_hosts: self.allowed_hosts.clone(),
component_tls_configs: self.component_tls_configs.clone(),
Expand Down Expand Up @@ -126,7 +157,7 @@ impl p3::WasiHttpCtx for InstanceState {
sleep: None,
timeout: between_bytes_timeout,
}
.boxed()
.boxed_unsync()
}),
Box::new(async {
// TODO: Can we plumb connection errors through to here, or
Expand Down
28 changes: 14 additions & 14 deletions crates/factor-outbound-http/src/wasi_2023_10_18.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,20 @@ mod bindings {
imports: { default: trappable },
exports: { default: async },
with: {
"wasi:io/poll/pollable": latest::io::poll::Pollable,
"wasi:io/streams/input-stream": latest::io::streams::InputStream,
"wasi:io/streams/output-stream": latest::io::streams::OutputStream,
"wasi:io/streams/error": latest::io::streams::Error,
"wasi:http/types/incoming-response": latest::http::types::IncomingResponse,
"wasi:http/types/incoming-request": latest::http::types::IncomingRequest,
"wasi:http/types/incoming-body": latest::http::types::IncomingBody,
"wasi:http/types/outgoing-response": latest::http::types::OutgoingResponse,
"wasi:http/types/outgoing-request": latest::http::types::OutgoingRequest,
"wasi:http/types/outgoing-body": latest::http::types::OutgoingBody,
"wasi:http/types/fields": latest::http::types::Fields,
"wasi:http/types/response-outparam": latest::http::types::ResponseOutparam,
"wasi:http/types/future-incoming-response": latest::http::types::FutureIncomingResponse,
"wasi:http/types/future-trailers": latest::http::types::FutureTrailers,
"wasi:io/poll.pollable": latest::io::poll::Pollable,
"wasi:io/streams.input-stream": latest::io::streams::InputStream,
"wasi:io/streams.output-stream": latest::io::streams::OutputStream,
"wasi:io/streams.error": latest::io::streams::Error,
"wasi:http/types.incoming-response": latest::http::types::IncomingResponse,
"wasi:http/types.incoming-request": latest::http::types::IncomingRequest,
"wasi:http/types.incoming-body": latest::http::types::IncomingBody,
"wasi:http/types.outgoing-response": latest::http::types::OutgoingResponse,
"wasi:http/types.outgoing-request": latest::http::types::OutgoingRequest,
"wasi:http/types.outgoing-body": latest::http::types::OutgoingBody,
"wasi:http/types.fields": latest::http::types::Fields,
"wasi:http/types.response-outparam": latest::http::types::ResponseOutparam,
"wasi:http/types.future-incoming-response": latest::http::types::FutureIncomingResponse,
"wasi:http/types.future-trailers": latest::http::types::FutureTrailers,
},
});
}
Expand Down
30 changes: 15 additions & 15 deletions crates/factor-outbound-http/src/wasi_2023_11_10.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@ mod bindings {
imports: { default: trappable },
exports: { default: async },
with: {
"wasi:io/poll/pollable": latest::io::poll::Pollable,
"wasi:io/streams/input-stream": latest::io::streams::InputStream,
"wasi:io/streams/output-stream": latest::io::streams::OutputStream,
"wasi:io/error/error": latest::io::error::Error,
"wasi:http/types/incoming-response": latest::http::types::IncomingResponse,
"wasi:http/types/incoming-request": latest::http::types::IncomingRequest,
"wasi:http/types/incoming-body": latest::http::types::IncomingBody,
"wasi:http/types/outgoing-response": latest::http::types::OutgoingResponse,
"wasi:http/types/outgoing-request": latest::http::types::OutgoingRequest,
"wasi:http/types/outgoing-body": latest::http::types::OutgoingBody,
"wasi:http/types/fields": latest::http::types::Fields,
"wasi:http/types/response-outparam": latest::http::types::ResponseOutparam,
"wasi:http/types/future-incoming-response": latest::http::types::FutureIncomingResponse,
"wasi:http/types/future-trailers": latest::http::types::FutureTrailers,
"wasi:http/types/request-options": latest::http::types::RequestOptions,
"wasi:io/poll.pollable": latest::io::poll::Pollable,
"wasi:io/streams.input-stream": latest::io::streams::InputStream,
"wasi:io/streams.output-stream": latest::io::streams::OutputStream,
"wasi:io/error.error": latest::io::error::Error,
"wasi:http/types.incoming-response": latest::http::types::IncomingResponse,
"wasi:http/types.incoming-request": latest::http::types::IncomingRequest,
"wasi:http/types.incoming-body": latest::http::types::IncomingBody,
"wasi:http/types.outgoing-response": latest::http::types::OutgoingResponse,
"wasi:http/types.outgoing-request": latest::http::types::OutgoingRequest,
"wasi:http/types.outgoing-body": latest::http::types::OutgoingBody,
"wasi:http/types.fields": latest::http::types::Fields,
"wasi:http/types.response-outparam": latest::http::types::ResponseOutparam,
"wasi:http/types.future-incoming-response": latest::http::types::FutureIncomingResponse,
"wasi:http/types.future-trailers": latest::http::types::FutureTrailers,
"wasi:http/types.request-options": latest::http::types::RequestOptions,
},
});
}
Expand Down
Loading