3.1 Using GET Requests
In this lesson, you'll learn how to grab data from the query string and URL segments in order to provide users with the data they requested.
1.Introduction4 lessons, 28:03
2.Displaying Content5 lessons, 38:57
3.Handling User Input2 lessons, 20:19
4.Conclusion1 lesson, 01:22
3.1 Using GET Requests
We're going to start looking at handling user input. And in this lesson, we're going to focus on GET requests. And we're going to start with displaying an individual guitar. Now, the obvious place that the input is going to be is the query string. So our URL would look like this. /guitars, then we would have our query string. id =, and then whatever value. Now, this URL is going to match our existing route. Because you cannot define a route based upon the query string. In fact, you would get an error if you attempted to do that. Instead, routes are matched based upon the segments of a URL. So this means that we need to modify our handler to check to see if we have anything in the query string. And then change the behavior based upon that. So the first thing we're going to do is see if we have an id in the query string. And we do that using our request object. We have a property called query, and then we use the name of the query parameter, id, in this case. Now we need to check to see if we don't have an id. Because if the URL is just /guitars, then there's nothing to check. We just need to display our list of guitars. So if we don't have an id, then we are going to just use our existing behavior. Otherwise, we need to take that id and check to see if we have a guitar in the repository. So let's do that. We will use the getById method. We will pass in the id. Now, we should be doing some validation like parseint and all of that wonderful stuff. We're just going to keep things simple. So we are going to try to retrieve a guitar with that id. But we also need to check to see if we don't have a guitar. Because, now, the user could supply an id of 100, which we just have 1, 2, 3, and 4. I would like to have a 100 guitars, but since we don't have an id of 100, then that guitar doesn't exist. So for right now, let's add a todo and return 404, we'll get to that here in a few moments. But if we do have a guitar, then we want to return a view that's going to allow us to display a single guitar. We can't really use our index because that works with in array of guitars. So we could create another view called single. And then we could pass in the pageTitle, which would be the name of the guitar. And then we could also supply the guitar information itself. So that's what we would do. And let's go ahead and create that view. So inside of views and guitars, we'll create a new file called single.html, and I'm just going to paste this in. I mean, the majority of the markup is very much like the index view except that it is for displaying a single guitar. We are displaying all of the information that we have, the manufacturer, the year, the neck material, the fingerboard material, and the frets. And, yeah, that's it. Also, the object name is guitar, as opposed to this, because inside of index, we were inside of a loop. In this case, we're not. So we're using the guitar object because that is what we passed to the view here. So let's test it, that's really all that we need to do to implement that. So we will say guitars with an id of 1 and voila, we have a single guitar. If we say id of 2, id of 3, and id of 4, that’s great. But this is 2018 at the time of this recording, and for many years, we have used nice, pretty, clean URLs. So that we would use guitars/1 or /2, or /3, or /4, normal stuff. So we want to be able to handle those types of URLs as well, and we can. All we have to do is just set up another route, so let's do that. The method is, of course, going to be GET, and the path is going to be a little bit different. We need to start with /guitars. But then we have another segment in the URL, we have the id. Now, in this case, we're going to use what's called a route parameter. You can think of it as a query parameter, except that it's actually a segment in the URL. And to denote a query parameter, we just, or no, not query, a route parameter, we use a set of curly braces. And then inside, we use the name of whatever we want to use. You can think of it as a variable that we are then going to access from the request object. So this is going to match a request for the URL of /guitars/1/2/3/4 and all of that wonderful stuff. So let's have our handler, and why am I doing that? We can do it like this, handler. And we have our request, our response, and in this case, we want a lot of the same code. So let's just copy and paste that. And then we want to get the id from our URL. Well, to do that, we say request, and in this case, we have a property called params. And then we use the name of our route parameter, although it helps if we actually if we use correct syntax. So we have request.params.id. If we named this guitarId, then our parameter name would be guitarId as well. But in this case, we're just going to stick with id. And then we have the same code. Now, we have code replication here. And code replication is not code reuse. So what we're going to do is write a function that is going to do all of that. So we're going to supply an id and the response object. And then we're just going to paste in that code, so that we will attempt to retrieve the guitar and return the single view if we do have a guitar. Let's line this up so that it's a lot nicer. And so this means that inside of our two routes all we have to do is say return single, pass in the id and the response. And we're done, as far as that is concerned. So now let's test it. Let's go to the browser, let's just use that URL there. We did guitars/4, that seemed to have worked. Let's do guitars/1, that worked. Let's also recheck our query string usage. And that appears to work as well. Now, we do need to handle the 404. So let's make a request for an id of 100. And we see that we get a status code 500. We don't get a 404, we get a 500. The reason is because we are trying to access a property on a null object. If we look at the console, Cannot read property 'name' of null. So let's stop this, because we are going to install a tool that this is for hapi, and it's called Boom. I love the name of it. This is a utility for handling HTTP errors. And it's just called boom, like that. So inside of our code, what we are going to do, if we don't have guitar, we are going to throw Boom. And this has a method called notFound. Although we do need a request, or not a request, a require, boom at the top. And then we will throw Boom.notFound. You don't have to supply anything, but you can supply a method or a message if you want. So we can say, Cannot find the requested guitar. And if we refresh that page, we're going to see that it changes from a 500 to a 404. The error is Not Found, the message, Cannot find the requested guitar. Now, we can also approach this in a slightly different way. We have two routes here. And in a real application, I would stick with the two routes, just because that's what I would do. However, we can combine all of this into a single route. Because we do have the ability to say that one of our segments is optional. To do that, we once again use a query or a route parameter. But we would append the route parameter name with a question mark. So this means that this is optional, the URL can or cannot have it. So this means that we can change our code to either retrieve the id from the query string, or we could also use the params as well. And then the rest of the code should be fine. So let's test this, let's make sure that this actually works. Let's refresh. We get the 404, which we would expect there. Let's do /1, /2. All that works fine. Let's use the query parameter of id=4, that works. So we get the same behavior with a little less code. However, in my opinion, the other approach was much more clear. It's also less likely to have bugs. So you can take whatever approach that you want. But my personal preference would be to have multiple routes to handle those situations. And so for the most part we're done. The only other thing that I want to do is add a link to the index. So that as we iterate over the guitars and display the names, I want a link here, so that we go to /guitars, and then we would have the id. And that would make it much easier to navigate to those individual pages. So let's add that link, let's make sure [LAUGH] that it works, and then we will be done. So let's go to the index page, let's click on the link, and that works just great. So handling user input for GET requests is rather straightforward. You can use the query string, and you can easily retrieve the values from the query string. You can also define route parameters, so that different segments in your URL are used for different values. Either way, you will get the information that you need to provide users with the data that they request.