Changes to handle multi filters on execution pt
Showing
4 changed files
with
211 additions
and
8 deletions
| ... | @@ -318,9 +318,10 @@ func DelStaticPath(url string) *App { | ... | @@ -318,9 +318,10 @@ func DelStaticPath(url string) *App { |
| 318 | 318 | ||
| 319 | // InsertFilter adds a FilterFunc with pattern condition and action constant. | 319 | // InsertFilter adds a FilterFunc with pattern condition and action constant. |
| 320 | // The pos means action constant including | 320 | // The pos means action constant including |
| 321 | // beego.BeforeRouter, beego.AfterStatic, beego.BeforeExec, beego.AfterExec and beego.FinishRouter. | 321 | // beego.BeforeStatic, beego.BeforeRouter, beego.BeforeExec, beego.AfterExec and beego.FinishRouter. |
| 322 | func InsertFilter(pattern string, pos int, filter FilterFunc) *App { | 322 | // The bool params is for setting the returnOnOutput value (false allows multiple filters to execute) |
| 323 | BeeApp.Handlers.InsertFilter(pattern, pos, filter) | 323 | func InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) *App { |
| 324 | BeeApp.Handlers.InsertFilter(pattern, pos, filter, params...) | ||
| 324 | return BeeApp | 325 | return BeeApp |
| 325 | } | 326 | } |
| 326 | 327 | ... | ... |
| ... | @@ -17,9 +17,10 @@ package beego | ... | @@ -17,9 +17,10 @@ package beego |
| 17 | // FilterRouter defines filter operation before controller handler execution. | 17 | // FilterRouter defines filter operation before controller handler execution. |
| 18 | // it can match patterned url and do filter function when action arrives. | 18 | // it can match patterned url and do filter function when action arrives. |
| 19 | type FilterRouter struct { | 19 | type FilterRouter struct { |
| 20 | filterFunc FilterFunc | 20 | filterFunc FilterFunc |
| 21 | tree *Tree | 21 | tree *Tree |
| 22 | pattern string | 22 | pattern string |
| 23 | returnOnOutput bool | ||
| 23 | } | 24 | } |
| 24 | 25 | ||
| 25 | // ValidRouter check current request is valid for this filter. | 26 | // ValidRouter check current request is valid for this filter. | ... | ... |
| ... | @@ -381,7 +381,9 @@ func (p *ControllerRegistor) AddAutoPrefix(prefix string, c ControllerInterface) | ... | @@ -381,7 +381,9 @@ func (p *ControllerRegistor) AddAutoPrefix(prefix string, c ControllerInterface) |
| 381 | } | 381 | } |
| 382 | 382 | ||
| 383 | // Add a FilterFunc with pattern rule and action constant. | 383 | // Add a FilterFunc with pattern rule and action constant. |
| 384 | func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter FilterFunc) error { | 384 | // The bool params is for setting the returnOnOutput value (false allows multiple filters to execute) |
| 385 | func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) error { | ||
| 386 | |||
| 385 | mr := new(FilterRouter) | 387 | mr := new(FilterRouter) |
| 386 | mr.tree = NewTree() | 388 | mr.tree = NewTree() |
| 387 | mr.pattern = pattern | 389 | mr.pattern = pattern |
| ... | @@ -389,6 +391,11 @@ func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter Filter | ... | @@ -389,6 +391,11 @@ func (p *ControllerRegistor) InsertFilter(pattern string, pos int, filter Filter |
| 389 | if !RouterCaseSensitive { | 391 | if !RouterCaseSensitive { |
| 390 | pattern = strings.ToLower(pattern) | 392 | pattern = strings.ToLower(pattern) |
| 391 | } | 393 | } |
| 394 | if params == nil { | ||
| 395 | mr.returnOnOutput = true | ||
| 396 | } else { | ||
| 397 | mr.returnOnOutput = params[0] | ||
| 398 | } | ||
| 392 | mr.tree.AddRouter(pattern, true) | 399 | mr.tree.AddRouter(pattern, true) |
| 393 | return p.insertFilterRouter(pos, mr) | 400 | return p.insertFilterRouter(pos, mr) |
| 394 | } | 401 | } |
| ... | @@ -587,7 +594,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) | ... | @@ -587,7 +594,7 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request) |
| 587 | if ok, p := filterR.ValidRouter(urlPath); ok { | 594 | if ok, p := filterR.ValidRouter(urlPath); ok { |
| 588 | context.Input.Params = p | 595 | context.Input.Params = p |
| 589 | filterR.filterFunc(context) | 596 | filterR.filterFunc(context) |
| 590 | if w.started { | 597 | if filterR.returnOnOutput && w.started { |
| 591 | return true | 598 | return true |
| 592 | } | 599 | } |
| 593 | } | 600 | } | ... | ... |
| ... | @@ -17,6 +17,7 @@ package beego | ... | @@ -17,6 +17,7 @@ package beego |
| 17 | import ( | 17 | import ( |
| 18 | "net/http" | 18 | "net/http" |
| 19 | "net/http/httptest" | 19 | "net/http/httptest" |
| 20 | "strings" | ||
| 20 | "testing" | 21 | "testing" |
| 21 | 22 | ||
| 22 | "github.com/astaxie/beego/context" | 23 | "github.com/astaxie/beego/context" |
| ... | @@ -385,3 +386,196 @@ func testRequest(method, path string) (*httptest.ResponseRecorder, *http.Request | ... | @@ -385,3 +386,196 @@ func testRequest(method, path string) (*httptest.ResponseRecorder, *http.Request |
| 385 | 386 | ||
| 386 | return recorder, request | 387 | return recorder, request |
| 387 | } | 388 | } |
| 389 | |||
| 390 | // Execution point: BeforeRouter | ||
| 391 | // expectation: only BeforeRouter function is executed, notmatch output as router doesn't handle | ||
| 392 | func TestFilterBeforeRouter(t *testing.T) { | ||
| 393 | testName := "TestFilterBeforeRouter" | ||
| 394 | url := "/beforeRouter" | ||
| 395 | |||
| 396 | mux := NewControllerRegister() | ||
| 397 | mux.InsertFilter(url, BeforeRouter, beegoBeforeRouter1) | ||
| 398 | |||
| 399 | mux.Get(url, beegoFilterFunc) | ||
| 400 | |||
| 401 | rw, r := testRequest("GET", url) | ||
| 402 | mux.ServeHTTP(rw, r) | ||
| 403 | |||
| 404 | if strings.Contains(rw.Body.String(), "BeforeRouter1") == false { | ||
| 405 | t.Errorf(testName + " BeforeRouter did not run") | ||
| 406 | } | ||
| 407 | if strings.Contains(rw.Body.String(), "hello") == true { | ||
| 408 | t.Errorf(testName + " BeforeRouter did not return properly") | ||
| 409 | } | ||
| 410 | } | ||
| 411 | |||
| 412 | // Execution point: BeforeExec | ||
| 413 | // expectation: only BeforeExec function is executed, match as router determines route only | ||
| 414 | func TestFilterBeforeExec(t *testing.T) { | ||
| 415 | testName := "TestFilterBeforeExec" | ||
| 416 | url := "/beforeExec" | ||
| 417 | |||
| 418 | mux := NewControllerRegister() | ||
| 419 | mux.InsertFilter(url, BeforeRouter, beegoFilterNoOutput) | ||
| 420 | mux.InsertFilter(url, BeforeExec, beegoBeforeExec1) | ||
| 421 | |||
| 422 | mux.Get(url, beegoFilterFunc) | ||
| 423 | |||
| 424 | rw, r := testRequest("GET", url) | ||
| 425 | mux.ServeHTTP(rw, r) | ||
| 426 | |||
| 427 | if strings.Contains(rw.Body.String(), "BeforeExec1") == false { | ||
| 428 | t.Errorf(testName + " BeforeExec did not run") | ||
| 429 | } | ||
| 430 | if strings.Contains(rw.Body.String(), "hello") == true { | ||
| 431 | t.Errorf(testName + " BeforeExec did not return properly") | ||
| 432 | } | ||
| 433 | if strings.Contains(rw.Body.String(), "BeforeRouter") == true { | ||
| 434 | t.Errorf(testName + " BeforeRouter ran in error") | ||
| 435 | } | ||
| 436 | } | ||
| 437 | |||
| 438 | // Execution point: AfterExec | ||
| 439 | // expectation: only AfterExec function is executed, match as router handles | ||
| 440 | func TestFilterAfterExec(t *testing.T) { | ||
| 441 | testName := "TestFilterAfterExec" | ||
| 442 | url := "/afterExec" | ||
| 443 | |||
| 444 | mux := NewControllerRegister() | ||
| 445 | mux.InsertFilter(url, BeforeRouter, beegoFilterNoOutput) | ||
| 446 | mux.InsertFilter(url, BeforeExec, beegoFilterNoOutput) | ||
| 447 | mux.InsertFilter(url, AfterExec, beegoAfterExec1) | ||
| 448 | |||
| 449 | mux.Get(url, beegoFilterFunc) | ||
| 450 | |||
| 451 | rw, r := testRequest("GET", url) | ||
| 452 | mux.ServeHTTP(rw, r) | ||
| 453 | |||
| 454 | if strings.Contains(rw.Body.String(), "AfterExec1") == false { | ||
| 455 | t.Errorf(testName + " AfterExec did not run") | ||
| 456 | } | ||
| 457 | if strings.Contains(rw.Body.String(), "hello") == false { | ||
| 458 | t.Errorf(testName + " handler did not run properly") | ||
| 459 | } | ||
| 460 | if strings.Contains(rw.Body.String(), "BeforeRouter") == true { | ||
| 461 | t.Errorf(testName + " BeforeRouter ran in error") | ||
| 462 | } | ||
| 463 | if strings.Contains(rw.Body.String(), "BeforeExec") == true { | ||
| 464 | t.Errorf(testName + " BeforeExec ran in error") | ||
| 465 | } | ||
| 466 | } | ||
| 467 | |||
| 468 | // Execution point: FinishRouter | ||
| 469 | // expectation: only FinishRouter function is executed, match as router handles | ||
| 470 | func TestFilterFinishRouter(t *testing.T) { | ||
| 471 | testName := "TestFilterFinishRouter" | ||
| 472 | url := "/finishRouter" | ||
| 473 | |||
| 474 | mux := NewControllerRegister() | ||
| 475 | mux.InsertFilter(url, BeforeRouter, beegoFilterNoOutput) | ||
| 476 | mux.InsertFilter(url, BeforeExec, beegoFilterNoOutput) | ||
| 477 | mux.InsertFilter(url, AfterExec, beegoFilterNoOutput) | ||
| 478 | mux.InsertFilter(url, FinishRouter, beegoFinishRouter1) | ||
| 479 | |||
| 480 | mux.Get(url, beegoFilterFunc) | ||
| 481 | |||
| 482 | rw, r := testRequest("GET", url) | ||
| 483 | mux.ServeHTTP(rw, r) | ||
| 484 | |||
| 485 | if strings.Contains(rw.Body.String(), "FinishRouter1") == true { | ||
| 486 | t.Errorf(testName + " FinishRouter did not run") | ||
| 487 | } | ||
| 488 | if strings.Contains(rw.Body.String(), "hello") == false { | ||
| 489 | t.Errorf(testName + " handler did not run properly") | ||
| 490 | } | ||
| 491 | if strings.Contains(rw.Body.String(), "AfterExec1") == true { | ||
| 492 | t.Errorf(testName + " AfterExec ran in error") | ||
| 493 | } | ||
| 494 | if strings.Contains(rw.Body.String(), "BeforeRouter") == true { | ||
| 495 | t.Errorf(testName + " BeforeRouter ran in error") | ||
| 496 | } | ||
| 497 | if strings.Contains(rw.Body.String(), "BeforeExec") == true { | ||
| 498 | t.Errorf(testName + " BeforeExec ran in error") | ||
| 499 | } | ||
| 500 | } | ||
| 501 | |||
| 502 | // Execution point: FinishRouter | ||
| 503 | // expectation: only first FinishRouter function is executed, match as router handles | ||
| 504 | func TestFilterFinishRouterMultiFirstOnly(t *testing.T) { | ||
| 505 | testName := "TestFilterFinishRouterMultiFirstOnly" | ||
| 506 | url := "/finishRouterMultiFirstOnly" | ||
| 507 | |||
| 508 | mux := NewControllerRegister() | ||
| 509 | mux.InsertFilter(url, FinishRouter, beegoFinishRouter1) | ||
| 510 | mux.InsertFilter(url, FinishRouter, beegoFinishRouter2) | ||
| 511 | |||
| 512 | mux.Get(url, beegoFilterFunc) | ||
| 513 | |||
| 514 | rw, r := testRequest("GET", url) | ||
| 515 | mux.ServeHTTP(rw, r) | ||
| 516 | |||
| 517 | if strings.Contains(rw.Body.String(), "FinishRouter1") == false { | ||
| 518 | t.Errorf(testName + " FinishRouter1 did not run") | ||
| 519 | } | ||
| 520 | if strings.Contains(rw.Body.String(), "hello") == false { | ||
| 521 | t.Errorf(testName + " handler did not run properly") | ||
| 522 | } | ||
| 523 | // not expected in body | ||
| 524 | if strings.Contains(rw.Body.String(), "FinishRouter2") == true { | ||
| 525 | t.Errorf(testName + " FinishRouter2 did run") | ||
| 526 | } | ||
| 527 | } | ||
| 528 | |||
| 529 | // Execution point: FinishRouter | ||
| 530 | // expectation: both FinishRouter functions execute, match as router handles | ||
| 531 | func TestFilterFinishRouterMulti(t *testing.T) { | ||
| 532 | testName := "TestFilterFinishRouterMulti" | ||
| 533 | url := "/finishRouterMulti" | ||
| 534 | |||
| 535 | mux := NewControllerRegister() | ||
| 536 | mux.InsertFilter(url, FinishRouter, beegoFinishRouter1, false) | ||
| 537 | mux.InsertFilter(url, FinishRouter, beegoFinishRouter2) | ||
| 538 | |||
| 539 | mux.Get(url, beegoFilterFunc) | ||
| 540 | |||
| 541 | rw, r := testRequest("GET", url) | ||
| 542 | mux.ServeHTTP(rw, r) | ||
| 543 | |||
| 544 | if strings.Contains(rw.Body.String(), "FinishRouter1") == false { | ||
| 545 | t.Errorf(testName + " FinishRouter1 did not run") | ||
| 546 | } | ||
| 547 | if strings.Contains(rw.Body.String(), "hello") == false { | ||
| 548 | t.Errorf(testName + " handler did not run properly") | ||
| 549 | } | ||
| 550 | if strings.Contains(rw.Body.String(), "FinishRouter2") == false { | ||
| 551 | t.Errorf(testName + " FinishRouter2 did not run properly") | ||
| 552 | } | ||
| 553 | } | ||
| 554 | |||
| 555 | func beegoFilterNoOutput(ctx *context.Context) { | ||
| 556 | return | ||
| 557 | } | ||
| 558 | func beegoBeforeRouter1(ctx *context.Context) { | ||
| 559 | ctx.WriteString("|BeforeRouter1") | ||
| 560 | } | ||
| 561 | func beegoBeforeRouter2(ctx *context.Context) { | ||
| 562 | ctx.WriteString("|BeforeRouter2") | ||
| 563 | } | ||
| 564 | func beegoBeforeExec1(ctx *context.Context) { | ||
| 565 | ctx.WriteString("|BeforeExec1") | ||
| 566 | } | ||
| 567 | func beegoBeforeExec2(ctx *context.Context) { | ||
| 568 | ctx.WriteString("|BeforeExec2") | ||
| 569 | } | ||
| 570 | func beegoAfterExec1(ctx *context.Context) { | ||
| 571 | ctx.WriteString("|AfterExec1") | ||
| 572 | } | ||
| 573 | func beegoAfterExec2(ctx *context.Context) { | ||
| 574 | ctx.WriteString("|AfterExec2") | ||
| 575 | } | ||
| 576 | func beegoFinishRouter1(ctx *context.Context) { | ||
| 577 | ctx.WriteString("|FinishRouter1") | ||
| 578 | } | ||
| 579 | func beegoFinishRouter2(ctx *context.Context) { | ||
| 580 | ctx.WriteString("|FinishRouter2") | ||
| 581 | } | ... | ... |
-
Please register or sign in to post a comment