Skip to content

Commit dc9c8be

Browse files
committed
Adjust outbound http
Signed-off-by: Ryan Levick <[email protected]>
1 parent a4da3b7 commit dc9c8be

File tree

4 files changed

+65
-7
lines changed

4 files changed

+65
-7
lines changed

examples/http-rust-outbound-http/outbound-http/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use spin_sdk::{
77
/// Send an HTTP request and return the response.
88
#[http_component]
99
async fn send_outbound(_req: Request) -> Result<impl IntoResponse> {
10-
let mut res: http::Response<()> = spin_sdk::http::send(
10+
let mut res: http::Response<String> = spin_sdk::http::send(
1111
http::Request::builder()
1212
.method("GET")
1313
.uri("https://random-data-api.fermyon.app/animals/json")

sdk/rust/src/http.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,34 @@ impl Request {
107107
uri,
108108
)
109109
}
110+
111+
/// Whether the request is an HTTPS request
112+
fn is_https(&self) -> bool {
113+
self.uri
114+
.0
115+
.as_ref()
116+
.and_then(|u| u.scheme())
117+
.map(|s| s == &hyperium::uri::Scheme::HTTPS)
118+
.unwrap_or(true)
119+
}
120+
121+
/// The URI's authority
122+
fn authority(&self) -> Option<&str> {
123+
self.uri
124+
.0
125+
.as_ref()
126+
.and_then(|u| u.authority())
127+
.map(|a| a.as_str())
128+
}
129+
130+
/// The request path and query combined
131+
pub fn path_and_query(&self) -> Option<&str> {
132+
self.uri
133+
.0
134+
.as_ref()
135+
.and_then(|u| u.path_and_query())
136+
.map(|s| s.as_str())
137+
}
110138
}
111139

112140
/// A request builder
@@ -454,7 +482,7 @@ impl OutgoingResponse {
454482
/// # Panics
455483
///
456484
/// Panics if the body was already taken.
457-
pub fn take_body(&self) -> impl futures::Sink<Vec<u8>, Error = anyhow::Error> {
485+
pub fn take_body(&self) -> impl futures::Sink<Vec<u8>, Error = Error> {
458486
executor::outgoing_body(self.write().expect("response body was already taken"))
459487
}
460488
}
@@ -482,7 +510,7 @@ impl ResponseOutparam {
482510
self,
483511
response: OutgoingResponse,
484512
buffer: Vec<u8>,
485-
) -> anyhow::Result<()> {
513+
) -> Result<(), Error> {
486514
use futures::SinkExt;
487515
let mut body = response.take_body();
488516
self.set(response);

sdk/rust/src/http/conversions.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,28 @@ where
482482
}
483483
}
484484

485+
impl TryFrom<Request> for OutgoingRequest {
486+
type Error = std::convert::Infallible;
487+
488+
fn try_from(req: Request) -> Result<Self, Self::Error> {
489+
let headers = req
490+
.headers()
491+
.map(|(k, v)| (k.to_owned(), v.as_bytes().to_owned()))
492+
.collect::<Vec<_>>();
493+
Ok(OutgoingRequest::new(
494+
req.method(),
495+
req.path_and_query(),
496+
Some(if req.is_https() {
497+
&super::Scheme::Https
498+
} else {
499+
&super::Scheme::Http
500+
}),
501+
req.authority(),
502+
&Headers::new(&headers),
503+
))
504+
}
505+
}
506+
485507
#[cfg(feature = "http")]
486508
impl<B> TryFrom<hyperium::Request<B>> for OutgoingRequest
487509
where

sdk/rust/src/http/executor.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::wit::wasi::http::types::{
55
use crate::wit::wasi::io;
66
use crate::wit::wasi::io::streams::{InputStream, OutputStream, StreamError};
77

8-
use anyhow::{anyhow, Error, Result};
8+
use anyhow::{anyhow, Result};
99
use futures::{future, sink, stream, Sink, Stream};
1010

1111
use std::cell::RefCell;
@@ -67,7 +67,7 @@ pub fn run<T>(future: impl Future<Output = T>) -> T {
6767
}
6868
}
6969

70-
pub(crate) fn outgoing_body(body: OutgoingBody) -> impl Sink<Vec<u8>, Error = Error> {
70+
pub(crate) fn outgoing_body(body: OutgoingBody) -> impl Sink<Vec<u8>, Error = types::Error> {
7171
struct Outgoing(Option<(OutputStream, OutgoingBody)>);
7272

7373
impl Drop for Outgoing {
@@ -119,11 +119,19 @@ pub(crate) fn outgoing_body(body: OutgoingBody) -> impl Sink<Vec<u8>, Error = Er
119119
Ok(()) => {
120120
offset += count;
121121
}
122-
Err(_) => break Poll::Ready(Err(anyhow!("I/O error"))),
122+
Err(e) => {
123+
break Poll::Ready(Err(types::Error::ProtocolError(
124+
format!("I/O error: {e}"),
125+
)))
126+
}
123127
}
124128
}
125129
}
126-
Err(_) => break Poll::Ready(Err(anyhow!("I/O error"))),
130+
Err(e) => {
131+
break Poll::Ready(Err(types::Error::ProtocolError(format!(
132+
"I/O error: {e}"
133+
))))
134+
}
127135
}
128136
}
129137
}

0 commit comments

Comments
 (0)