• No results found

Dynamic reloading

In document Web Development With Go (Page 31-40)

Box 2.7. Port 3000 and localhost.

If this is your first time seeing things likelocalhostand:3000they might seem confusing at first, but don’t worry! They are actually pretty simple to understand.

In computer networking, the term localhost was created to mean “this com-puter”. When we talk about visiting http://localhost:3000/ in your browser, what we are really telling the browser is “try to load a web page from this computer at port 3000”.

The port comes from the last part of the URL; The:3000portion. When you type www.google.cominto your browser you don’t have to include a port because the browser will use a default port automatically, but you could type it explicitly if you wanted. Try going tohttp://www.google.com:80.

We don’t have to use port 3000 locally. In fact, many developers use port 8080 for local development. I simply opted to use port 3000 because it is what I am used to.

2.3 Dynamic reloading

You may have noticed this already, but when you make changes to your ap-plication it doesn’t automatically restart and show us our changes. This is a good thing when we deploy to a production server because it means our server doesn’t have to waste time checking to see if the code has changed, but when we are developing an app and changing it a lot it can become very tedious to always have to stop and restart our server.

Enter fresh. This is a Go library written to monitor your folder for file changes, and when it detects them it will recompile your code and restart your server. This is called hot reloading.

Box 2.8. Fresh is NOT required!

20 CHAPTER 2. A BASIC WEB APPLICATION

You DO NOT need to use fresh throughout the rest of the book. This section is purely optional, but if you purchased the screencasts to go with the book you might see or hear me refer to fresh, so I wanted to cover it briefly in the book as well.

It is also worth mentioning that while fresh IS an abandoned project, it still works perfectly fine for our purposes. The abandoned tag on Github simply means that the primary developer behind it is no longer maintaining and improving fresh.

To use fresh, you first need to install it. Open up your terminal and get the library usinggo get.

Listing 2.4: Installing fresh.

$ go get github.com/pilu/fresh

Next we need to configure fresh to recognize changes in all of the files we will be editing in this tutorial. By default fresh only recognizes changes to .go, .tpl, .tmpl, and .html. We will be using .gohtml for our templates because this is the common extension used byAtomand theGoSublimeplugin forSublime Text 3.

Create a file in yourusegolang.comdirectory namedrunner.confand add the following contents to it.

Listing 2.5: Creating a runner.confforfresh.

root: .

tmp_path: ./tmp

build_name: runner-build

build_log: runner-build-errors.log

valid_ext: .go, .tpl, .tmpl, .html, .gohtml ignored: public, assets, tmp

2.3. DYNAMIC RELOADING 21 You don’t really need to understand this for now, but you are welcome to tweak the colors in this file. Just be sure to use a color listedin the fresh colors map.

Now that we have fresh setup, all we need to do to run it is to typefresh into our terminal inside theusegolang.com directory.

Listing 2.6: Starting the server using fresh.

$ fresh

Figure 2.1: Fresh starting up

You should see some output that looks like Figure 2.1 after running the fresh command. If so, congrats! You have successfully started your web application using fresh!

Box 2.9. A warning about failed builds.

22 CHAPTER 2. A BASIC WEB APPLICATION

While fresh is incredibly helpful, there are a few things to be aware of if you are going to use it. The first is that it isn’t always obvious when a build fails. The second is that until a build completes, fresh will continue running the old version of the application.

Put these two together and it can be very confusing when you can’t figure out why your application won’t update with your most recent changes. When this happens it is very likely that you have a bug in your code that is preventing it from building.

My suggestion is to stop fresh (use ctrl + c in the terminal) and then restart it if you are uncertain of why new changes aren’t being displayed. If you had a build issue fresh will fail to start up until you fix it. If the issue was something else (like a file extension not being watched by fresh) then your application will at the very least update with the new code and hint that you might want to add another file type to therunner.conffile.

Chapter 3

Adding new pages

A web application would be pretty boring with only one page, so in this section we are going to explore how to add new pages to a web application. We will start off by adding a contact page where people can find contact information for getting in touch, and then we will add a catch-all page (often called a 404 page, but for now we won’t ) that we want to show when someone goes to a page that we haven’t specified.

Box 3.1. HTTP Status Codes.

When your web server responds to a request, it also returns a status code. For most web requests your server will return a 200 status code, which means that everything was successful. When something goes wrong that was a result of bad data or a mistake in the client, a 400-499 status code is returned. For example, if you try to visit a page that doesn’t exist a server will return a 404 status code, which means that the page was not found.

A 404 page gets its name from its HTTP status code. When a user attempts to visit a page that doesn’t exist your application should return a 404 status code, and if the user was requesting an HTML page it should render a page telling the user that you couldn’t find the page the user was looking for. For now we are going to use a basic 404 page, but remember that over time a lot of your users may see this

23

24 CHAPTER 3. ADDING NEW PAGES

page when they make a typo or any other mistake, and it is a great page to make an impression on them. You can see several great examples of 404 pageshere.

Once we have a few basic pages added to our site we will start to talk about routing. Routing is used to determine what code should be responding to each request based on what URL the user is visiting. For example, if you visit usegolang.com you will be directed to the Use Golang homepage, but if you visitusegolang.com/faqyou will instead be shown the FAQ. Both of these requests end up going to the same web application and a router determines what code to use to respond to each request.

To get started, lets try to write our own very basic routing logic. Open up main.goand edit the handlerFunc.

Listing 3.1: Routing via the URL path.

func handlerFunc(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html")

if r.URL.Path == "/" {

fmt.Fprint(w, "<h1>Welcome to my awesome site!</h1>") } else if r.URL.Path == "/contact" {

fmt.Fprint(w, "To get in touch, please send an email "+

"to <a href=\"mailto:[email protected]\">"+

"[email protected]</a>.") }

}

If you don’t have your server running, start it up again using fresh.

Listing 3.2: Starting the server with fresh.

$ fresh

Box 3.2. Restarting without hot reloading.

25

If you are opting to not use fresh you will need to stop the server by pressing ctrl + c in the terminal, and then start it again usinggo run main.go.

Once your server has restarted, head on over to localhost:3000/contactand you will see your contact page. Then head to localhost:3000and you will see your home page. But what happens if you go to another path? Try it out -navigate to localhost:3000/something. You should see a blank page, because our server isn’t raising an error, but it also isn’t returning a webpage. Ideally when a user visits a page that doesn’t exist we want to raise a 404 error and render a page telling the user that we couldn’t locate the page they were looking for. To do this, change handlerFuncto reflect the code inListing 3.3.

Listing 3.3: Creating a 404 page.

func handlerFunc(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html")

if r.URL.Path == "/" {

fmt.Fprint(w, "<h1>Welcome to my awesome site!</h1>") } else if r.URL.Path == "/contact" {

fmt.Fprint(w, "To get in touch, please send an email "+

"to <a href=\"mailto:[email protected]\">"+

"[email protected]</a>") } else {

w.WriteHeader(http.StatusNotFound)

fmt.Fprint(w, "<h1>We could not find the page you were "+

"looking for :(</h1>"+

"<p>Please email us if you keep being sent to an "+

"invalid page.</p>") }

}

Let’s quickly review what we have done here before we add anything else.

First we get the URL from the Request object, which returns a *url.URL. This struct has a field on it named Path that returns the path of a URL. For example, if the URL washttp://usegolang.com/docs/abcthen the Path would be/docs/abc. The only exception here is that an empty path is always set to/, or the root path.

26 CHAPTER 3. ADDING NEW PAGES Once we have the path we use it to determine what page to render. If the user is visiting the root path (/) we return our Welcome page. If the user is visiting our contact page (/contact) we return a page with information on how to contact. Finally if we get any other path that we haven’t handled yet we write a header with the 404 code and return a page explaining that we couldn’t find the page they were looking for.

Box 3.3. http.StatusNotFound is a constant.

http.StatusNotFound is simply a constant that has the value 404. This is used to help make code more readable, as most developers don’t know all of the http status codes and using integers throughout your code can make it harder to maintain. If you wanted you could change the line to be w.WriteHeader(404).

3.1 Popular routers

Now that we have some basic routing in place we are going to look into ways to improve and simplify our application. Specifically, we are going to explore open source routers and choose one of those to use with our project.

3.1.1 net/http.ServeMux

The first router we are going to look at is part of the standard library in Go.

net/http.ServeMux is a pretty straightforward router, it is incredibly easy to use, and it works great for simple web applications.

Unfortunately this package is a little lacking in features, and many of these are features that we would ultimately need to write on our own. For example, the http.ServeMux doesn’t provide an easy way to define URL parameters which is something we will utilize in later chapters.

While we could ultimately wrap this router in our own type and add all of the functionality we need, I didn’t want to spend the entire book focusing on

3.1. POPULAR ROUTERS 27 one specific part of a web application and instead opted to use another option.

3.1.2 github.com/julienschmidt/httprouter

github.com/julienschmidt/httprouteris a very popular router and one that I have seen used in several other tutorials and web frameworks. It is used in the popu-lar web framework Gin, and I have even written a few blog posts myself using this router.

What I love about this router is its strong focus on being simple, fast, and efficient. If you check out some of the benchmarks on its Github page you will notice that it outperforms many other routers. On top of this focus on being fast, it also supports named URL parameters and routing based on the HTTP request methodused. We will learn more about this in a future chapter.

Ultimately I opted not to use httprouter for this book for two reasons.

The first is that the library requires you to write http handler functions that take in a third argument if you want to access any path parameters. There isn’t anything wrong with this approach, but I was concerned that it might lead to some confusion with new programmers and opted to instead use the router we are going to cover next -gorilla/mux.Router.

3.1.3 github.com/gorilla/mux.Router

Finally, we are going to check out github.com/gorilla/mux.Router. This router supports everything that we will need throughout this book (and much more), and it also allows us to work with regular old http handler functions.

On top of that,gorilla/muxis a part of theGorilla Toolkit, a popular set of packages for building web applications. That in itself isn’t a reason to use it, but since we will also be using a few other packages from the Gorilla Toolkit it is an added bonus that we are also using their router.

28 CHAPTER 3. ADDING NEW PAGES

In document Web Development With Go (Page 31-40)

Related documents