|
5 | 5 | package mux
|
6 | 6 |
|
7 | 7 | import (
|
| 8 | + "bufio" |
| 9 | + "bytes" |
8 | 10 | "errors"
|
9 | 11 | "fmt"
|
10 | 12 | "net/http"
|
@@ -280,6 +282,16 @@ func TestPath(t *testing.T) {
|
280 | 282 | pathTemplate: `/111`,
|
281 | 283 | shouldMatch: false,
|
282 | 284 | },
|
| 285 | + { |
| 286 | + title: "Path route, match root with no host", |
| 287 | + route: new(Route).Path("/"), |
| 288 | + request: newRequest("GET", "/"), |
| 289 | + vars: map[string]string{}, |
| 290 | + host: "", |
| 291 | + path: "/", |
| 292 | + pathTemplate: `/`, |
| 293 | + shouldMatch: true, |
| 294 | + }, |
283 | 295 | {
|
284 | 296 | title: "Path route, wrong path in request in request URL",
|
285 | 297 | route: new(Route).Path("/111/222/333"),
|
@@ -309,6 +321,16 @@ func TestPath(t *testing.T) {
|
309 | 321 | pathTemplate: `/111/{v1:[0-9]{3}}/333`,
|
310 | 322 | shouldMatch: false,
|
311 | 323 | },
|
| 324 | + { |
| 325 | + title: "Path route, URL with encoded slash does match", |
| 326 | + route: new(Route).Path("/v1/{v1}/v2"), |
| 327 | + request: newRequest("GET", "http://localhost/v1/1%2F2/v2"), |
| 328 | + vars: map[string]string{"v1": "1%2F2"}, |
| 329 | + host: "", |
| 330 | + path: "/v1/1%2F2/v2", |
| 331 | + pathTemplate: `/v1/{v1}/v2`, |
| 332 | + shouldMatch: true, |
| 333 | + }, |
312 | 334 | {
|
313 | 335 | title: "Path route with multiple patterns, match",
|
314 | 336 | route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"),
|
@@ -1466,11 +1488,42 @@ func stringMapEqual(m1, m2 map[string]string) bool {
|
1466 | 1488 | return true
|
1467 | 1489 | }
|
1468 | 1490 |
|
1469 |
| -// newRequest is a helper function to create a new request with a method and url |
| 1491 | +// newRequest is a helper function to create a new request with a method and url. |
| 1492 | +// The request returned is a 'server' request as opposed to a 'client' one through |
| 1493 | +// simulated write onto the wire and read off of the wire. |
| 1494 | +// The differences between requests are detailed in the net/http package. |
1470 | 1495 | func newRequest(method, url string) *http.Request {
|
1471 | 1496 | req, err := http.NewRequest(method, url, nil)
|
1472 | 1497 | if err != nil {
|
1473 | 1498 | panic(err)
|
1474 | 1499 | }
|
| 1500 | + // extract the escaped original host+path from url |
| 1501 | + // http://localhost/path/here?v=1#frag -> //localhost/path/here |
| 1502 | + opaque := "" |
| 1503 | + if i := len(req.URL.Scheme); i > 0 { |
| 1504 | + opaque = url[i+1:] |
| 1505 | + } |
| 1506 | + |
| 1507 | + if i := strings.LastIndex(opaque, "?"); i > -1 { |
| 1508 | + opaque = opaque[:i] |
| 1509 | + } |
| 1510 | + if i := strings.LastIndex(opaque, "#"); i > -1 { |
| 1511 | + opaque = opaque[:i] |
| 1512 | + } |
| 1513 | + |
| 1514 | + // Escaped host+path workaround as detailed in https://golang.org/pkg/net/url/#URL |
| 1515 | + // for < 1.5 client side workaround |
| 1516 | + req.URL.Opaque = opaque |
| 1517 | + |
| 1518 | + // Simulate writing to wire |
| 1519 | + var buff bytes.Buffer |
| 1520 | + req.Write(&buff) |
| 1521 | + ioreader := bufio.NewReader(&buff) |
| 1522 | + |
| 1523 | + // Parse request off of 'wire' |
| 1524 | + req, err = http.ReadRequest(ioreader) |
| 1525 | + if err != nil { |
| 1526 | + panic(err) |
| 1527 | + } |
1475 | 1528 | return req
|
1476 | 1529 | }
|
0 commit comments