Skip to content

Commit 5f992cf

Browse files
authored
Merge pull request #2863 from fermyon/more-http
Move `HandlerType` to `spin-http`
2 parents a22119c + e2693b6 commit 5f992cf

File tree

8 files changed

+87
-70
lines changed

8 files changed

+87
-70
lines changed

Cargo.lock

Lines changed: 2 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use tracing::instrument;
1818
use wasmtime::{InstanceAllocationStrategy, PoolingAllocationConfig};
1919

2020
pub use async_trait::async_trait;
21+
pub use wasmtime::Engine as WasmtimeEngine;
2122
pub use wasmtime::{
2223
self,
2324
component::{Component, Instance, InstancePre, Linker},

crates/core/src/store.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use anyhow::Result;
22
use std::time::{Duration, Instant};
33

4-
use crate::{limits::StoreLimitsAsync, State};
4+
use crate::{limits::StoreLimitsAsync, State, WasmtimeEngine};
55

66
#[cfg(doc)]
77
use crate::EngineBuilder;
@@ -80,14 +80,14 @@ impl<T> wasmtime::AsContextMut for Store<T> {
8080
///
8181
/// A new [`StoreBuilder`] can be obtained with [`crate::Engine::store_builder`].
8282
pub struct StoreBuilder {
83-
engine: wasmtime::Engine,
83+
engine: WasmtimeEngine,
8484
epoch_tick_interval: Duration,
8585
store_limits: StoreLimitsAsync,
8686
}
8787

8888
impl StoreBuilder {
8989
// Called by Engine::store_builder.
90-
pub(crate) fn new(engine: wasmtime::Engine, epoch_tick_interval: Duration) -> Self {
90+
pub(crate) fn new(engine: WasmtimeEngine, epoch_tick_interval: Duration) -> Self {
9191
Self {
9292
engine,
9393
epoch_tick_interval,

crates/factors-executor/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,16 @@ impl<'a, T: RuntimeFactors, U> FactorsInstanceBuilder<'a, T, U> {
211211
pub fn factor_builder<F: Factor>(&mut self) -> Option<&mut F::InstanceBuilder> {
212212
self.factor_builders().for_factor::<F>()
213213
}
214+
215+
/// Returns the underlying wasmtime engine for the instance.
216+
pub fn wasmtime_engine(&self) -> &spin_core::WasmtimeEngine {
217+
self.instance_pre.engine()
218+
}
219+
220+
/// Returns the compiled component for the instance.
221+
pub fn component(&self) -> &Component {
222+
self.instance_pre.component()
223+
}
214224
}
215225

216226
impl<'a, T: RuntimeFactors, U: Send> FactorsInstanceBuilder<'a, T, U> {

crates/http/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ anyhow = { workspace = true }
99
http = { workspace = true }
1010
http-body-util = { workspace = true }
1111
hyper = { workspace = true }
12-
indexmap = "1"
12+
indexmap = "2"
1313
percent-encoding = "2"
1414
routefinder = "0.5.4"
1515
serde = { workspace = true }
1616
spin-app = { path = "../app", optional = true }
1717
spin-locked-app = { path = "../locked-app" }
1818
tracing = { workspace = true }
19+
wasmtime = { workspace = true }
1920
wasmtime-wasi-http = { workspace = true, optional = true }
2021

2122
[dev-dependencies]

crates/http/src/trigger.rs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use serde::{Deserialize, Serialize};
2+
use wasmtime::component::Component;
23

34
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
45
#[serde(deny_unknown_fields)]
@@ -11,3 +12,67 @@ pub struct Metadata {
1112
pub fn default_base() -> String {
1213
"/".into()
1314
}
15+
16+
/// The type of http handler export used by a component.
17+
#[derive(Clone, Copy)]
18+
pub enum HandlerType {
19+
Spin,
20+
Wagi,
21+
Wasi0_2,
22+
Wasi2023_11_10,
23+
Wasi2023_10_18,
24+
}
25+
26+
/// The `incoming-handler` export for `wasi:http` version rc-2023-10-18
27+
pub const WASI_HTTP_EXPORT_2023_10_18: &str = "wasi:http/[email protected]";
28+
/// The `incoming-handler` export for `wasi:http` version rc-2023-11-10
29+
pub const WASI_HTTP_EXPORT_2023_11_10: &str = "wasi:http/[email protected]";
30+
/// The `incoming-handler` export for `wasi:http` version 0.2.0
31+
pub const WASI_HTTP_EXPORT_0_2_0: &str = "wasi:http/[email protected]";
32+
/// The `incoming-handler` export for `wasi:http` version 0.2.1
33+
pub const WASI_HTTP_EXPORT_0_2_1: &str = "wasi:http/[email protected]";
34+
/// The `inbound-http` export for `fermyon:spin`
35+
pub const SPIN_HTTP_EXPORT: &str = "fermyon:spin/inbound-http";
36+
37+
impl HandlerType {
38+
/// Determine the handler type from the exports of a component.
39+
pub fn from_component(
40+
engine: &wasmtime::Engine,
41+
component: &Component,
42+
) -> anyhow::Result<HandlerType> {
43+
let mut handler_ty = None;
44+
45+
let mut set = |ty: HandlerType| {
46+
if handler_ty.is_none() {
47+
handler_ty = Some(ty);
48+
Ok(())
49+
} else {
50+
Err(anyhow::anyhow!(
51+
"component exports multiple different handlers but \
52+
it's expected to export only one"
53+
))
54+
}
55+
};
56+
let ty = component.component_type();
57+
for (name, _) in ty.exports(engine) {
58+
match name {
59+
WASI_HTTP_EXPORT_2023_10_18 => set(HandlerType::Wasi2023_10_18)?,
60+
WASI_HTTP_EXPORT_2023_11_10 => set(HandlerType::Wasi2023_11_10)?,
61+
WASI_HTTP_EXPORT_0_2_0 | WASI_HTTP_EXPORT_0_2_1 => set(HandlerType::Wasi0_2)?,
62+
SPIN_HTTP_EXPORT => set(HandlerType::Spin)?,
63+
_ => {}
64+
}
65+
}
66+
67+
handler_ty.ok_or_else(|| {
68+
anyhow::anyhow!(
69+
"Expected component to export one of \
70+
`{WASI_HTTP_EXPORT_2023_10_18}`, \
71+
`{WASI_HTTP_EXPORT_2023_11_10}`, \
72+
`{WASI_HTTP_EXPORT_0_2_0}`, \
73+
`{WASI_HTTP_EXPORT_0_2_1}`, \
74+
or `{SPIN_HTTP_EXPORT}` but it exported none of those"
75+
)
76+
})
77+
}
78+
}

crates/trigger-http/src/server.rs

Lines changed: 2 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ use spin_http::{
2020
body,
2121
config::{HttpExecutorType, HttpTriggerConfig},
2222
routes::{RouteMatch, Router},
23+
trigger::HandlerType,
2324
};
2425
use tokio::{
2526
io::{AsyncRead, AsyncWrite},
2627
net::TcpListener,
2728
task,
2829
};
2930
use tracing::Instrument;
30-
use wasmtime::component::Component;
3131
use wasmtime_wasi_http::body::HyperOutgoingBody;
3232

3333
use crate::{
@@ -104,7 +104,7 @@ impl<F: RuntimeFactors> HttpServer<F> {
104104
let handler_type = match &trigger_config.executor {
105105
None | Some(HttpExecutorType::Http) => {
106106
let component = trigger_app.get_component(component_id)?;
107-
HandlerType::from_component(trigger_app.engine(), component)?
107+
HandlerType::from_component(trigger_app.engine().as_ref(), component)?
108108
}
109109
Some(HttpExecutorType::Wagi(wagi_config)) => {
110110
anyhow::ensure!(
@@ -464,61 +464,3 @@ pub(crate) trait HttpExecutor: Clone + Send + Sync + 'static {
464464
client_addr: SocketAddr,
465465
) -> impl Future<Output = anyhow::Result<Response<Body>>>;
466466
}
467-
468-
/// Whether this handler uses the custom Spin http handler interface for wasi-http
469-
#[derive(Clone, Copy)]
470-
pub enum HandlerType {
471-
Spin,
472-
Wagi,
473-
Wasi0_2,
474-
Wasi2023_11_10,
475-
Wasi2023_10_18,
476-
}
477-
478-
pub const WASI_HTTP_EXPORT_2023_10_18: &str = "wasi:http/[email protected]";
479-
pub const WASI_HTTP_EXPORT_2023_11_10: &str = "wasi:http/[email protected]";
480-
pub const WASI_HTTP_EXPORT_0_2_0: &str = "wasi:http/[email protected]";
481-
pub const WASI_HTTP_EXPORT_0_2_1: &str = "wasi:http/[email protected]";
482-
483-
impl HandlerType {
484-
/// Determine the handler type from the exports of a component
485-
pub fn from_component(
486-
engine: impl AsRef<wasmtime::Engine>,
487-
component: &Component,
488-
) -> anyhow::Result<HandlerType> {
489-
let mut handler_ty = None;
490-
491-
let mut set = |ty: HandlerType| {
492-
if handler_ty.is_none() {
493-
handler_ty = Some(ty);
494-
Ok(())
495-
} else {
496-
Err(anyhow::anyhow!(
497-
"component exports multiple different handlers but \
498-
it's expected to export only one"
499-
))
500-
}
501-
};
502-
let ty = component.component_type();
503-
for (name, _) in ty.exports(engine.as_ref()) {
504-
match name {
505-
WASI_HTTP_EXPORT_2023_10_18 => set(HandlerType::Wasi2023_10_18)?,
506-
WASI_HTTP_EXPORT_2023_11_10 => set(HandlerType::Wasi2023_11_10)?,
507-
WASI_HTTP_EXPORT_0_2_0 | WASI_HTTP_EXPORT_0_2_1 => set(HandlerType::Wasi0_2)?,
508-
"fermyon:spin/inbound-http" => set(HandlerType::Spin)?,
509-
_ => {}
510-
}
511-
}
512-
513-
handler_ty.ok_or_else(|| {
514-
anyhow::anyhow!(
515-
"Expected component to export one of \
516-
`{WASI_HTTP_EXPORT_2023_10_18}`, \
517-
`{WASI_HTTP_EXPORT_2023_11_10}`, \
518-
`{WASI_HTTP_EXPORT_0_2_0}`, \
519-
`{WASI_HTTP_EXPORT_0_2_1}`, \
520-
or `fermyon:spin/inbound-http` but it exported none of those"
521-
)
522-
})
523-
}
524-
}

crates/trigger-http/src/wasi.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,13 @@ use spin_factor_outbound_http::wasi_2023_10_18::exports::wasi::http::incoming_ha
88
use spin_factor_outbound_http::wasi_2023_11_10::exports::wasi::http::incoming_handler as incoming_handler2023_11_10;
99
use spin_factors::RuntimeFactors;
1010
use spin_http::routes::RouteMatch;
11+
use spin_http::trigger::HandlerType;
1112
use tokio::{sync::oneshot, task};
1213
use tracing::{instrument, Instrument, Level};
1314
use wasmtime_wasi_http::bindings::http::types::Scheme;
1415
use wasmtime_wasi_http::{bindings::Proxy, body::HyperIncomingBody as Body, WasiHttpView};
1516

16-
use crate::{
17-
headers::prepare_request_headers,
18-
server::{HandlerType, HttpExecutor},
19-
TriggerInstanceBuilder,
20-
};
17+
use crate::{headers::prepare_request_headers, server::HttpExecutor, TriggerInstanceBuilder};
2118

2219
/// An [`HttpExecutor`] that uses the `wasi:http/incoming-handler` interface.
2320
#[derive(Clone)]

0 commit comments

Comments
 (0)