Skip to content

Commit 3821266

Browse files
committed
rust: Add some convenience methods/impls to http types
And update rust outbound http examples to use "simple" types. - Add `Request::{get,post}` associated functions which cover the most common request types. - `impl TryIntoOutgoingRequest for RequestBuilder` to skip a boilerplate `.build()` - Add `Response::into_builder` to ease returning an updated response. - `impl Debug for Response` to fix examples Signed-off-by: Lann Martin <[email protected]>
1 parent 3185092 commit 3821266

File tree

8 files changed

+66
-93
lines changed

8 files changed

+66
-93
lines changed

examples/http-rust-outbound-http/outbound-http-to-same-app/Cargo.lock

Lines changed: 0 additions & 53 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/http-rust-outbound-http/outbound-http-to-same-app/Cargo.toml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@ edition = "2021"
77
crate-type = ["cdylib"]
88

99
[dependencies]
10-
# Useful crate to handle errors.
1110
anyhow = "1"
12-
# Crate to simplify working with bytes.
13-
http = "0.2"
14-
# The Spin SDK.
1511
spin-sdk = { path = "../../../sdk/rust" }
16-
url = "2"
12+
1713
[workspace]
Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
use anyhow::Result;
22
use spin_sdk::{
3-
http::{IntoResponse, Request},
3+
http::{IntoResponse, Request, Response},
44
http_component,
55
};
66

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<String> = spin_sdk::http::send(
11-
http::Request::builder()
12-
.method("GET")
13-
.uri("/hello")
14-
.body(())?,
15-
)
16-
.await?;
17-
res.headers_mut()
18-
.insert("spin-component", "rust-outbound-http".try_into()?);
19-
println!("{:?}", res);
20-
Ok(res)
10+
let resp: Response = spin_sdk::http::send(Request::get("/hello")).await?;
11+
let resp = resp
12+
.into_builder()
13+
.header("spin-component", "rust-outbound-http")
14+
.build();
15+
println!("{resp:?}");
16+
Ok(resp)
2117
}

examples/http-rust-outbound-http/outbound-http/Cargo.lock

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

examples/http-rust-outbound-http/outbound-http/Cargo.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@ edition = "2021"
77
crate-type = ["cdylib"]
88

99
[dependencies]
10-
# Useful crate to handle errors.
1110
anyhow = "1"
12-
# General-purpose crate with common HTTP types.
13-
http = "0.2"
14-
# The Spin SDK.
1511
spin-sdk = { path = "../../../sdk/rust" }
1612

1713
[workspace]
Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
use anyhow::Result;
22
use spin_sdk::{
3-
http::{IntoResponse, Request},
3+
http::{IntoResponse, Request, Response},
44
http_component,
55
};
66

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<String> = spin_sdk::http::send(
11-
http::Request::builder()
12-
.method("GET")
13-
.uri("https://random-data-api.fermyon.app/animals/json")
14-
.body(())?,
15-
)
10+
let resp: Response = spin_sdk::http::send(Request::get(
11+
"https://random-data-api.fermyon.app/animals/json",
12+
))
1613
.await?;
17-
res.headers_mut()
18-
.insert("spin-component", "rust-outbound-http".try_into()?);
19-
println!("{:?}", res);
20-
Ok(res)
14+
let resp = resp
15+
.into_builder()
16+
.header("spin-component", "rust-outbound-http")
17+
.build();
18+
println!("{resp:?}");
19+
Ok(resp)
2120
}

sdk/rust/src/http.rs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ pub struct Request {
3434
}
3535

3636
impl Request {
37-
/// Create a new request from a method and uri
37+
/// Creates a new request from a method and uri
3838
pub fn new(method: Method, uri: impl Into<String>) -> Self {
3939
Self {
4040
method,
@@ -44,6 +44,23 @@ impl Request {
4444
}
4545
}
4646

47+
/// Creates a [`RequestBuilder`]
48+
pub fn builder() -> RequestBuilder {
49+
RequestBuilder::new(Method::Get, "/")
50+
}
51+
52+
/// Creates a [`RequestBuilder`] to GET the given `uri`
53+
pub fn get(uri: impl Into<String>) -> RequestBuilder {
54+
RequestBuilder::new(Method::Get, uri)
55+
}
56+
57+
/// Creates a [`RequestBuilder`] to POST the given `body` to `uri`
58+
pub fn post(uri: impl Into<String>, body: impl conversions::IntoBody) -> RequestBuilder {
59+
let mut builder = RequestBuilder::new(Method::Post, uri);
60+
builder.body(body);
61+
builder
62+
}
63+
4764
/// The request method
4865
pub fn method(&self) -> &Method {
4966
&self.method
@@ -95,11 +112,6 @@ impl Request {
95112
self.body
96113
}
97114

98-
/// Create a request builder
99-
pub fn builder() -> RequestBuilder {
100-
RequestBuilder::new(Method::Get, "/")
101-
}
102-
103115
fn parse_uri(uri: String) -> (Option<hyperium::Uri>, String) {
104116
(
105117
hyperium::Uri::try_from(&uri)
@@ -244,11 +256,27 @@ impl Response {
244256
self.body
245257
}
246258

259+
/// Converts this response into a [`ResponseBuilder`]. This can be used to
260+
/// update a response before passing it on.
261+
pub fn into_builder(self) -> ResponseBuilder {
262+
ResponseBuilder { response: self }
263+
}
264+
247265
fn builder() -> ResponseBuilder {
248266
ResponseBuilder::new(200)
249267
}
250268
}
251269

270+
impl std::fmt::Debug for Response {
271+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
272+
f.debug_struct("Response")
273+
.field("status", &self.status)
274+
.field("headers", &self.headers)
275+
.field("body.len()", &self.body.len())
276+
.finish()
277+
}
278+
}
279+
252280
/// A builder for `Response``
253281
pub struct ResponseBuilder {
254282
response: Response,

sdk/rust/src/http/conversions.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ use async_trait::async_trait;
44

55
use crate::wit::wasi::io::streams;
66

7-
use super::{Headers, IncomingRequest, IncomingResponse, OutgoingRequest, OutgoingResponse};
7+
use super::{
8+
Headers, IncomingRequest, IncomingResponse, OutgoingRequest, OutgoingResponse, RequestBuilder,
9+
};
810

911
use super::{responses, NonUtf8BodyError, Request, Response};
1012

@@ -528,6 +530,16 @@ impl TryIntoOutgoingRequest for Request {
528530
}
529531
}
530532

533+
impl TryIntoOutgoingRequest for RequestBuilder {
534+
type Error = std::convert::Infallible;
535+
536+
fn try_into_outgoing_request(
537+
mut self,
538+
) -> Result<(OutgoingRequest, Option<Vec<u8>>), Self::Error> {
539+
self.build().try_into_outgoing_request()
540+
}
541+
}
542+
531543
#[cfg(feature = "http")]
532544
impl<B> TryIntoOutgoingRequest for hyperium::Request<B>
533545
where

0 commit comments

Comments
 (0)