Watch / Tutorial On demand
Overview

About this video

What You'll Learn

  1. Show a Rust password validator shared between backend and frontend.
  2. Compile shared domain logic into WebAssembly for multiple runtimes.
  3. Reuse the same validation rules from Spin and JavaScript clients.

Kicking off the Fermyon Spin course with the why of WebAssembly. A Rust password validator becomes a shared domain crate consumed by a Spin HTTP backend and a JavaScript frontend, both compiled to Wasm.

Chapters

Jump to a chapter

  1. 0:00 Introduction to Course & Topic
  2. 0:19 Why WebAssembly? The Core Value
  3. 1:23 Sample Application Overview
  4. 3:08 Domain Logic: The Language-Agnostic Code (Rust Example)
  5. 5:49 Exposing Domain Logic via WebAssembly (WASM Crate)
  6. 8:09 Consuming in a Fermion Spin (Rust) Application
  7. 9:47 Demonstrating the Spin Backend
  8. 11:26 Consuming in a JavaScript (Frontend) Application
  9. 12:14 Demonstrating the JavaScript Frontend
  10. 14:07 Recap: The Power of WebAssembly
  11. 14:18 What's Next in the Course?
  12. 15:31 Conclusion
Transcript

Full transcript

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

Read the full transcript

0:00 Introduction to Course & Topic

0:06 Hello, and welcome back to the Rawkode Academy. My name is David Flanagan, although you probably know me as Rawkode. And today, we're kicking off our new course, the complete guide to Fermion Spin. If you're not familiar, Spin is a framework from the team at Fermion, which allows you to write micro service applications with a compilation target of WebAssembly. Now before we dive in to the different SDKs and languages that you can write and compile to WebAssembly web, we're gonna spend a little bit of time today understanding the why of WebAssembly. Why if you are a Rust developer,

0:19 Why WebAssembly? The Core Value

0:48 TypeScript developer, Go developer, or any other developer, should you care about using WebAssembly as a target for your application? And there are a few reasons. And I hope that today's small demo will set off a small chain reaction in your mind with an explosion of ideas for your use case on WebAssembly. So without further ado, let's dive in and take a look at today's small code example and why you should start looking at WebAssembly. Let's dive right in. So in order to show you why I think WebAssembly is so important, I have put together a small sample application.

1:23 Sample Application Overview

1:31 Now the first thing to note is this is not a life changing application. This is not a production application. This is a contrived example that wants to show you how to consume WebAssembly modules across disparate systems. Because the true value in WebAssembly comes from the fact that we can choose to use Rust for one part of our system, Go in another, JavaScript or TypeScript, and so forth. Now assuming you compile those to a WebAssembly module, they can be consumed by a WebAssembly runtime or by other languages that understand WebAssembly. This means you get the ability to explore

2:17 and test new languages. Use the correct language for the correct job. Maybe the Rust is the right 190% of the time, but there's still 10% where you wanna fall back on JavaScript or Tensor. There are times you want to use a strongly typed language on the front end, like Rust. And these are all possible via the power of WebAssembly. In fact, Solomon Hicks, the founder of Docker, once said that if WebAssembly had existed, Docker wouldn't. He's saying that if WebAssembly was a compilation target for applications, we wouldn't need containers. And that's a very powerful statement.

3:02 So let's dive into the contrived example and see what I put together. Okay. First, we have the domain folder. This is where we store the domain logic for our application. This is really common across most software teams these days. Domain driven design has gathered a lot of adoption along with the various architectures which have spun out of the movement. It teaches us to build reusable components across our domain using our domain language and hopefully ensuring that you don't reimplement the same thing twice. This is often a challenge for companies that want to have polyglot teams

3:08 Domain Logic: The Language-Agnostic Code (Rust Example)

3:40 because if you write your domain logic in one language, how do you share it and consume it in another? This often leads to rather special test cases to ensure that we have compliance across multiple run times. But with WebAssembly, that concern disappears. And I'm taking the domain that is hopefully familiar to everybody watching this video. Password validation. Is the password that your customer or user using pass the constraints provided by your security team across all of your applications? So I've chosen to write this in Rust. We have a constant defining the minimum length for a password with 16 characters.

4:24 We have two error messages, password too short and password no space, which give us the error message if the password is too short or has no space. We then have a validate password function. Now I kept this really small and simple for today's demo, but you may have more rules in your production systems. We receive the password, and we return a result or an error message. If the length of the password is less than password min length, we return an error message. And if it doesn't contain a space, we return an error message. Assuming both our constraints pass, we return our

5:08 okay response. If we scroll down, you'll see we have a test case. I'm not gonna go through it, but it's just making a few assertions against our function. What's important here is that there is nothing to tell you this is going to be used on WebAssembly. This is a Rust function using Rust types and Rust paradigms. This is the perfect example of writing your domain logic without truly understanding where it's going to end up or be used. Next, we have the Wasm crate. This is our glue. This is what consumes our domain logic with a little bit of binding

5:49 Exposing Domain Logic via WebAssembly (WASM Crate)

5:59 to the WebAssembly module. Now this first function is entirely optional, but I wanna use it to show you the interrupt between client side browser and Rust. Here, we're defining a function called main, and we bind it using wasm bindgen to run when our application has started. We find the HTML DOM window, the document, and the body element. From there, we can actually write hello in your browser and your browser. Kinda neat. Next, we want to expose our domain logic via the Wasm bindings. So we write a function that calls our domain function. Here we have wasm bindgen

