1use serde::{Deserialize, Serialize};
2use spin_factor_outbound_http::wasi_2023_10_18::ProxyIndices as ProxyIndices2023_10_18;
3use spin_factor_outbound_http::wasi_2023_11_10::ProxyIndices as ProxyIndices2023_11_10;
4use wasmtime::component::InstancePre;
5use wasmtime_wasi::p2::bindings::CommandIndices;
6use wasmtime_wasi_http::bindings::ProxyIndices;
7
8#[derive(Clone, Debug, Default, Deserialize, Serialize)]
9#[serde(deny_unknown_fields)]
10pub struct Metadata {
11 #[serde(default = "default_base")]
13 pub base: String,
14}
15
16pub fn default_base() -> String {
17 "/".into()
18}
19
20pub enum HandlerType {
22 Spin,
23 Wagi(CommandIndices),
24 Wasi0_2(ProxyIndices),
25 Wasi2023_11_10(ProxyIndices2023_11_10),
26 Wasi2023_10_18(ProxyIndices2023_10_18),
27}
28
29const WASI_HTTP_EXPORT_2023_10_18: &str = "wasi:http/incoming-handler@0.2.0-rc-2023-10-18";
31const WASI_HTTP_EXPORT_2023_11_10: &str = "wasi:http/incoming-handler@0.2.0-rc-2023-11-10";
33const WASI_HTTP_EXPORT_0_2_PREFIX: &str = "wasi:http/incoming-handler@0.2";
35const SPIN_HTTP_EXPORT: &str = "fermyon:spin/inbound-http";
37
38impl HandlerType {
39 pub fn from_instance_pre<T>(pre: &InstancePre<T>) -> anyhow::Result<HandlerType> {
41 let mut candidates = Vec::new();
42 if let Ok(indices) = ProxyIndices::new(pre) {
43 candidates.push(HandlerType::Wasi0_2(indices));
44 }
45 if let Ok(indices) = ProxyIndices2023_10_18::new(pre) {
46 candidates.push(HandlerType::Wasi2023_10_18(indices));
47 }
48 if let Ok(indices) = ProxyIndices2023_11_10::new(pre) {
49 candidates.push(HandlerType::Wasi2023_11_10(indices));
50 }
51 if pre
52 .component()
53 .get_export_index(None, SPIN_HTTP_EXPORT)
54 .is_some()
55 {
56 candidates.push(HandlerType::Spin);
57 }
58
59 match candidates.len() {
60 0 => {
61 anyhow::bail!(
62 "Expected component to export one of \
63 `{WASI_HTTP_EXPORT_2023_10_18}`, \
64 `{WASI_HTTP_EXPORT_2023_11_10}`, \
65 `{WASI_HTTP_EXPORT_0_2_PREFIX}.*`, \
66 or `{SPIN_HTTP_EXPORT}` but it exported none of those. \
67 This may mean the component handles a different trigger, or that its `wasi:http` export is newer then those supported by Spin. \
68 If you're sure this is an HTTP module, check if a Spin upgrade is available: this may handle the newer version."
69 )
70 }
71 1 => Ok(candidates.pop().unwrap()),
72 _ => anyhow::bail!(
73 "component exports multiple different handlers but \
74 it's expected to export only one"
75 ),
76 }
77 }
78}