From the course: Full-Stack Web Applications with Rust and Leptos

Server functions

- [Instructor] Up until this point, we've been laser-focused on the frontend of our web application. In this lesson, we'll finally see how to write backend logic in a Leptos way, and I'm excited, because it's really, really nice. First, to show this off, we're going to create another module called repository. We'll have to declare this module in lib.rs, similar to how we did for component, and then, of course, we'll also have to create a mod.rs file in that directory, and then declare the blog_repository file that we just created. Similar to how the centerpiece of frontend logic in Leptos is the component macro, the centerpiece of writing backend logic in Leptos is the server macro. The way this works is, kind of like the component macro, you use it to annotate a Rust function, and then the function becomes the handler for the API described in the macro. We then call that function a handler function. The server macro takes two parameters. The first is what you'd like to call the API, and the second is a URL path for the API. The return type of the function is going to be a regular Rust result, and the type of the okay variant can be anything that implements serialize and deserialize. We'll get to server function error in a minute. Using this as a starting point, we're going to write the API that allows the frontend to create or update an existing post. Okay, so we're going to turn this example into a function called upsert post that will take as parameters each of the fields that a post has in it, ID, date time, title, image, URL, and content. By upsert, we are combining edit and insert into one function instead of making separate ones, because they would mostly share the same logic. So this is what the function's going to look like. To have our API accept parameters, we literally just add parameters to the handler function. Leptos completely abstracts away the details around how these things are serialized, deserialized, and so on. You might be asking, can't we just add a single post parameter instead of each individual field? We actually could do that, as long as we make post derive serialize and deserialize, but having them as separate parameters will make things a little bit easier on the frontend side of things. You'll see why later. But first, I wanted to point out the best part about Leptos server functions. The function body that you explicitly write is guaranteed to be run on the server. Let me say that again. The function body that you write is guaranteed to be run on the server. You can make requests to other origin servers, perform database operations, and so on. For now, we're just returning this placeholder value, but in a later video, we're going to put some actual SQL queries in here. Stay tuned for that. But here's the kicker. You can actually call this function directly from your frontend code, despite the fact that the body is guaranteed to run on the server. That's because on the frontend, the Leptos framework will swap out the function body with different logic that actually makes an HTTP request to the backend API at the path that you specified in the second parameter of the macro up here, or depending on the situation, if you have server-side rendering enabled, the actual function body will be run on the server before the page HTML is even sent to the client. But don't worry about that too much for now. The point is, one way or another, your frontend code will be calling the function directly. No need to worry about keeping the contract between the client and the server in sync. While we're in here, we might as well create another function for getting a post with a specific ID. For now, we're just going to hardcode the actual response. We'll deal with actually retrieving posts from a database later. Notice how the path we specify is the same as the upsert API. We can do that because Leptos automatically appends the API name to the end of the URL. You'll see exactly what I mean when we actually look at this from the browser perspective. Anyway, there isn't too much different here from the upsert function conceptually. Kind of the same idea. The kicker here is that as we wrote it, this get isn't actually an HTTP GET. That's because Leptos makes all server functions POST by default. All function parameters are sent to the backend using URL form encoding in the POST request, and by default, the response is JSON text. The server macro does have an optional third parameter that you can use to change these defaults, for example, if you wanted to make it a GET instead of a POST. There are a few possible reasons you might want to do that, but in this course, we're just going to embrace the defaults. While we're in here, we'll add another API called get previews that we'll use on the homepage of our blog to get short excerpts from many blog posts, and that's just going to return a vector of posts. In this video, we looked at how to write Leptos server functions, and we wrote a function for getting a post, another function for creating or editing posts, and a third function for getting a vector of posts. For now, they only have placeholder logic. In a future video, we'll be adding database queries. Also in a future video, we'll look at how to invoke them from the frontend.

Contents