Watch / Tutorial On demand
Overview

About this video

What You'll Learn

  1. Read request headers with Spin's request object and access specific header values safely.
  2. Decode request bodies by matching bytes and converting them into Rust strings.
  3. Parse query strings, send outbound HTTP requests, and allowlist destinations in spin.toml.

A hands-on tour of Spin's Rust SDK: writing and routing an HTTP component, reading headers, decoding the request body, parsing query strings, and making outbound HTTP requests with allowed-domain configuration in spin.toml.

Chapters

Jump to a chapter

  1. 0:00 Introduction
  2. 0:20 Video Outline
  3. 0:44 Writing and Routing the First Endpoint
  4. 2:55 Extracting Request Headers
  5. 4:33 Getting the Request Body
  6. 7:14 Getting Query Parameters
  7. 9:25 Making Outbound HTTP Requests
  8. 13:02 Conclusion
Transcript

Full transcript

Generated from the English captions. Timestamps jump the player to that moment.

Read the full transcript

0:00 Introduction

0:00 Welcome back to the complete guide to Spin. Spin is a framework for building micro services and WebAssembly. Today, I'm gonna guide you through the Rust SDK. Let's get started. Alright. So, for this Rust SDK, I'm gonna guide you through each of the points listed in this markdown file. One, we're gonna write our first endpoint or at least modify what Spin has generated for us. Next, we'll take a look at extracting information from the HTTP headers, then the body, then some query params, then a small gotcha with working with Spin getting the HTTP domain that your application was

0:20 Video Outline

0:38 served on. And lastly, making an outbound HTTP request. So let's start with our endpoint. When you generate in your HTTP rust microservice, you get a lib dot r s. The scaffolding has already generated everything that you need for your first endpoint and all it takes is using the macro HTTP underscore component. Now it doesn't matter what you call this function, but it probably makes sense for this function to represent the endpoint that you're serving. Now, how is this endpoint routed? Well, we use the spin dot toml. If we take a look at the HTTP trigger, you can see that we're serving over

0:44 Writing and Routing the First Endpoint

1:21 slash And we're actually matching on all sub paths. That just means that our endpoint and this application will actually be all paths. Now because spend services are so easy to write, it probably makes sense to generate a new spin micro service for every endpoint. And then you're just modifying the trigger with a path that you want to capture. However, if you prefer to go to more monolithic approach, there's nothing stopping you from bringing in any Rust based router or even just a match statement into your function here and handling the routing yourself. However, I feel that best practice leans towards

1:59 one microservice for each endpoint and as such we're going to do that. So to show that for today, we'll change our base to be slash hello world and our component trigger to only match on this path. Now, we can run spin build And then we can run spin up follow all. Follow all is gonna get us the logs from our component. So now we can run curl localhost 3,000 hello world. And we get hello fermion from our endpoint. If we run this again on the root path, we actually find as we get a photo for.

2:43 And this is what we want. We only want our service to be responsible for the one path at our application. Check. So how do we grab request headers? The spin project provides request and response objects that you can work with within spin services. As such, you can actually see that we have a print statement to print all of the headers from our application to the terminal. So already we're accessing the headers here. So let's just confirm the behavior that we expect. We can run curl dash h, x name Rawkode. We're providing our own custom header here,

2:55 Extracting Request Headers

3:30 where we have local host 3,000 on hello world. And as you can see here, our header has been propagated and printed by our HTTP endpoint. Now, if you only want to access one specific header, like the Rawkode name header. And we can do a request headers get. Where we can ask for x name and now we can change our print statement to only print the Rawkode name. Let's run spin build and spin up follow all. And now you see, we have an option string for the value of our header of Rawkode. If we get a typo or we forget

4:24 this about header, we'll get a none value. Just like you would expect with any piece of Rust code. Headers, check. So now let's take a look at getting the request body. Now there is a little bit of type juggling that has to be done to successfully get the body as a Rust string. Let's take a look. Let's start with let body equals request dot body. Rust analyzer kicks in and tells us that we have a reference to option bytes. Okay. So let's be good to our citizens and instead of just unwrapping, we're going to do a match

4:33 Getting the Request Body

