Skip to content

Instantly share code, notes, and snippets.

@carbonphyber
Created April 2, 2013 05:12
Show Gist options
  • Save carbonphyber/5290082 to your computer and use it in GitHub Desktop.
Save carbonphyber/5290082 to your computer and use it in GitHub Desktop.
package main
import (
"net/http"
"./muxtester" // this is our router library. the "muxtester" dir should be in the same directory as this "main.go"
)
func main() {
http.HandleFunc("/", muxtester.HandleCatchall)
http.ListenAndServe("localhost:8080", nil)
}
/**
* This should be inside of a "muxtester" directory
*/
package muxtester
import(
"io"
"log"
"net/http"
"strings"
)
/**
* HandleCatchall
* This is where all incoming HTTP requests are initially handled.
* This function creates no output, but simply passes off output to other "handle*App" functions.
* This methos is capitalized so it can be exported (to "main.go").
*/
func HandleCatchall(w http.ResponseWriter, r *http.Request) {
// trim the leading and trailing slashes from the URI; then create an array of strings delineated by "/"
theUriParts := strings.SplitN(strings.Trim(r.URL.Path, "/"), "/", 3)
locale := "en_US" // default locale
app := "home" // default app
// set "locale" if there is a non-empty part of the URI where "locale" should be
if len(theUriParts) > 0 && len(theUriParts) > 0 {
locale = theUriParts[0]
}
// set "app" if there is a non-empty part of the URI where "app" should be
if len(theUriParts) > 1 && len(theUriParts[1]) > 0 {
app = theUriParts[1]
}
log.Printf("locale: %s; app: %s;\n", locale, app)
switch app {
case "user":
// note: Go requires no breaks; they are assumed.
handleUserApp(w, r)
case "auth":
// note: Go requires no breaks; they are assumed.
handleAuthApp(w, r)
case "home":
// note: Go requires no breaks; they are assumed.
// in order to combine the "home" case and the default case with the same chunk of code, we need to "fallthrough"
fallthrough
default:
handleHomeApp(w, r)
}
}
func handleUserApp(w http.ResponseWriter, r *http.Request) {
w.Header().Set("content-type", "text/plain; charset=utf8") // "text/plain" for security until you use html/template to safely escape HTML output
io.WriteString(w, "User App")
return
}
func handleAuthApp(w http.ResponseWriter, r *http.Request) {
w.Header().Set("content-type", "text/plain; charset=utf8") // "text/plain" for security until you use html/template to safely escape HTML output
io.WriteString(w, "Auth App")
return
}
// the default app handler
func handleHomeApp(w http.ResponseWriter, r *http.Request) {
w.Header().Set("content-type", "text/plain; charset=utf8") // "text/plain" for security until you use html/template to safely escape HTML output
io.WriteString(w, "Home App")
return
}
/**
* This should be inside of a "muxtester" directory
* To test: cd into "muxtester" directory. "go test"
* Note: tests require that you are already running "main.go" (which runs on "http://localhost:8080")
*/
package muxtester
import(
// "log"
"io/ioutil"
"net/http"
"testing"
)
/**
* Assuming you are running your Go HTTP server code HTTP port 8080 (common testing port since ports less than 1024 require admin on some systems)
* @see http://golang.org/src/pkg/net/http/serve_test.go#L162
*/
var vtests = []struct {
url string
expected string
}{
{"http://localhost:8080/", "Home App"}, // trivial case
{"http://localhost:8080/en_US/", "Home App"}, // locale-only
{"http://localhost:8080/en_US/meh", "Home App"}, // catchall since no other pattern matches this URI
{"http://localhost:8080/en_US/user", "User App"}, // expected
{"http://localhost:8080/en_US/user/", "User App"}, // expected. The default Mux behavior is to 301 from "/user/" to "/user"
{"http://localhost:8080/en_US/user/username/1", "User App"}, // expected
{"http://localhost:8080/en_US/auth", "Auth App"}, // expected
{"http://localhost:8080/en_US/auth/logout", "Auth App"}, // expected
}
func startServer() {
http.HandleFunc("/", HandleCatchall)
http.ListenAndServe("localhost:8080", nil)
}
/**
*
*/
func TestRequest(t *testing.T) {
// log.Printf("vtests: %s;\n", vtests)
for _, thisTest := range vtests {
// log.Printf("thisTest: %s;\n", thisTest)
url, expectedBody := thisTest.url, thisTest.expected
// log.Printf("url: %s; expectedBody: %s;\n", url, expectedBody)
r, err := http.Get(url)
// log.Printf("r: %s; err: %s;\n", r, err)
if err != nil {
t.Errorf("Get(%s) failed", url)
continue
}
defer r.Body.Close()
gotBody, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Errorf("Reading the Body of (%s) failed", url)
continue
}
// log.Printf("gotBody (%s) == expectedBody (%s);\n", gotBody, expectedBody)
if string(gotBody) != expectedBody {
t.Errorf("Get(%s) = %s, want %s", url, string(gotBody), expectedBody)
continue
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment