How can I handle http requests of different methods to / in Go?

Go

Go Problem Overview


I'm trying to figure out the best way to handle requests to / and only / in Go and handle different methods in different ways. Here's the best I've come up with:

package main

import (
	"fmt"
	"html"
	"log"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.URL.Path != "/" {
			http.NotFound(w, r)
			return
		}

		if r.Method == "GET" {
			fmt.Fprintf(w, "GET, %q", html.EscapeString(r.URL.Path))
		} else if r.Method == "POST" {
			fmt.Fprintf(w, "POST, %q", html.EscapeString(r.URL.Path))
		} else {
			http.Error(w, "Invalid request method.", 405)
		}
	})

	log.Fatal(http.ListenAndServe(":8080", nil))
}

Is this idiomatic Go? Is this the best I can do with the standard http lib? I'd much rather do something like http.HandleGet("/", handler) as in express or Sinatra. Is there a good framework for writing simple REST services? web.go looks attractive but appears stagnant.

Thank you for your advice.

Go Solutions


Solution 1 - Go

To ensure that you only serve the root: You're doing the right thing. In some cases you would want to call the ServeHttp method of an http.FileServer object instead of calling NotFound; it depends whether you have miscellaneous files that you want to serve as well.

To handle different methods differently: Many of my HTTP handlers contain nothing but a switch statement like this:

switch r.Method {
case http.MethodGet:
	// Serve the resource.
case http.MethodPost:
	// Create a new record.
case http.MethodPut:
	// Update an existing record.
case http.MethodDelete:
	// Remove the record.
default:
	http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}

Of course, you may find that a third-party package like gorilla works better for you.

Solution 2 - Go

eh, I was actually heading to bed and thus the quick comment on looking at http://www.gorillatoolkit.org/pkg/mux which is really nice and does what you want, just give the docs a look over. For example

func main() {
    r := mux.NewRouter()
    r.HandleFunc("/", HomeHandler)
    r.HandleFunc("/products", ProductsHandler)
    r.HandleFunc("/articles", ArticlesHandler)
    http.Handle("/", r)
}

and

r.HandleFunc("/products", ProductsHandler).
    Host("www.domain.com").
    Methods("GET").
    Schemes("http")

and many other possibilities and ways to perform the above operations.

But I felt a need to address the other part of the question, "Is this the best I can do". If the std lib is a little too bare, a great resource to check out is here: https://github.com/golang/go/wiki/Projects#web-libraries (linked specifically to web libraries).

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTrevor DixonView Question on Stackoverflow
Solution 1 - GoandybalholmView Answer on Stackoverflow
Solution 2 - GodskinnerView Answer on Stackoverflow