Skip to content

Commit dc70154

Browse files
committed
http_component -> http_service
Signed-off-by: itowlson <ivan.towlson@fermyon.com>
1 parent bbff617 commit dc70154

14 files changed

Lines changed: 162 additions & 2499 deletions

content/v4/ai-sentiment-analysis-api-tutorial.md

Lines changed: 0 additions & 1158 deletions
This file was deleted.

content/v4/http-outbound.md

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30,65 +30,51 @@ The outbound HTTP interface depends on your language.
3030

3131
> [**Want to go straight to the reference documentation?** Find it here.](https://docs.rs/spin-sdk/latest/spin_sdk/http/index.html)
3232
33-
To send requests, use the [`spin_sdk::http::send`](https://docs.rs/spin-sdk/latest/spin_sdk/http/fn.send.html) function. This takes a request argument and returns a response (or error). It is `async`, so within an async inbound handler you can have multiple outbound `send`s running concurrently.
33+
To send requests, use the [`spin_sdk::http::send`](https://docs.rs/spin-sdk/latest/spin_sdk/http/fn.send.html) function. This takes a request argument and returns a response (or error).
3434

35-
> Support for streaming request and response bodies is **experimental**. We currently recommend that you stick with the simpler non-streaming interfaces if you don't require streaming.
36-
37-
`send` is quite flexible in its request and response types. The request may be:
35+
The request you pass to `send` may be:
3836

3937
* [`http::Request`](https://docs.rs/http/latest/http/request/struct.Request.html) - typically constructed via `http::Request::builder()`
4038
* [`spin_sdk::http::Request`](https://docs.rs/spin-sdk/latest/spin_sdk/http/struct.Request.html) - typically constructed via `spin_sdk::http::Request::get()`, `spin_sdk::http::Request::post()`, or `spin_sdk::http::Request::builder()`
41-
* You can also use the [builder type](https://docs.rs/spin-sdk/latest/spin_sdk/http/struct.RequestBuilder.html) directly - `build` will be called automatically for you
42-
* [`spin_sdk::http::OutgoingRequest`](https://docs.rs/spin-sdk/latest/spin_sdk/http/struct.OutgoingRequest.html) - constructed via `OutgoingRequest::new()`
43-
* Any type for which you have implemented the `TryInto<spin_sdk::http::OutgoingRequest>` trait
39+
* Any type which implements the `spin_sdk::http::IntoRequest` trait
4440

4541
Generally, you should use `OutgoingRequest` when you need to stream the outbound request body; otherwise, the `Request` types are usually simpler.
4642

47-
The response may be:
48-
49-
* [`http::Response`](https://docs.rs/http/latest/http/response/struct.Response.html)
50-
* [`spin_sdk::http::Response`](https://docs.rs/spin-sdk/latest/spin_sdk/http/struct.Response.html)
51-
* [`spin_sdk::http::IncomingResponse`](https://docs.rs/spin-sdk/latest/spin_sdk/http/struct.IncomingResponse.html)
52-
* Any type for which you have implemented the [spin_sdk::http::conversions::TryFromIncomingResponse](https://docs.rs/spin-sdk/latest/spin_sdk/http/conversions/trait.TryFromIncomingResponse.html) trait
53-
54-
Generally, you should use `IncomingResponse` when you need to stream the response body; otherwise, the `Response` types are usually simpler.
43+
The response is a `spin_sdk::http::Response`.
5544

5645
Here is an example of doing outbound HTTP in a simple request-response style:
5746

5847
```rust
48+
use futures::StreamExt;
5949
use spin_sdk::{
60-
http::{IntoResponse, Request, Method, Response},
61-
http_component,
50+
http::{body::IncomingBodyExt, EmptyBody, IntoResponse, Request, Method, Response},
51+
http_service,
6252
};
6353

64-
#[http_component]
65-
// The trigger handler (in this case an HTTP handler) has to be async
66-
// so we can `await` the outbound send.
54+
#[http_service]
6755
async fn handle_request(_req: Request) -> anyhow::Result<impl IntoResponse> {
68-
6956
// Create the outbound request object
7057
let request = Request::builder()
7158
.method(Method::Get)
72-
.uri("https://www.fermyon.com/")
73-
.build();
59+
.uri("https://spinframework.dev/")
60+
.body(EmptyBody::new())?;
7461

7562
// Send the request and await the response
76-
let response: Response = spin_sdk::http::send(request).await?;
63+
let response = spin_sdk::http::send(request).await?;
7764

7865
// Use the outbound response body
79-
let response_len = response.body().len();
80-
81-
// Return the response to the inbound request
82-
Ok(Response::builder()
83-
.status(200)
84-
.header("content-type", "text/plain")
85-
.body(format!("The test page was {response_len} bytes"))
86-
.build())
66+
let mut body = response.into_body().stream();
67+
68+
let mut response_len = 0;
69+
while let Some(chunk) = body.next().await {
70+
response_len += chunk?.len();
71+
}
72+
73+
// Return a response to the inbound request
74+
Ok((http::StatusCode::OK, response_len.to_string()))
8775
}
8876
```
8977

90-
For an example of receiving the response in a streaming style, [see this example in the Spin repository](https://github.com/spinframework/spin-rust-sdk/blob/main/examples/wasi-http-streaming-outgoing-body/src/lib.rs).
91-
9278
{{ blockEnd }}
9379

9480
{{ startTab "TypeScript"}}

content/v4/http-trigger.md

Lines changed: 7 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -156,98 +156,39 @@ The exact signature of the HTTP handler, and how a function is identified to be
156156

157157
> [**Want to go straight to the reference documentation?** Find it here.](https://docs.rs/spin-sdk/latest/spin_sdk/http/index.html)
158158
159-
In Rust, the handler is identified by the [`#[spin_sdk::http_component]`](https://docs.rs/spin-sdk/latest/spin_sdk/attr.http_component.html) attribute. The handler function can have one of two forms: _request-response_ or _input-output parameter_.
160-
161-
**Request-Response Handlers**
162-
163-
This form of handler function receives the request as an argument, and returns the response as the return value of the function. For example:
159+
In Rust, the handler is identified by the [`#[spin_sdk::http_service]`](https://docs.rs/spin-sdk/latest/spin_sdk/attr.http_service.html) attribute. The handler function is an async function which receives the request as an argument, and returns the response as the return value of the function. For example:
164160

165161
```rust
166-
#[http_component]
162+
#[http_service]
167163
async fn handle(request: http::Request) -> anyhow::Result<http::Response> { ... }
168164
```
169165

170-
In this form, nothing is sent to the client until the entire response is ready. It is convenient for many use cases, but is not suitable for streaming responses.
171-
172-
> The Rust SDK includes **experimental** support for streaming request and response bodies. We currently recommend that you stick with the simpler non-streaming interfaces if you don't require streaming.
173-
174166
You have some flexibility in choosing the types of the request and response. The request may be:
175167

176168
* [`http::Request`](https://docs.rs/http/latest/http/request/struct.Request.html)
177169
* [`spin_sdk::http::Request`](https://docs.rs/spin-sdk/latest/spin_sdk/http/struct.Request.html)
178-
* [`spin_sdk::http::IncomingRequest`](https://docs.rs/spin-sdk/latest/spin_sdk/http/struct.IncomingRequest.html)
179-
* Any type for which you have implemented the [`spin_sdk::http::conversions::TryFromIncomingRequest`](https://docs.rs/spin-sdk/latest/spin_sdk/http/conversions/trait.TryFromIncomingRequest.html) trait
170+
* Any type which implements the [`spin_sdk::http::FromRequest`](https://docs.rs/spin-sdk/latest/spin_sdk/http/trait.FromRequest.html) trait
180171

181172
The response may be:
182173

183174
* [`http::Response`](https://docs.rs/http/latest/http/response/struct.Response.html) - typically constructed via `Response::builder()`
184175
* [`spin_sdk::http::Response`](https://docs.rs/spin-sdk/latest/spin_sdk/http/struct.Response.html) - typically constructed via a [`ResponseBuilder`](https://docs.rs/spin-sdk/latest/spin_sdk/http/struct.ResponseBuilder.html)
185-
* Any type for which you have implemented the [`spin_sdk::http::IntoResponse`](https://docs.rs/spin-sdk/latest/spin_sdk/http/trait.IntoResponse.html) trait
176+
* Any type which implements the [`spin_sdk::http::IntoResponse`](https://docs.rs/spin-sdk/latest/spin_sdk/http/trait.IntoResponse.html) trait
186177
* A `Result` where the success type is one of the above and the error type is `anyhow::Error` or another error type for which you have implemented `spin_sdk::http::IntoResponse` (such as `anyhow::Result<http::Response>`)
187178

188179
For example:
189180

190181
```rust
191182
use http::{Request, Response};
192183
use spin_sdk::http::IntoResponse;
193-
use spin_sdk::http_component;
184+
use spin_sdk::http_service;
194185

195-
/// A simple Spin HTTP component.
196-
#[http_component]
186+
#[http_service]
197187
async fn handle_hello_rust(_req: Request<()>) -> anyhow::Result<impl IntoResponse> {
198188
Ok(Response::builder()
199189
.status(200)
200190
.header("content-type", "text/plain")
201-
.body("Hello, Fermyon")?)
202-
}
203-
```
204-
205-
> If you're familiar with Spin 1.x, note that Spin 2 is more forgiving with the type in the `.body()` call. You don't need to convert it to bytes or wrap it in an `Option`. To return an empty body, you can pass `()` instead of `None`.
206-
207-
To extract data from the request, specify a body type as the generic parameter for the `Request` type. You can use raw content types such as `Vec<u8>` and `String`, or automatically deserialize a JSON body by using the `spin_sdk::http::Json<T>` type.
208-
209-
**Input-Output Parameter Handlers**
210-
211-
In this form, the handler function receives the request as an argument of type [`spin_sdk::http::IncomingRequest`](https://docs.rs/spin-sdk/latest/spin_sdk/http/struct.IncomingRequest.html). It also receives an argument of type [`spin_sdk::http::ResponseOutparam`](https://docs.rs/spin-sdk/latest/spin_sdk/http/struct.ResponseOutparam.html), through which is sends the response. The function does not return a value. This form is recommended for streaming responses.
212-
213-
To send a response:
214-
215-
1. Create a [`spin_sdk::http::OutgoingResponse`](https://docs.rs/spin-sdk/latest/spin_sdk/http/struct.OutgoingResponse.html).
216-
2. Call `take_body()` on the `OutgoingResponse` - this gives you a [`futures::Sink`](https://docs.rs/futures/latest/futures/sink/trait.Sink.html) that you can later use to send data via the response.
217-
3. Call `set` on the `ResponseOutparam`, passing the `OutgoingResponse`.
218-
4. Call `send` on the `Sink` as many times as you like. Each send is carried out as you call it, so you can send the first part of the response without waiting for the whole response to be ready.
219-
220-
> You will need to reference the `futures` crate in `Cargo.toml`, and `use futures::SinkExt;`, to access the `send` method.
221-
222-
```rust
223-
use futures::SinkExt;
224-
use spin_sdk::http::{Headers, IncomingRequest, OutgoingResponse, ResponseOutparam};
225-
use spin_sdk::http_component;
226-
227-
/// A streaming Spin HTTP component.
228-
#[http_component]
229-
async fn handle_hello_rust(_req: IncomingRequest, response_out: ResponseOutparam) {
230-
// Status code and headers must be supplied before calling take_body
231-
let response = OutgoingResponse::new(
232-
200,
233-
&Headers::new(&[("content-type".to_string(), b"text/plain".to_vec())]),
234-
);
235-
// Get the sink for writing the body into. This must be mutable!
236-
let mut body = response.take_body();
237-
238-
// Connect the OutgoingResponse to the ResponseOutparam.
239-
response_out.set(response);
240-
241-
// Write to the body sink over a period of time. (In this case we simulate a
242-
// long-running operation by manually calling `thread::sleep`.)
243-
for i in 1..20 {
244-
let payload = format!("Hello {i}\n");
245-
if let Err(e) = body.send(payload.into()).await {
246-
eprintln!("Error sending payload: {e:#}");
247-
return;
248-
}
249-
std::thread::sleep(std::time::Duration::from_millis(100));
250-
}
191+
.body("Hello, Spin".to_string())?)
251192
}
252193
```
253194

0 commit comments

Comments
 (0)