6:51 validate password, which takes the string and returns a result or a JS value error. Next, we can just call our Rust function, the validate password function, passing in our password. Now because our domain logic returns a string error, we do need to map this to a JS value. And we do so like this. Rust provides a map error function, which takes the original value and returns a different value. Nice and simple. From here, we can compile our Wasm create, and we have two pieces of reusable information. Any other Rust service or application that we build can consume our domain create just as

7:44 if it was another Rust create because it is just another Rust create. And any application that runs or supports WebAssembly can pull in our WebAssembly module, which just so happens to consume some of our domain logic. And you can expand on this as much as you need and share as much of that agnostic domain logic as you need across all of your services. So let's consume our domain logic from a Fermion Spin application. I've chosen to write this in Rust so that we can see the Rust and Rust interrupt. Although, I should definitely point out that Fermion

8:09 Consuming in a Fermion Spin (Rust) Application

8:29 Spin applications are compiled to a WebAssembly module. Because of that and because our domain is written in Rust, we don't need to consume our domain logic as a WebAssembly module. We can consume it as a Rust module, which is still gonna be compiled to a WebAssembly target. Pretty cool. Here we have a macro that sets up our back end function as an HTTP component on Fermion Spin framework. This just means that when request come in, they can be routed to this back end function. And you'll see it takes a request input parameter. And all it expects is a result response.

9:10 Now we've got a little bit of tape juggling to do to fetch the body from this request, but we can grab the base, coerce it into a string, and then call a validate password function. If we get an okay response, we return a 200 okay. And if we get an error message, we return a four zero one with the error message. Now let me click through to our validate function. This is our nonspecific, non WebAssembly knowledge, straight up pure Rust function. So let's run our back end service. So let's run spin build, followed by spin up

9:47 Demonstrating the Spin Backend

9:57 and follow all to get the logs. Now I provide a small HARL test suite, which we can run like so. You'll see that two requests were made against our back end API and both succeeded. What does our HARL test suite look like? One, we send a post request to local host 3,000 and the password is the full string and the code block. Password space one two three space password space one two three. This will satisfy both our constraints. One, that it's at least 16 characters and two, that has at least one space. Our second assertion is another post to localhost:one

10:53 3000 And this time the password is password space. So we pass the space constraint, but not the 16 characters. And this should return a photo one. And we can confirm by running Hurl one more time. Remove the dash dash test, and we will get the output from the function or the assertion that fails. And the error message is the password must contain at least 16 characters. Perfect. And for the last demo, I'm going to consume the wasm trait. This is a domain logic compiled and exposed via WebAssembly. This time being consumed by a JavaScript function.

11:26 Consuming in a JavaScript (Frontend) Application

11:40 Here, with the right webpack configuration, you can just pull in a WASM package. So here, we're importing a WASM package like any other Node JS dependency. We use a promise so that after the module is loaded, we call the validate password function, and we pass it a password. In this case, password. So now we can run this front end application and see it work. We can run NPM, run build, followed by NPM, run start. This runs the webpack dev server, which we can browse to in our browser. So let's pop open 80 80. And first, we see the string from our

12:14 Demonstrating the JavaScript Frontend

12:40 Rust compiled WebAssembly application. If we take a look at index.HTML, We actually don't print out anything in the body of our HTML. So only by browsing to this is the hello in your browser injected. So let's pop open our dev tools. And if we go to the console, you'll see that the password must be at least 16 characters. Now I am no front end web developer. To me, a good UI is in the CLI. However, we wanna show a demo today. So we're gonna go back to our application and modify the JavaScript code. And this time, I'll make sure the password

13:32 passes the constraints and hit save. Now the webpack web dev server will have reloaded our application in the background, which internal have reloaded our browser. And already, we can see the error message about our password constraints is gone. And one more time, we'll make it fail, hit save, and jump back, and the reload we caught just in time. So from our front end application and pure JavaScript, we're able to consume our domain logic written in Rust, which is compiled to WebAssembly. And that is the power of WebAssembly. And that's all we're gonna cover in this

14:07 Recap: The Power of WebAssembly

14:13 first video. I hope this piques your interest in WebAssembly and you want to learn more. In future segments of this course, we'll be taking a look at all the SDKs provided by Spin. That is Rust, TypeScript and JavaScript, and Go. We may even get a sneak preview of the new Python SDK. I'm not even sure if I'm allowed to say that. After we have covered the SDKs, we're going to build some real world applications using Fermion Spin. One, a Google Analytics replacement. Not completely, but enough to get analytics from the front end application stored into a database

14:18 What's Next in the Course?

14:52 on the back end. This should show us what a full three tier application looks like in the real world. And because we're deploying it as web assembly on Fermion Cloud, we get almost infinite scale with sub millisecond startup times for was in binaries. And the second application we will build is an uptime checker. Using WebAssembly, we can make HTTP requests to check the status of our website. We can run this on a regular cadence and send notifications if our website fails to check. So I hope you'll join us for the next parts of this complete guide to Fermion

15:31 Conclusion

15:34 Spin. Until then, I'll see you next time. Have a great day.

Technologies featured

Weekly Cloud Native insights

Stay ahead in cloud native

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

Comments, transcript, and resources

Spin

More about Spin

View all 20 videos

More about WebAssembly & WASI

View all 17 videos
Rust

More about Rust

View all 22 videos