1use crate::FieldMap;
2use crate::p3::bindings::clocks::monotonic_clock::Duration;
3use crate::p3::bindings::http::types::{
4 ErrorCode, FieldName, FieldValue, Fields, HeaderError, Headers, Host, HostFields, HostRequest,
5 HostRequestOptions, HostRequestWithStore, HostResponse, HostResponseWithStore, Method, Request,
6 RequestOptions, RequestOptionsError, Response, Scheme, StatusCode, Trailers,
7};
8use crate::p3::body::Body;
9use crate::p3::{HeaderResult, HttpError, RequestOptionsResult};
10use crate::{WasiHttp, WasiHttpCtxView};
11use std::sync::Arc;
12use wasmtime::AsContextMut;
13use wasmtime::component::{Access, FutureReader, Resource, ResourceTable, StreamReader};
14use wasmtime::error::Context as _;
15
16fn get_fields<'a>(
17 table: &'a ResourceTable,
18 fields: &Resource<Fields>,
19) -> wasmtime::Result<&'a Fields> {
20 table
21 .get(&fields)
22 .context("failed to get fields from table")
23}
24
25fn get_fields_mut<'a>(
26 table: &'a mut ResourceTable,
27 fields: &Resource<Fields>,
28) -> HeaderResult<&'a mut Fields> {
29 table
30 .get_mut(&fields)
31 .context("failed to get fields from table")
32 .map_err(crate::p3::HeaderError::trap)
33}
34
35fn push_fields(table: &mut ResourceTable, fields: Fields) -> wasmtime::Result<Resource<Fields>> {
36 table.push(fields).context("failed to push fields to table")
37}
38
39fn delete_fields(table: &mut ResourceTable, fields: Resource<Fields>) -> wasmtime::Result<Fields> {
40 let mut fields = table
41 .delete(fields)
42 .context("failed to delete fields from table")?;
43 fields.set_immutable();
48 Ok(fields)
49}
50
51fn get_request<'a>(
52 table: &'a ResourceTable,
53 req: &Resource<Request>,
54) -> wasmtime::Result<&'a Request> {
55 table.get(req).context("failed to get request from table")
56}
57
58fn get_request_mut<'a>(
59 table: &'a mut ResourceTable,
60 req: &Resource<Request>,
61) -> wasmtime::Result<&'a mut Request> {
62 table
63 .get_mut(req)
64 .context("failed to get request from table")
65}
66
67fn get_response<'a>(
68 table: &'a ResourceTable,
69 res: &Resource<Response>,
70) -> wasmtime::Result<&'a Response> {
71 table.get(res).context("failed to get response from table")
72}
73
74fn get_response_mut<'a>(
75 table: &'a mut ResourceTable,
76 res: &Resource<Response>,
77) -> wasmtime::Result<&'a mut Response> {
78 table
79 .get_mut(res)
80 .context("failed to get response from table")
81}
82
83fn get_request_options<'a>(
84 table: &'a ResourceTable,
85 opts: &Resource<RequestOptions>,
86) -> wasmtime::Result<&'a RequestOptions> {
87 table
88 .get(opts)
89 .context("failed to get request options from table")
90}
91
92fn get_request_options_mut<'a>(
93 table: &'a mut ResourceTable,
94 opts: &Resource<RequestOptions>,
95) -> RequestOptionsResult<&'a mut RequestOptions> {
96 table
97 .get_mut(opts)
98 .context("failed to get request options from table")
99 .map_err(crate::p3::RequestOptionsError::trap)
100}
101
102fn push_request_options(
103 table: &mut ResourceTable,
104 opts: RequestOptions,
105) -> wasmtime::Result<Resource<RequestOptions>> {
106 table
107 .push(opts)
108 .context("failed to push request options to table")
109}
110
111fn delete_request_options(
112 table: &mut ResourceTable,
113 opts: Resource<RequestOptions>,
114) -> wasmtime::Result<RequestOptions> {
115 table
116 .delete(opts)
117 .context("failed to delete request options from table")
118}
119
120impl HostFields for WasiHttpCtxView<'_> {
121 fn new(&mut self) -> wasmtime::Result<Resource<Fields>> {
122 push_fields(self.table, FieldMap::new_mutable(self.ctx.field_size_limit))
123 }
124
125 fn from_list(
126 &mut self,
127 entries: Vec<(FieldName, FieldValue)>,
128 ) -> HeaderResult<Resource<Fields>> {
129 let mut fields = FieldMap::new_mutable(self.ctx.field_size_limit);
130 for (name, value) in entries {
131 fields.append(self.hooks, name, value)?;
132 }
133 let fields = push_fields(self.table, fields).map_err(crate::p3::HeaderError::trap)?;
134 Ok(fields)
135 }
136
137 fn get(
138 &mut self,
139 fields: Resource<Fields>,
140 name: FieldName,
141 ) -> wasmtime::Result<Vec<FieldValue>> {
142 let fields = get_fields(self.table, &fields)?;
143 Ok(fields
144 .get_all(name)
145 .into_iter()
146 .map(|val| val.as_bytes().into())
147 .collect())
148 }
149
150 fn has(&mut self, fields: Resource<Fields>, name: FieldName) -> wasmtime::Result<bool> {
151 let fields = get_fields(self.table, &fields)?;
152 Ok(fields.contains_key(name))
153 }
154
155 fn set(
156 &mut self,
157 fields: Resource<Fields>,
158 name: FieldName,
159 values: Vec<FieldValue>,
160 ) -> HeaderResult<()> {
161 get_fields_mut(self.table, &fields)?.set(self.hooks, name, values)?;
162 Ok(())
163 }
164
165 fn delete(&mut self, fields: Resource<Fields>, name: FieldName) -> HeaderResult<()> {
166 get_fields_mut(self.table, &fields)?.remove_all(self.hooks, name)?;
167 Ok(())
168 }
169
170 fn get_and_delete(
171 &mut self,
172 fields: Resource<Fields>,
173 name: FieldName,
174 ) -> HeaderResult<Vec<FieldValue>> {
175 let name = name.parse().or(Err(HeaderError::InvalidSyntax))?;
176 let values = get_fields_mut(self.table, &fields)?
177 .remove_all(self.hooks, name)?
178 .into_iter();
179 Ok(values.map(|value| value.as_bytes().into()).collect())
180 }
181
182 fn append(
183 &mut self,
184 fields: Resource<Fields>,
185 name: FieldName,
186 value: FieldValue,
187 ) -> HeaderResult<()> {
188 get_fields_mut(self.table, &fields)?.append(self.hooks, name, value)?;
189 Ok(())
190 }
191
192 fn copy_all(
193 &mut self,
194 fields: Resource<Fields>,
195 ) -> wasmtime::Result<Vec<(FieldName, FieldValue)>> {
196 let fields = get_fields(self.table, &fields)?;
197 let fields = fields
198 .iter()
199 .map(|(name, value)| (name.as_str().into(), value.as_bytes().into()))
200 .collect();
201 Ok(fields)
202 }
203
204 fn clone(&mut self, fields: Resource<Fields>) -> wasmtime::Result<Resource<Fields>> {
205 let mut fields = get_fields(self.table, &fields)?.clone();
206 fields.set_mutable(self.ctx.field_size_limit);
207 push_fields(self.table, fields)
208 }
209
210 fn drop(&mut self, fields: Resource<Fields>) -> wasmtime::Result<()> {
211 delete_fields(self.table, fields)?;
212 Ok(())
213 }
214}
215
216fn new_request<S>(
217 mut store: S,
218 mut getter: impl FnMut(&mut S::Data) -> WasiHttpCtxView<'_> + Copy + Send + 'static,
219 headers: Resource<Headers>,
220 contents: Option<StreamReader<u8>>,
221 trailers: FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
222 options: Option<Resource<RequestOptions>>,
223) -> wasmtime::Result<(Resource<Request>, FutureReader<Result<(), ErrorCode>>)>
224where
225 S: AsContextMut,
226{
227 let mut store = store.as_context_mut();
228 let (body, body_result) = Body::new_guest(&mut store, getter, contents, trailers)?;
229 let cx = getter(store.data_mut());
230 let headers = delete_fields(cx.table, headers)?;
231 let options = options
232 .map(|options| delete_request_options(cx.table, options))
233 .transpose()?;
234 let req = Request {
235 method: http::Method::GET,
236 scheme: None,
237 authority: None,
238 path_with_query: None,
239 headers,
240 options: options.map(Into::into),
241 body,
242 };
243 let req = cx
244 .table
245 .push(req)
246 .context("failed to push request to table")?;
247 Ok((req, body_result))
248}
249
250impl<T> HostRequestWithStore<T> for WasiHttp {
251 fn new(
252 store: Access<T, Self>,
253 headers: Resource<Headers>,
254 contents: Option<StreamReader<u8>>,
255 trailers: FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
256 options: Option<Resource<RequestOptions>>,
257 ) -> wasmtime::Result<(Resource<Request>, FutureReader<Result<(), ErrorCode>>)> {
258 let getter = store.getter();
259 new_request(store, getter, headers, contents, trailers, options)
260 }
261
262 fn consume_body(
263 mut store: Access<T, Self>,
264 req: Resource<Request>,
265 fut: FutureReader<Result<(), ErrorCode>>,
266 ) -> wasmtime::Result<(
267 StreamReader<u8>,
268 FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
269 )> {
270 let getter = store.getter();
271 let Request { body, .. } = store.get().table.delete(req)?;
272 body.consume(store, fut, getter)
273 }
274
275 fn drop(mut store: Access<'_, T, Self>, req: Resource<Request>) -> wasmtime::Result<()> {
276 let Request { body, .. } = store.get().table.delete(req)?;
277 body.drop(store)?;
278 Ok(())
279 }
280}
281
282impl HostRequest for WasiHttpCtxView<'_> {
283 fn get_method(&mut self, req: Resource<Request>) -> wasmtime::Result<Method> {
284 let Request { method, .. } = get_request(self.table, &req)?;
285 Ok(method.into())
286 }
287
288 fn set_method(
289 &mut self,
290 req: Resource<Request>,
291 method: Method,
292 ) -> wasmtime::Result<Result<(), ()>> {
293 let req = get_request_mut(self.table, &req)?;
294 let Ok(method) = method.try_into() else {
295 return Ok(Err(()));
296 };
297 req.method = method;
298 Ok(Ok(()))
299 }
300
301 fn get_path_with_query(&mut self, req: Resource<Request>) -> wasmtime::Result<Option<String>> {
302 let Request {
303 path_with_query, ..
304 } = get_request(self.table, &req)?;
305 Ok(path_with_query.as_ref().map(|pq| pq.as_str().into()))
306 }
307
308 fn set_path_with_query(
309 &mut self,
310 req: Resource<Request>,
311 path_with_query: Option<String>,
312 ) -> wasmtime::Result<Result<(), ()>> {
313 let req = get_request_mut(self.table, &req)?;
314 let Some(path_with_query) = path_with_query else {
315 req.path_with_query = None;
316 return Ok(Ok(()));
317 };
318 let Ok(path_with_query) = path_with_query.try_into() else {
319 return Ok(Err(()));
320 };
321 req.path_with_query = Some(path_with_query);
322 Ok(Ok(()))
323 }
324
325 fn get_scheme(&mut self, req: Resource<Request>) -> wasmtime::Result<Option<Scheme>> {
326 let Request { scheme, .. } = get_request(self.table, &req)?;
327 Ok(scheme.as_ref().map(Into::into))
328 }
329
330 fn set_scheme(
331 &mut self,
332 req: Resource<Request>,
333 scheme: Option<Scheme>,
334 ) -> wasmtime::Result<Result<(), ()>> {
335 let req = get_request_mut(self.table, &req)?;
336 let Some(scheme) = scheme else {
337 req.scheme = None;
338 return Ok(Ok(()));
339 };
340 let Ok(scheme) = scheme.try_into() else {
341 return Ok(Err(()));
342 };
343 req.scheme = Some(scheme);
344 Ok(Ok(()))
345 }
346
347 fn get_authority(&mut self, req: Resource<Request>) -> wasmtime::Result<Option<String>> {
348 let Request { authority, .. } = get_request(self.table, &req)?;
349 Ok(authority.as_ref().map(|auth| auth.as_str().into()))
350 }
351
352 fn set_authority(
353 &mut self,
354 req: Resource<Request>,
355 authority: Option<String>,
356 ) -> wasmtime::Result<Result<(), ()>> {
357 let req = get_request_mut(self.table, &req)?;
358 let Some(authority) = authority else {
359 req.authority = None;
360 return Ok(Ok(()));
361 };
362 let Ok(authority) = crate::parse_authority(authority) else {
363 return Ok(Err(()));
364 };
365 req.authority = Some(authority);
366 Ok(Ok(()))
367 }
368
369 fn get_options(
370 &mut self,
371 req: Resource<Request>,
372 ) -> wasmtime::Result<Option<Resource<RequestOptions>>> {
373 let Request { options, .. } = get_request(self.table, &req)?;
374 if let Some(options) = options {
375 let options = push_request_options(
376 self.table,
377 RequestOptions::new_immutable(Arc::clone(options)),
378 )?;
379 Ok(Some(options))
380 } else {
381 Ok(None)
382 }
383 }
384
385 fn get_headers(&mut self, req: Resource<Request>) -> wasmtime::Result<Resource<Headers>> {
386 let Request { headers, .. } = get_request(self.table, &req)?;
387 push_fields(self.table, headers.clone())
388 }
389}
390
391impl HostRequestOptions for WasiHttpCtxView<'_> {
392 fn new(&mut self) -> wasmtime::Result<Resource<RequestOptions>> {
393 push_request_options(self.table, RequestOptions::new_mutable_default())
394 }
395
396 fn get_connect_timeout(
397 &mut self,
398 opts: Resource<RequestOptions>,
399 ) -> wasmtime::Result<Option<Duration>> {
400 let opts = get_request_options(self.table, &opts)?;
401 let Some(connect_timeout) = opts.connect_timeout else {
402 return Ok(None);
403 };
404 let ns = connect_timeout.as_nanos();
405 let ns = Duration::try_from(ns)
406 .context("connect timeout duration nanoseconds do not fit in u64")?;
407 Ok(Some(ns))
408 }
409
410 fn set_connect_timeout(
411 &mut self,
412 opts: Resource<RequestOptions>,
413 duration: Option<Duration>,
414 ) -> RequestOptionsResult<()> {
415 let opts = get_request_options_mut(self.table, &opts)?;
416 let opts = opts.get_mut().ok_or(RequestOptionsError::Immutable)?;
417 opts.connect_timeout = duration.map(core::time::Duration::from_nanos);
418 Ok(())
419 }
420
421 fn get_first_byte_timeout(
422 &mut self,
423 opts: Resource<RequestOptions>,
424 ) -> wasmtime::Result<Option<Duration>> {
425 let opts = get_request_options(self.table, &opts)?;
426 let Some(first_byte_timeout) = opts.first_byte_timeout else {
427 return Ok(None);
428 };
429 let ns = first_byte_timeout.as_nanos();
430 let ns = Duration::try_from(ns)
431 .context("first byte timeout duration nanoseconds do not fit in u64")?;
432 Ok(Some(ns))
433 }
434
435 fn set_first_byte_timeout(
436 &mut self,
437 opts: Resource<RequestOptions>,
438 duration: Option<Duration>,
439 ) -> RequestOptionsResult<()> {
440 let opts = get_request_options_mut(self.table, &opts)?;
441 let opts = opts.get_mut().ok_or(RequestOptionsError::Immutable)?;
442 opts.first_byte_timeout = duration.map(core::time::Duration::from_nanos);
443 Ok(())
444 }
445
446 fn get_between_bytes_timeout(
447 &mut self,
448 opts: Resource<RequestOptions>,
449 ) -> wasmtime::Result<Option<Duration>> {
450 let opts = get_request_options(self.table, &opts)?;
451 let Some(between_bytes_timeout) = opts.between_bytes_timeout else {
452 return Ok(None);
453 };
454 let ns = between_bytes_timeout.as_nanos();
455 let ns = Duration::try_from(ns)
456 .context("between bytes timeout duration nanoseconds do not fit in u64")?;
457 Ok(Some(ns))
458 }
459
460 fn set_between_bytes_timeout(
461 &mut self,
462 opts: Resource<RequestOptions>,
463 duration: Option<Duration>,
464 ) -> RequestOptionsResult<()> {
465 let opts = get_request_options_mut(self.table, &opts)?;
466 let opts = opts.get_mut().ok_or(RequestOptionsError::Immutable)?;
467 opts.between_bytes_timeout = duration.map(core::time::Duration::from_nanos);
468 Ok(())
469 }
470
471 fn clone(
472 &mut self,
473 opts: Resource<RequestOptions>,
474 ) -> wasmtime::Result<Resource<RequestOptions>> {
475 let opts = get_request_options(self.table, &opts)?;
476 push_request_options(self.table, RequestOptions::new_mutable(Arc::clone(opts)))
477 }
478
479 fn drop(&mut self, opts: Resource<RequestOptions>) -> wasmtime::Result<()> {
480 delete_request_options(self.table, opts)?;
481 Ok(())
482 }
483}
484
485fn new_response<S>(
486 mut store: S,
487 mut getter: impl FnMut(&mut S::Data) -> WasiHttpCtxView<'_> + Copy + Send + 'static,
488 headers: Resource<Headers>,
489 contents: Option<StreamReader<u8>>,
490 trailers: FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
491) -> wasmtime::Result<(Resource<Response>, FutureReader<Result<(), ErrorCode>>)>
492where
493 S: AsContextMut,
494{
495 let mut store = store.as_context_mut();
496 let (body, body_result) = Body::new_guest(&mut store, getter, contents, trailers)?;
497 let cx = getter(store.data_mut());
498 let headers = delete_fields(cx.table, headers)?;
499 let res = Response {
500 status: http::StatusCode::OK,
501 headers,
502 body,
503 };
504 let res = cx.table.push(res)?;
505 Ok((res, body_result))
506}
507
508impl<T> HostResponseWithStore<T> for WasiHttp {
509 fn new(
510 store: Access<T, Self>,
511 headers: Resource<Headers>,
512 contents: Option<StreamReader<u8>>,
513 trailers: FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
514 ) -> wasmtime::Result<(Resource<Response>, FutureReader<Result<(), ErrorCode>>)> {
515 let getter = store.getter();
516 new_response(store, getter, headers, contents, trailers)
517 }
518
519 fn consume_body(
520 mut store: Access<T, Self>,
521 res: Resource<Response>,
522 fut: FutureReader<Result<(), ErrorCode>>,
523 ) -> wasmtime::Result<(
524 StreamReader<u8>,
525 FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
526 )> {
527 let getter = store.getter();
528 let Response { body, .. } = store.get().table.delete(res)?;
529 body.consume(store, fut, getter)
530 }
531
532 fn drop(mut store: Access<'_, T, Self>, res: Resource<Response>) -> wasmtime::Result<()> {
533 let Response { body, .. } = store.get().table.delete(res)?;
534 body.drop(store)?;
535 Ok(())
536 }
537}
538
539impl HostResponse for WasiHttpCtxView<'_> {
540 fn get_status_code(&mut self, res: Resource<Response>) -> wasmtime::Result<StatusCode> {
541 let res = get_response(self.table, &res)?;
542 Ok(res.status.into())
543 }
544
545 fn set_status_code(
546 &mut self,
547 res: Resource<Response>,
548 status_code: StatusCode,
549 ) -> wasmtime::Result<Result<(), ()>> {
550 let res = get_response_mut(self.table, &res)?;
551 match http::StatusCode::from_u16(status_code) {
552 Ok(status) if matches!(status_code, 100..=599) => {
553 res.status = status;
554 Ok(Ok(()))
555 }
556 _ => Ok(Err(())),
557 }
558 }
559
560 fn get_headers(&mut self, res: Resource<Response>) -> wasmtime::Result<Resource<Headers>> {
561 let Response { headers, .. } = get_response(self.table, &res)?;
562 push_fields(self.table, headers.clone())
563 }
564}
565
566impl Host for WasiHttpCtxView<'_> {
567 fn convert_error_code(&mut self, error: HttpError) -> wasmtime::Result<ErrorCode> {
568 error.downcast()
569 }
570
571 fn convert_header_error(
572 &mut self,
573 error: crate::p3::HeaderError,
574 ) -> wasmtime::Result<HeaderError> {
575 error.downcast()
576 }
577
578 fn convert_request_options_error(
579 &mut self,
580 error: crate::p3::RequestOptionsError,
581 ) -> wasmtime::Result<RequestOptionsError> {
582 error.downcast()
583 }
584}
585
586mod named {
587 use crate::p3::bindings::clocks::monotonic_clock::Duration;
588 use crate::p3::bindings::http::types::{
589 ErrorCode, FieldName, FieldValue, Fields, HeaderError, Headers, Method, Request,
590 RequestOptions, RequestOptionsError, Response, Scheme, StatusCode, Trailers,
591 };
592 use crate::p3::bindings::named_imports::wasi::http::types;
593 use crate::p3::{HeaderResult, HttpError, RequestOptionsResult};
594 use crate::{WasiHttpNamed, WasiHttpNamedView};
595 use wasmtime::component::{Access, FutureReader, Resource, StreamReader};
596 use wasmtime_wasi::{NamedId, WasiCtxNamedView};
597
598 impl<T> types::Host for WasiCtxNamedView<'_, T>
599 where
600 T: WasiHttpNamedView,
601 {
602 fn convert_error_code(&mut self, error: HttpError) -> wasmtime::Result<ErrorCode> {
603 error.downcast()
604 }
605
606 fn convert_header_error(
607 &mut self,
608 error: crate::p3::HeaderError,
609 ) -> wasmtime::Result<HeaderError> {
610 error.downcast()
611 }
612
613 fn convert_request_options_error(
614 &mut self,
615 error: crate::p3::RequestOptionsError,
616 ) -> wasmtime::Result<RequestOptionsError> {
617 error.downcast()
618 }
619 }
620
621 impl<T> types::HostFields for WasiCtxNamedView<'_, T>
622 where
623 T: WasiHttpNamedView,
624 {
625 fn new(&mut self, id: NamedId) -> wasmtime::Result<Resource<Fields>> {
626 super::HostFields::new(&mut self.0.http(id))
627 }
628
629 fn from_list(
630 &mut self,
631 id: NamedId,
632 entries: Vec<(FieldName, FieldValue)>,
633 ) -> HeaderResult<Resource<Fields>> {
634 super::HostFields::from_list(&mut self.0.http(id), entries)
635 }
636
637 fn get(
638 &mut self,
639 id: NamedId,
640 fields: Resource<Fields>,
641 name: FieldName,
642 ) -> wasmtime::Result<Vec<FieldValue>> {
643 super::HostFields::get(&mut self.0.http(id), fields, name)
644 }
645
646 fn has(
647 &mut self,
648 id: NamedId,
649 fields: Resource<Fields>,
650 name: FieldName,
651 ) -> wasmtime::Result<bool> {
652 super::HostFields::has(&mut self.0.http(id), fields, name)
653 }
654
655 fn set(
656 &mut self,
657 id: NamedId,
658 fields: Resource<Fields>,
659 name: FieldName,
660 values: Vec<FieldValue>,
661 ) -> HeaderResult<()> {
662 super::HostFields::set(&mut self.0.http(id), fields, name, values)
663 }
664
665 fn delete(
666 &mut self,
667 id: NamedId,
668 fields: Resource<Fields>,
669 name: FieldName,
670 ) -> HeaderResult<()> {
671 super::HostFields::delete(&mut self.0.http(id), fields, name)
672 }
673
674 fn get_and_delete(
675 &mut self,
676 id: NamedId,
677 fields: Resource<Fields>,
678 name: FieldName,
679 ) -> HeaderResult<Vec<FieldValue>> {
680 super::HostFields::get_and_delete(&mut self.0.http(id), fields, name)
681 }
682
683 fn append(
684 &mut self,
685 id: NamedId,
686 fields: Resource<Fields>,
687 name: FieldName,
688 value: FieldValue,
689 ) -> HeaderResult<()> {
690 super::HostFields::append(&mut self.0.http(id), fields, name, value)
691 }
692
693 fn copy_all(
694 &mut self,
695 id: NamedId,
696 fields: Resource<Fields>,
697 ) -> wasmtime::Result<Vec<(FieldName, FieldValue)>> {
698 super::HostFields::copy_all(&mut self.0.http(id), fields)
699 }
700
701 fn clone(
702 &mut self,
703 id: NamedId,
704 fields: Resource<Fields>,
705 ) -> wasmtime::Result<Resource<Fields>> {
706 super::HostFields::clone(&mut self.0.http(id), fields)
707 }
708
709 fn drop(&mut self, id: NamedId, fields: Resource<Fields>) -> wasmtime::Result<()> {
710 super::HostFields::drop(&mut self.0.http(id), fields)
711 }
712 }
713
714 impl<T> types::HostRequest for WasiCtxNamedView<'_, T>
715 where
716 T: WasiHttpNamedView,
717 {
718 fn get_method(&mut self, id: NamedId, req: Resource<Request>) -> wasmtime::Result<Method> {
719 super::HostRequest::get_method(&mut self.0.http(id), req)
720 }
721
722 fn set_method(
723 &mut self,
724 id: NamedId,
725 req: Resource<Request>,
726 method: Method,
727 ) -> wasmtime::Result<Result<(), ()>> {
728 super::HostRequest::set_method(&mut self.0.http(id), req, method)
729 }
730
731 fn get_path_with_query(
732 &mut self,
733 id: NamedId,
734 req: Resource<Request>,
735 ) -> wasmtime::Result<Option<String>> {
736 super::HostRequest::get_path_with_query(&mut self.0.http(id), req)
737 }
738
739 fn set_path_with_query(
740 &mut self,
741 id: NamedId,
742 req: Resource<Request>,
743 path_with_query: Option<String>,
744 ) -> wasmtime::Result<Result<(), ()>> {
745 super::HostRequest::set_path_with_query(&mut self.0.http(id), req, path_with_query)
746 }
747
748 fn get_scheme(
749 &mut self,
750 id: NamedId,
751 req: Resource<Request>,
752 ) -> wasmtime::Result<Option<Scheme>> {
753 super::HostRequest::get_scheme(&mut self.0.http(id), req)
754 }
755
756 fn set_scheme(
757 &mut self,
758 id: NamedId,
759 req: Resource<Request>,
760 scheme: Option<Scheme>,
761 ) -> wasmtime::Result<Result<(), ()>> {
762 super::HostRequest::set_scheme(&mut self.0.http(id), req, scheme)
763 }
764
765 fn get_authority(
766 &mut self,
767 id: NamedId,
768 req: Resource<Request>,
769 ) -> wasmtime::Result<Option<String>> {
770 super::HostRequest::get_authority(&mut self.0.http(id), req)
771 }
772
773 fn set_authority(
774 &mut self,
775 id: NamedId,
776 req: Resource<Request>,
777 authority: Option<String>,
778 ) -> wasmtime::Result<Result<(), ()>> {
779 super::HostRequest::set_authority(&mut self.0.http(id), req, authority)
780 }
781
782 fn get_options(
783 &mut self,
784 id: NamedId,
785 req: Resource<Request>,
786 ) -> wasmtime::Result<Option<Resource<RequestOptions>>> {
787 super::HostRequest::get_options(&mut self.0.http(id), req)
788 }
789
790 fn get_headers(
791 &mut self,
792 id: NamedId,
793 req: Resource<Request>,
794 ) -> wasmtime::Result<Resource<Headers>> {
795 super::HostRequest::get_headers(&mut self.0.http(id), req)
796 }
797 }
798
799 impl<T> types::HostRequestOptions for WasiCtxNamedView<'_, T>
800 where
801 T: WasiHttpNamedView,
802 {
803 fn new(&mut self, id: NamedId) -> wasmtime::Result<Resource<RequestOptions>> {
804 super::HostRequestOptions::new(&mut self.0.http(id))
805 }
806
807 fn get_connect_timeout(
808 &mut self,
809 id: NamedId,
810 opts: Resource<RequestOptions>,
811 ) -> wasmtime::Result<Option<Duration>> {
812 super::HostRequestOptions::get_connect_timeout(&mut self.0.http(id), opts)
813 }
814
815 fn set_connect_timeout(
816 &mut self,
817 id: NamedId,
818 opts: Resource<RequestOptions>,
819 duration: Option<Duration>,
820 ) -> RequestOptionsResult<()> {
821 super::HostRequestOptions::set_connect_timeout(&mut self.0.http(id), opts, duration)
822 }
823
824 fn get_first_byte_timeout(
825 &mut self,
826 id: NamedId,
827 opts: Resource<RequestOptions>,
828 ) -> wasmtime::Result<Option<Duration>> {
829 super::HostRequestOptions::get_first_byte_timeout(&mut self.0.http(id), opts)
830 }
831
832 fn set_first_byte_timeout(
833 &mut self,
834 id: NamedId,
835 opts: Resource<RequestOptions>,
836 duration: Option<Duration>,
837 ) -> RequestOptionsResult<()> {
838 super::HostRequestOptions::set_first_byte_timeout(&mut self.0.http(id), opts, duration)
839 }
840
841 fn get_between_bytes_timeout(
842 &mut self,
843 id: NamedId,
844 opts: Resource<RequestOptions>,
845 ) -> wasmtime::Result<Option<Duration>> {
846 super::HostRequestOptions::get_between_bytes_timeout(&mut self.0.http(id), opts)
847 }
848
849 fn set_between_bytes_timeout(
850 &mut self,
851 id: NamedId,
852 opts: Resource<RequestOptions>,
853 duration: Option<Duration>,
854 ) -> RequestOptionsResult<()> {
855 super::HostRequestOptions::set_between_bytes_timeout(
856 &mut self.0.http(id),
857 opts,
858 duration,
859 )
860 }
861
862 fn clone(
863 &mut self,
864 id: NamedId,
865 opts: Resource<RequestOptions>,
866 ) -> wasmtime::Result<Resource<RequestOptions>> {
867 super::HostRequestOptions::clone(&mut self.0.http(id), opts)
868 }
869
870 fn drop(&mut self, id: NamedId, opts: Resource<RequestOptions>) -> wasmtime::Result<()> {
871 super::HostRequestOptions::drop(&mut self.0.http(id), opts)
872 }
873 }
874
875 impl<T> types::HostResponse for WasiCtxNamedView<'_, T>
876 where
877 T: WasiHttpNamedView,
878 {
879 fn get_status_code(
880 &mut self,
881 id: NamedId,
882 res: Resource<Response>,
883 ) -> wasmtime::Result<StatusCode> {
884 super::HostResponse::get_status_code(&mut self.0.http(id), res)
885 }
886
887 fn set_status_code(
888 &mut self,
889 id: NamedId,
890 res: Resource<Response>,
891 status_code: StatusCode,
892 ) -> wasmtime::Result<Result<(), ()>> {
893 super::HostResponse::set_status_code(&mut self.0.http(id), res, status_code)
894 }
895
896 fn get_headers(
897 &mut self,
898 id: NamedId,
899 res: Resource<Response>,
900 ) -> wasmtime::Result<Resource<Headers>> {
901 super::HostResponse::get_headers(&mut self.0.http(id), res)
902 }
903 }
904
905 impl<T, U> types::HostRequestWithStore<U> for WasiHttpNamed<T>
906 where
907 T: WasiHttpNamedView,
908 U: 'static,
909 {
910 fn new(
911 store: Access<U, Self>,
912 id: NamedId,
913 headers: Resource<Headers>,
914 contents: Option<StreamReader<u8>>,
915 trailers: FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
916 options: Option<Resource<RequestOptions>>,
917 ) -> wasmtime::Result<(Resource<Request>, FutureReader<Result<(), ErrorCode>>)> {
918 let getter = store.getter();
919 super::new_request(
920 store,
921 move |data| getter(data).0.http(id),
922 headers,
923 contents,
924 trailers,
925 options,
926 )
927 }
928
929 fn consume_body(
930 mut store: Access<U, Self>,
931 id: NamedId,
932 req: Resource<Request>,
933 fut: FutureReader<Result<(), ErrorCode>>,
934 ) -> wasmtime::Result<(
935 StreamReader<u8>,
936 FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
937 )> {
938 let getter = store.getter();
939 let Request { body, .. } = store.get().0.http(id).table.delete(req)?;
940 body.consume(store, fut, move |data: &mut U| getter(data).0.http(id))
941 }
942
943 fn drop(
944 mut store: Access<'_, U, Self>,
945 id: NamedId,
946 req: Resource<Request>,
947 ) -> wasmtime::Result<()> {
948 let Request { body, .. } = store.get().0.http(id).table.delete(req)?;
949 body.drop(store)?;
950 Ok(())
951 }
952 }
953
954 impl<T, U> types::HostResponseWithStore<U> for WasiHttpNamed<T>
955 where
956 T: WasiHttpNamedView,
957 U: 'static,
958 {
959 fn new(
960 store: Access<U, Self>,
961 id: NamedId,
962 headers: Resource<Headers>,
963 contents: Option<StreamReader<u8>>,
964 trailers: FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
965 ) -> wasmtime::Result<(Resource<Response>, FutureReader<Result<(), ErrorCode>>)> {
966 let getter = store.getter();
967 super::new_response(
968 store,
969 move |data| getter(data).0.http(id),
970 headers,
971 contents,
972 trailers,
973 )
974 }
975
976 fn consume_body(
977 mut store: Access<U, Self>,
978 id: NamedId,
979 res: Resource<Response>,
980 fut: FutureReader<Result<(), ErrorCode>>,
981 ) -> wasmtime::Result<(
982 StreamReader<u8>,
983 FutureReader<Result<Option<Resource<Trailers>>, ErrorCode>>,
984 )> {
985 let getter = store.getter();
986 let Response { body, .. } = store.get().0.http(id).table.delete(res)?;
987 body.consume(store, fut, move |data: &mut U| getter(data).0.http(id))
988 }
989
990 fn drop(
991 mut store: Access<'_, U, Self>,
992 id: NamedId,
993 res: Resource<Response>,
994 ) -> wasmtime::Result<()> {
995 let Response { body, .. } = store.get().0.http(id).table.delete(res)?;
996 body.drop(store)?;
997 Ok(())
998 }
999 }
1000}