5:05 and could copilot like so. Now, when we have bytes from the body, we just return them to our variable. If we get a none, we're going to return a status of 400 to our client. Next, if you need this as a string, let's say body string equals string from UTF eight body to vector. Now, why do we have to do this little dance? Well, WebAssembly and Rust and Spin are all fairly performance systems. As such they use Rust, Bytes, Bytes, which is a zero copy slice implementation that makes a very fast networking code. But for you to work with them and

5:57 your endpoint, you probably wanna coerce them into a string. Now the string trait does provide a from UTFE, which we can use on a vector of bytes. And baits baits does provide a two vec function that we can call on the baits. This does return our result, so we can use question mark to throw the error to the client or just get back a string. If you wanna handle this differently, you can of course match and do whatever you need. But we are gonna be happy with just a string. From here, we can now do another print

6:33 line and say the body is body string. Like so. So let's pop back to our terminal, run spin build and follow-up. Now we can run our curl command like so. And we see that our body is empty. So just to make sure everything works as expected, let's provide an empty JSON string like so. So there is a little bit of a type dance required to get the body as a string with the Rust SDK, but once you know how to do it, it's there whenever you need it. Next, let's take a look at getting the

7:14 Getting Query Parameters

7:16 query parameters. So let's pop back to our code and we'll just remove all the stuff from our body. And now we're going to do print ln query string, like so. But if we pop open request, as much as Copilot would love there to be a query string function, unfortunately, there is not. Instead, you have to pull out the URI where we can request the query. And right now, I'm just going to do an unwrap or default, so that we can do to print on the command line. The default for that should just be an empty

7:56 string. So we'll run spin build and follow, and we're just gonna do a simple curl to hello world. As you can see, our query string is non existent. So, let's modify that and to do so, we'll need to wrap our curl in quotes. And I can say that my name is Rawkode and my age is 21. And now our query string is printed out in the logs above. Now, you don't need to parse this query string yourself. Because we're using Rust, we have access to whole world of Rust create. So let's add the query string create,

8:42 like so. Now we call query string, queryfy, passing in our query string. Now this is going to return a vector of tuples with the key and values from the query. Now we can iterate over the key value pairs like so. You can grab an iterator for each and print, print, print. Thank you Copilot. Now we can run spin build, like so. And bring back our query command, bring back our curl command. And we can see our name and age. Awesome. Next and last, making an outbound HTTP request. So it's likely at some point your spend

9:25 Making Outbound HTTP Requests

9:31 microservice will want to talk to other parts of the internet or other spend microservices. And to do so is really simple. We can grab the spend, the spend SDK, HTTP and send. This gives us the ability to send an HTTP request to whatever we want. We can use the HTTP request builder to build up our HTTP query. So first we'll do method of get to google.com with no body, like so. Now this does return a result object, so we need to add a couple of question marks. We can grab the response from the outbound request like so.

10:33 Next, we could use it much like a proxy, I just dump that straight to the calling client. Now this is complaining and it's because the errors are different. We can fix that with map error. Now, we can run, spin build and spin up follow all. We can jump back to our favorite kernel command, like so. Now we are presented with an error message right off the bat. Spin tries to be as secure as possible. And as such, you have to specifically allow outbound request to certain destinations and domains. So let's modify our spin.toml to allow a request to google.com.

11:34 So here is our spin.toml. On the component and on each component, you can choose to allow outbound traffic. As such, we could just do an unsecure allow all and this will at least get us running, so that we can run a request. Like so. Now we have a WebAssembly HTTP proxy to any website that we want. Well, kind of. So let's secure this just a little bit more. Instead of doing and secure all, let's just allow google.com. Now this shouldn't change our application and we still get all the outputs from the Google request. So let's make one more change

12:34 to LibRS and this time we'll call github.com. We do a build, we do a curl and destination not allowed. Perfect. So make an outbound HTTP request using the Spin SDK for Rust. It's just a few lines of code. Remember to update your Spin.TOML, Be very specific about the outbound request that you expect to improve your security posture. And that's it. That is your introduction to the Rust SDK for Spin. Happy hacking. If you ever need any help, drop into the comments, reach me on Twitter, or join the Fermion Discord. I'll see you there. Have fun.

Technologies featured

Weekly Cloud Native insights

Stay ahead in cloud native

Tutorials, deep dives, and curated events. No fluff.

Comments, transcript, and resources

Additional Resources

Spin

More about Spin

View all 20 videos
Rust

More about Rust

View all 22 videos