Skip to content

Instantly share code, notes, and snippets.

@xeoncross
Created July 23, 2019 02:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xeoncross/f4657c6cce00ccf0d40e358de762905e to your computer and use it in GitHub Desktop.
Save xeoncross/f4657c6cce00ccf0d40e358de762905e to your computer and use it in GitHub Desktop.
Example of wrapping both Gorilla/Mux and httprouter while keeping route params in golang
package main
import (
"net/http"
"reflect"
"github.com/gorilla/mux"
"github.com/julienschmidt/httprouter"
)
func WrapHTTPRouter() func(interface{}) httprouter.Handle {
return func(function interface{}) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
get := func(name string) string {
return ps.ByName(name)
}
Wrap(function, w, r, get)
}
}
}
func WrapGorillaMux() func(interface{}) http.HandlerFunc {
return func(function interface{}) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
params := mux.Vars(r)
get := func(name string) string {
if param, ok := params[name]; ok {
return param
}
return ""
}
Wrap(function, w, r, get)
}
}
}
type DemoObject struct {
Name string
}
func Wrap(function interface{}, w http.ResponseWriter, r *http.Request, params func(string) string) {
object := DemoObject{params("name")}
funcValue := reflect.ValueOf(function)
in := []reflect.Value{
reflect.ValueOf(w),
reflect.ValueOf(r),
reflect.ValueOf(object),
}
funcValue.Call(in)
}
func main() {
}
package main
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/gorilla/mux"
"github.com/julienschmidt/httprouter"
)
func TestGorilla(t *testing.T) {
var req *http.Request
// Service we will be wrapping
controller := func(w http.ResponseWriter, r *http.Request, in struct{ Name string }) {
w.Write([]byte(in.Name))
}
// Create HTTP mux/router
// mux := httprouter.New()
router := mux.NewRouter()
// wrapper := WrapHTTPRouter()
wrapper := WrapGorillaMux()
// Our route
// router.GET("/:name", wrapper(controller))
router.HandleFunc("/{name}", wrapper(controller))
req, err := http.NewRequest("GET", "/john", nil)
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
router.ServeHTTP(rr, req)
if status := rr.Code; status != http.StatusOK {
t.Errorf("Wrong status code: got %v want %v", status, http.StatusOK)
}
response := strings.TrimSpace(rr.Body.String())
want := `john`
if response != want {
t.Errorf("Wrong response:\ngot %s\nwant %s", response, want)
}
}
func TestHTTPRouter(t *testing.T) {
var req *http.Request
// Service we will be wrapping
controller := func(w http.ResponseWriter, r *http.Request, in struct{ Name string }) {
w.Write([]byte(in.Name))
}
// Create HTTP mux/router
router := httprouter.New()
wrapper := WrapHTTPRouter()
// Our route
router.GET("/:name", wrapper(controller))
req, err := http.NewRequest("GET", "/john", nil)
if err != nil {
t.Fatal(err)
}
rr := httptest.NewRecorder()
router.ServeHTTP(rr, req)
if status := rr.Code; status != http.StatusOK {
t.Errorf("Wrong status code: got %v want %v", status, http.StatusOK)
}
response := strings.TrimSpace(rr.Body.String())
want := `john`
if response != want {
t.Errorf("Wrong response:\ngot %s\nwant %s", response, want)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment