Skip to content

Commit

Permalink
Merge branch 'release/3.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
nbari committed Mar 20, 2017
2 parents 2719e69 + 3e227ff commit 502d8b0
Show file tree
Hide file tree
Showing 4 changed files with 325 additions and 11 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,8 @@ In some cases there is a need to pass data across
handlers/middlewares, for doing this **Violetear** uses
[net/context](https://godoc.org/golang.org/x/net/context).
When using dynamic routes `:regex`, you can use `GetParam` or `GetParams`, see below.
Example:
```go
Expand All @@ -480,11 +482,14 @@ func catchAll(w http.ResponseWriter, r *http.Request) {
func handleUUID(w http.ResponseWriter, r *http.Request) {
// get router params
params := r.Context().Value(violetear.ParamsKey).(violetear.Params)
// using GetParam
uuid := violetear.GetParam("uuid", r)
// add a key-value pair to the context
ctx := context.WithValue(r.Context(), "key", "my-value")
// print current value for :uuid
fmt.Fprintf(w, "Named parameter: %q, key: %s",
fmt.Fprintf(w, "Named parameter: %q, uuid; %q, key: %s",
params[":uuid"],
uuid,
ctx.Value("key"),
)
}
Expand Down Expand Up @@ -514,11 +519,16 @@ An slice is created, for getting the values you need to do something like:
> Notice the ``:`` prefix when getting the named_parameters
Or by using `GetParams`:
uuid := violetear.GetParams("uuid")
After this you can access the slice like normal:
fmt.Println(uuid[0], uuid[1])
## Only for go < 1.7
For been available to use the **Context** ``ctx`` you need to do a type assertion:
Expand Down
39 changes: 39 additions & 0 deletions params.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package violetear

import "net/http"

// GetParam returns a value for the parameter set in path
// When having duplicate params pass the index as the last argument to
// retrieve the desired value.
func GetParam(name string, r *http.Request, index ...int) string {
params := r.Context().Value(ParamsKey).(Params)
if param := params[":"+name]; param != nil {
switch param := param.(type) {
case []string:
if len(index) > 0 {
if index[0] > len(param) {
return ""
}
return param[index[0]]
}
return param[0]
default:
return param.(string)
}
}
return ""
}

// GetParams returns param or params in a []string
func GetParams(name string, r *http.Request) []string {
params := r.Context().Value(ParamsKey).(Params)
if param := params[":"+name]; param != nil {
switch param := param.(type) {
case []string:
return param
default:
return []string{param.(string)}
}
}
return []string{}
}
266 changes: 266 additions & 0 deletions params_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
package violetear

import (
"fmt"
"net/http"
"net/http/httptest"
"reflect"
"testing"
)

func TestGetParam(t *testing.T) {
testCases := []struct {
path string
requestPath string
param string
expectedParam string
index int
}{
{
path: "/tests/:test_param",
requestPath: "/tests/abc",
param: "test_param",
expectedParam: "abc",
},
{
path: "/other_test",
requestPath: "/other_test",
param: "foo",
expectedParam: "",
},
{
path: "/other_test",
requestPath: "/other_test",
param: "",
expectedParam: "",
},
{
path: "/test/:ip",
requestPath: "/test/127.0.0.1",
param: "ip",
expectedParam: "127.0.0.1",
},
{
path: "/test/:ip",
requestPath: "/test/127.0.0.1",
param: "ip",
expectedParam: "127.0.0.1",
index: 3,
},
{
path: "/:uuid",
requestPath: "/78F204D2-26D9-409F-BE81-2E5D061E1FA1",
param: "uuid",
expectedParam: "78F204D2-26D9-409F-BE81-2E5D061E1FA1",
},
{
path: "/test/:uuid",
requestPath: "/test/78F204D2-26D9-409F-BE81-2E5D061E1FA1",
param: "uuid",
expectedParam: "78F204D2-26D9-409F-BE81-2E5D061E1FA1",
},
{
path: "/test/:uuid/:uuid",
requestPath: "/test/78F204D2-26D9-409F-BE81-2E5D061E1FA1/33A7B724-1498-4A5A-B29B-AD4E31824234",
param: "uuid",
expectedParam: "78F204D2-26D9-409F-BE81-2E5D061E1FA1",
index: 0,
},
{
path: "/test/:uuid/:uuid",
requestPath: "/test/78F204D2-26D9-409F-BE81-2E5D061E1FA1/33A7B724-1498-4A5A-B29B-AD4E31824234",
param: "uuid",
expectedParam: "33A7B724-1498-4A5A-B29B-AD4E31824234",
index: 1,
},
{
path: "/test/:uuid/:uuid",
requestPath: "/test/78F204D2-26D9-409F-BE81-2E5D061E1FA1/33A7B724-1498-4A5A-B29B-AD4E31824234",
param: "uuid",
expectedParam: "",
index: 2,
},
{
path: "/test/:uuid/:uuid",
requestPath: "/test/78F204D2-26D9-409F-BE81-2E5D061E1FA1/33A7B724-1498-4A5A-B29B-AD4E31824234",
param: "uuid",
expectedParam: "",
index: 3,
},
}

router := New()
for _, v := range dynamicRoutes {
router.AddRegex(v.name, v.regex)
}
router.AddRegex(":test_param", `^\w+$`)

var (
w *httptest.ResponseRecorder
obtainedParam string
)

for _, v := range testCases {
testHandler := func(w http.ResponseWriter, r *http.Request) {
if v.index > 0 {
obtainedParam = GetParam(v.param, r, v.index)
} else {
obtainedParam = GetParam(v.param, r)
}
expect(t, obtainedParam, v.expectedParam)
}
router.HandleFunc(v.path, testHandler, "GET")
w = httptest.NewRecorder()
req, _ := http.NewRequest("GET", v.requestPath, nil)
router.ServeHTTP(w, req)
}
}

func TestGetParams(t *testing.T) {
testCases := []struct {
path string
requestPath string
param string
expectedParam []string
}{
{
path: "/tests/:test_param",
requestPath: "/tests/abc",
param: "test_param",
expectedParam: []string{"abc"},
},
{
path: "/other_test",
requestPath: "/other_test",
param: "foo",
expectedParam: []string{},
},
{
path: "/other_test",
requestPath: "/other_test",
param: "",
expectedParam: []string{},
},
{
path: "/test/:ip",
requestPath: "/test/127.0.0.1",
param: "ip",
expectedParam: []string{"127.0.0.1"},
},
{
path: "/test/:ip",
requestPath: "/test/127.0.0.1",
param: "ip",
expectedParam: []string{"127.0.0.1"},
},
{
path: "/:uuid",
requestPath: "/78F204D2-26D9-409F-BE81-2E5D061E1FA1",
param: "uuid",
expectedParam: []string{"78F204D2-26D9-409F-BE81-2E5D061E1FA1"},
},
{
path: "/test/:uuid",
requestPath: "/test/78F204D2-26D9-409F-BE81-2E5D061E1FA1",
param: "uuid",
expectedParam: []string{"78F204D2-26D9-409F-BE81-2E5D061E1FA1"},
},
{
path: "/test/:uuid/:uuid",
requestPath: "/test/78F204D2-26D9-409F-BE81-2E5D061E1FA1/33A7B724-1498-4A5A-B29B-AD4E31824234",
param: "uuid",
expectedParam: []string{"78F204D2-26D9-409F-BE81-2E5D061E1FA1", "33A7B724-1498-4A5A-B29B-AD4E31824234"},
},
{
path: "/test/:uuid/:uuid:uuid",
requestPath: "/test/479BA626-0565-49CF-8852-9576F6C9964F/479BA626-0565-49CF-8852-9576F6C9964F/479BA626-0565-49CF-8852-9576F6C9964F",
param: "uuid",
expectedParam: []string{"479BA626-0565-49CF-8852-9576F6C9964F", "479BA626-0565-49CF-8852-9576F6C9964F", "479BA626-0565-49CF-8852-9576F6C9964F"},
},
}

router := New()
for _, v := range dynamicRoutes {
router.AddRegex(v.name, v.regex)
}
router.AddRegex(":test_param", `^\w+$`)

var (
w *httptest.ResponseRecorder
obtainedParams []string
)

for _, v := range testCases {
testHandler := func(w http.ResponseWriter, r *http.Request) {
obtainedParams = GetParams(v.param, r)
expect(t, obtainedParams, v.expectedParam)
}
router.HandleFunc(v.path, testHandler, "GET")
w = httptest.NewRecorder()
req, _ := http.NewRequest("GET", v.requestPath, nil)
router.ServeHTTP(w, req)
}
}

func TestGetParamDuplicates(t *testing.T) {
var uuids []string
request := "/test/"
requestHandler := "/test/"
for i := 0; i <= 10; i++ {
uuid := genUUID()
uuids = append(uuids, uuid)
request += fmt.Sprintf("%s/", uuid)
requestHandler += ":uuid/"
}

router := New()

for _, v := range dynamicRoutes {
router.AddRegex(v.name, v.regex)
}

handler := func(w http.ResponseWriter, r *http.Request) {
for i := 0; i <= 10; i++ {
expect(t, GetParam("uuid", r, i), uuids[i])
}
w.Write([]byte("named params"))
}

router.HandleFunc(requestHandler, handler)

w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", request, nil)
router.ServeHTTP(w, req)
expect(t, w.Code, 200)
}

func TestGetParamsDuplicates(t *testing.T) {
var uuids []string
request := "/test/"
requestHandler := "/test/"
for i := 0; i < 10; i++ {
uuid := genUUID()
uuids = append(uuids, uuid)
request += fmt.Sprintf("%s/", uuid)
requestHandler += ":uuid/"
}

router := New()

for _, v := range dynamicRoutes {
router.AddRegex(v.name, v.regex)
}

handler := func(w http.ResponseWriter, r *http.Request) {
p := GetParams("uuid", r)
expect(t, true, (reflect.DeepEqual(p, uuids)))
w.Write([]byte("named params"))
}

router.HandleFunc(requestHandler, handler)

w := httptest.NewRecorder()
req, _ := http.NewRequest("GET", request, nil)
router.ServeHTTP(w, req)
expect(t, w.Code, 200)
}
19 changes: 9 additions & 10 deletions violetear_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ func expectDeepEqual(t *testing.T, a interface{}, b interface{}) {
}
}

func genUUID() string {
b := make([]byte, 16)
_, err := rand.Read(b)
if err != nil {
panic(err)
}
return fmt.Sprintf("%X-%X-%X-%X-%X", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
}

type testRouter struct {
path string
methods string
Expand Down Expand Up @@ -460,15 +469,6 @@ func TestContextNamedParamsSlice(t *testing.T) {
}

func TestContextManyNamedParamsSlice(t *testing.T) {
genUUID := func() string {
b := make([]byte, 16)
_, err := rand.Read(b)
if err != nil {
t.Fatal(err)
}
return fmt.Sprintf("%X-%X-%X-%X-%X", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
}

var uuids []string
request := "/test/"
requestHandler := "/test/"
Expand Down Expand Up @@ -607,5 +607,4 @@ func TestVersioning(t *testing.T) {
req.Header.Set("Accept", "application/vnd.violetear.v2")
router.ServeHTTP(w, req)
expect(t, w.Body.String(), "* v2")

}

0 comments on commit 502d8b0

Please sign in to comment.