diff --git a/section01/README.md b/section01/README.md index c750648..75f7828 100644 --- a/section01/README.md +++ b/section01/README.md @@ -96,7 +96,7 @@ import ( "net/http" ) -func main() { +func doGet() { req, err := http.NewRequest("GET", "https://golang.org", nil) if err != nil { log.Fatalf("could not create request: %v", err) diff --git a/section01/examples/do-get.go b/section01/examples/do-get.go index b71d6a6..2a2f06c 100644 --- a/section01/examples/do-get.go +++ b/section01/examples/do-get.go @@ -19,7 +19,7 @@ import ( "net/http" ) -func main() { +func doGet() { req, err := http.NewRequest("GET", "https://golang.org", nil) if err != nil { log.Fatalf("could not create request: %v", err) diff --git a/section02/README.md b/section02/README.md index f079a5e..ae4a54a 100644 --- a/section02/README.md +++ b/section02/README.md @@ -20,7 +20,7 @@ method which makes it satisfy the `io.Writer` interface. Let's see a very simple HTTP handler that simply writes `"Hello, web"` to the output: -[embedmd]:# (examples/step1.go /package main/ $) +[embedmd]:# (examples/step1/main.go /package main/ /^}/) ```go package main @@ -58,7 +58,7 @@ for any other paths in the `"/images/"` subtree. Let's see how to register our `helloHandler` defined above: -[embedmd]:# (examples/step2.go /package main/ $) +[embedmd]:# (examples/step2/main.go /package main/ $) ```go package main @@ -81,7 +81,7 @@ Note that we're registering our handler as part of the `main` function. Try to run the code above: ```bash -$ go run examples/step2.go +$ go run examples/step2/main.go ``` What happens? Well, we're missing the last piece of the puzzle: starting the @@ -150,7 +150,7 @@ when no error has occurred the returned value equals to `nil`. So if we want to check that our server started successfully and log an error otherwise we would modify our code to add a call to `ListenAndServe`. -[embedmd]:# (examples/step3.go /package main/ $) +[embedmd]:# (examples/step3/main.go /package main/ $) ```go package main @@ -225,6 +225,7 @@ func addProduct(w http.ResponseWriter, r *http.Request) { func getProduct(w http.ResponseWriter, r *http.Request) { id := mux.Vars(r)["productID"] + log.Printf("fetching product with ID %q", id) // get a specific product } diff --git a/section02/examples/gorilla.go b/section02/examples/gorilla.go index cae3cb3..3d994a5 100644 --- a/section02/examples/gorilla.go +++ b/section02/examples/gorilla.go @@ -30,6 +30,7 @@ func addProduct(w http.ResponseWriter, r *http.Request) { func getProduct(w http.ResponseWriter, r *http.Request) { id := mux.Vars(r)["productID"] + log.Printf("fetching product with ID %q", id) // get a specific product } diff --git a/section02/examples/step1.go b/section02/examples/step1/main.go similarity index 92% rename from section02/examples/step1.go rename to section02/examples/step1/main.go index 9333e26..ed8c3b7 100644 --- a/section02/examples/step1.go +++ b/section02/examples/step1/main.go @@ -21,3 +21,6 @@ import ( func helloHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, web") } + +// This doesn't appear on the markdown docs. +func main() {} diff --git a/section02/examples/step2.go b/section02/examples/step2/main.go similarity index 100% rename from section02/examples/step2.go rename to section02/examples/step2/main.go diff --git a/section02/examples/step3.go b/section02/examples/step3/main.go similarity index 100% rename from section02/examples/step3.go rename to section02/examples/step3/main.go diff --git a/section03/README.md b/section03/README.md index 69cfb15..4faf5db 100644 --- a/section03/README.md +++ b/section03/README.md @@ -22,9 +22,9 @@ The `http.Request` type has a method `FormValue` with the following docs: That's easy! So if we want to obtain the value of a parameter `q` in the URL `/hello?msg=world` we can write the next program. -[embedmd]:# (examples/hello_parameter.go /func handler/ /^}/) +[embedmd]:# (examples/handlers/main.go /func paramHandler/ /^}/) ```go -func handler(w http.ResponseWriter, r *http.Request) { +func paramHandler(w http.ResponseWriter, r *http.Request) { name := r.FormValue("name") if name == "" { name = "friend" @@ -64,6 +64,22 @@ closed at the end of the execution of the http handler, so don't worry about it. There's many ways we can read from an `io.Reader`, but for now you can use `io.ReadAll`, which returns a `[]byte` and an `error` if something goes wrong. +[embedmd]:# (examples/handlers/main.go /func bodyHandler/ /^}/) +```go +func bodyHandler(w http.ResponseWriter, r *http.Request) { + b, err := ioutil.ReadAll(r.Body) + if err != nil { + fmt.Fprintf(w, "could not read body: %v", err) + return + } + name := string(b) + if name == "" { + name = "friend" + } + fmt.Fprintf(w, "Hello, %s!", name) +} +``` + ### Exercise Hello, body Modify the previous exercise so instead of reading the `name` argument from a query or form value it will @@ -143,7 +159,7 @@ You can set headers in the response with the `Header` function in the `ResponseW `Header` returns a [`http.Header`](https://golang.org/pkg/net/http/#Header) which has, among other methods, the method `Set`. We can then set the content type in our `ResponseWriter` named `w` like this. -[embedmd]:# (examples/text_handler.go /w.Header.*/) +[embedmd]:# (examples/texthandler/main.go /w.Header.*/) ```go w.Header().Set("Content-Type", "text/plain") ``` @@ -158,7 +174,7 @@ Some people call them decorators, most of them also write Python 😛. To start we're going to define a new type named `textHandler` that contains a `http.HandlerFunc`. -[embedmd]:# (examples/text_handler.go /type textHandler/ /^}/) +[embedmd]:# (examples/texthandler/main.go /type textHandler/ /^}/) ```go type textHandler struct { h http.HandlerFunc @@ -167,7 +183,7 @@ type textHandler struct { Now we're going to define the `ServeHTTP` method on `textHandler` so it satisfies the `http.Handler` interface. -[embedmd]:# (examples/text_handler.go /.*ServeHTTP/ /^}/) +[embedmd]:# (examples/texthandler/main.go /.*ServeHTTP/ /^}/) ```go func (t textHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { // Set the content type @@ -179,7 +195,7 @@ func (t textHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { Finally we replace our `http.HandleFunc` calls with `http.Handle`. -[embedmd]:# (examples/text_handler.go /func main/ /^}/) +[embedmd]:# (examples/texthandler/main.go /func main/ /^}/) ```go func main() { http.Handle("/hello", textHandler{helloHandler}) diff --git a/section03/examples/hello_body.go b/section03/examples/handlers/main.go similarity index 75% rename from section03/examples/hello_body.go rename to section03/examples/handlers/main.go index 871790d..163f75d 100644 --- a/section03/examples/hello_body.go +++ b/section03/examples/handlers/main.go @@ -21,11 +21,12 @@ import ( ) func main() { - http.HandleFunc("/hello", handler) + http.HandleFunc("/body", bodyHandler) + http.HandleFunc("/param", paramHandler) log.Fatal(http.ListenAndServe(":8080", nil)) } -func handler(w http.ResponseWriter, r *http.Request) { +func bodyHandler(w http.ResponseWriter, r *http.Request) { b, err := ioutil.ReadAll(r.Body) if err != nil { fmt.Fprintf(w, "could not read body: %v", err) @@ -37,3 +38,11 @@ func handler(w http.ResponseWriter, r *http.Request) { } fmt.Fprintf(w, "Hello, %s!", name) } + +func paramHandler(w http.ResponseWriter, r *http.Request) { + name := r.FormValue("name") + if name == "" { + name = "friend" + } + fmt.Fprintf(w, "Hello, %s!", name) +} diff --git a/section03/examples/hello_parameter.go b/section03/examples/hello_parameter.go deleted file mode 100644 index 99508dd..0000000 --- a/section03/examples/hello_parameter.go +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2017 Google Inc. All rights reserved. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to writing, software distributed -// under the License is distributed on a "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. -// -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "fmt" - "log" - "net/http" -) - -func main() { - http.HandleFunc("/hello", handler) - log.Fatal(http.ListenAndServe(":8080", nil)) -} - -func handler(w http.ResponseWriter, r *http.Request) { - name := r.FormValue("name") - if name == "" { - name = "friend" - } - fmt.Fprintf(w, "Hello, %s!", name) -} diff --git a/section03/examples/text_handler.go b/section03/examples/texthandler/main.go similarity index 100% rename from section03/examples/text_handler.go rename to section03/examples/texthandler/main.go