From e8b29c9fd18e97a56821e7f80464f80965dc6e71 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 27 Mar 2019 13:34:46 +0800 Subject: [PATCH 1/4] handle trace request --- controller.go | 63 +++++++++++++++++++++++++++++++++++++-------------- router.go | 2 ++ 2 files changed, 48 insertions(+), 17 deletions(-) diff --git a/controller.go b/controller.go index 9c605760..e6ecd12e 100644 --- a/controller.go +++ b/controller.go @@ -27,6 +27,8 @@ import ( "strconv" "strings" + "fmt" + "github.com/astaxie/beego/context" "github.com/astaxie/beego/context/param" "github.com/astaxie/beego/session" @@ -78,24 +80,30 @@ type ControllerComments struct { // ControllerCommentsSlice implements the sort interface type ControllerCommentsSlice []ControllerComments -func (p ControllerCommentsSlice) Len() int { return len(p) } -func (p ControllerCommentsSlice) Less(i, j int) bool { return p[i].Router < p[j].Router } -func (p ControllerCommentsSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } +func (p ControllerCommentsSlice) Len() int { + return len(p) +} +func (p ControllerCommentsSlice) Less(i, j int) bool { + return p[i].Router < p[j].Router +} +func (p ControllerCommentsSlice) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} // Controller defines some basic http request handler operations, such as // http context, template and view, session and xsrf. type Controller struct { - // context data - Ctx *context.Context - Data map[interface{}]interface{} + // context data + Ctx *context.Context + Data map[interface{}]interface{} - // route controller info + // route controller info controllerName string actionName string methodMapping map[string]func() //method:routertree AppController interface{} - // template data + // template data TplName string ViewPath string Layout string @@ -104,13 +112,13 @@ type Controller struct { TplExt string EnableRender bool - // xsrf data - _xsrfToken string - XSRFExpire int - EnableXSRF bool + // xsrf data + _xsrfToken string + XSRFExpire int + EnableXSRF bool - // session - CruSession session.Store + // session + CruSession session.Store } // ControllerInterface is an interface to uniform all controller handler. @@ -124,6 +132,7 @@ type ControllerInterface interface { Head() Patch() Options() + Trace() Finish() Render() error XSRFToken() string @@ -188,6 +197,26 @@ func (c *Controller) Options() { http.Error(c.Ctx.ResponseWriter, "Method Not Allowed", http.StatusMethodNotAllowed) } +// Trace adds a request function to handle Trace request. +// https://tools.ietf.org/html/rfc7231#section-4.3.8 +// The TRACE method requests a remote, application-level loop-back of +// the request message. The final recipient of the request SHOULD +// reflect the message received, excluding some fields described below, +// back to the client as the message body of a 200 (OK) response with a +// Content-Type of "message/http" (Section 8.3.1 of [RFC7230]). +func (c *Controller) Trace() { + ts := func(h http.Header) (hs string) { + for k, v := range h { + hs += fmt.Sprintf("\r\n%s: %s", k, v) + } + return + } + hs := fmt.Sprintf("\r\nTRACE %s %s%s\r\n", c.Ctx.Request.RequestURI, c.Ctx.Request.Proto, ts(c.Ctx.Request.Header)) + c.Ctx.Output.Header("Content-Type", "message/http") + c.Ctx.Output.Header("Content-Length", fmt.Sprint(len(hs))) + c.Ctx.WriteString(hs) +} + // HandlerFunc call function with the name func (c *Controller) HandlerFunc(fnname string) bool { if v, ok := c.methodMapping[fnname]; ok { @@ -342,7 +371,7 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string { return "" } if endpoint[0] == '.' { - return URLFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name()+endpoint, values...) + return URLFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name() + endpoint, values...) } return URLFor(endpoint, values...) } @@ -350,7 +379,7 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string { // ServeJSON sends a json response with encoding charset. func (c *Controller) ServeJSON(encoding ...bool) { var ( - hasIndent = BConfig.RunMode != PROD + hasIndent = BConfig.RunMode != PROD hasEncoding = len(encoding) > 0 && encoding[0] ) @@ -575,7 +604,7 @@ func (c *Controller) SaveToFile(fromfile, tofile string) error { return err } defer file.Close() - f, err := os.OpenFile(tofile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) + f, err := os.OpenFile(tofile, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0666) if err != nil { return err } diff --git a/router.go b/router.go index a9b6f078..c7abe38c 100644 --- a/router.go +++ b/router.go @@ -843,6 +843,8 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) execController.Patch() case http.MethodOptions: execController.Options() + case http.MethodTrace: + execController.Trace() default: if !execController.HandlerFunc(runMethod) { vc := reflect.ValueOf(execController) From 02bead509778356b010c8ef08f1fdee139e44d6f Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 27 Mar 2019 13:40:34 +0800 Subject: [PATCH 2/4] handle trace request must NOT CACHE https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Cache-Control --- controller.go | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/controller.go b/controller.go index e6ecd12e..c1bbb857 100644 --- a/controller.go +++ b/controller.go @@ -93,17 +93,17 @@ func (p ControllerCommentsSlice) Swap(i, j int) { // Controller defines some basic http request handler operations, such as // http context, template and view, session and xsrf. type Controller struct { - // context data - Ctx *context.Context - Data map[interface{}]interface{} + // context data + Ctx *context.Context + Data map[interface{}]interface{} - // route controller info + // route controller info controllerName string actionName string methodMapping map[string]func() //method:routertree AppController interface{} - // template data + // template data TplName string ViewPath string Layout string @@ -112,13 +112,13 @@ type Controller struct { TplExt string EnableRender bool - // xsrf data - _xsrfToken string - XSRFExpire int - EnableXSRF bool + // xsrf data + _xsrfToken string + XSRFExpire int + EnableXSRF bool - // session - CruSession session.Store + // session + CruSession session.Store } // ControllerInterface is an interface to uniform all controller handler. @@ -214,6 +214,7 @@ func (c *Controller) Trace() { hs := fmt.Sprintf("\r\nTRACE %s %s%s\r\n", c.Ctx.Request.RequestURI, c.Ctx.Request.Proto, ts(c.Ctx.Request.Header)) c.Ctx.Output.Header("Content-Type", "message/http") c.Ctx.Output.Header("Content-Length", fmt.Sprint(len(hs))) + c.Ctx.Output.Header("Cache-Control", "no-cache, no-store, must-revalidate") c.Ctx.WriteString(hs) } @@ -371,7 +372,7 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string { return "" } if endpoint[0] == '.' { - return URLFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name() + endpoint, values...) + return URLFor(reflect.Indirect(reflect.ValueOf(c.AppController)).Type().Name()+endpoint, values...) } return URLFor(endpoint, values...) } @@ -379,7 +380,7 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string { // ServeJSON sends a json response with encoding charset. func (c *Controller) ServeJSON(encoding ...bool) { var ( - hasIndent = BConfig.RunMode != PROD + hasIndent = BConfig.RunMode != PROD hasEncoding = len(encoding) > 0 && encoding[0] ) @@ -604,7 +605,7 @@ func (c *Controller) SaveToFile(fromfile, tofile string) error { return err } defer file.Close() - f, err := os.OpenFile(tofile, os.O_WRONLY | os.O_CREATE | os.O_TRUNC, 0666) + f, err := os.OpenFile(tofile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { return err } From 3155f07ccdcdd7d3fc0e5ebcf022e834b7e24688 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 27 Mar 2019 13:43:27 +0800 Subject: [PATCH 3/4] no need to override Trace method. --- controller.go | 1 + 1 file changed, 1 insertion(+) diff --git a/controller.go b/controller.go index c1bbb857..38328c17 100644 --- a/controller.go +++ b/controller.go @@ -198,6 +198,7 @@ func (c *Controller) Options() { } // Trace adds a request function to handle Trace request. +// this method SHOULD NOT be overridden. // https://tools.ietf.org/html/rfc7231#section-4.3.8 // The TRACE method requests a remote, application-level loop-back of // the request message. The final recipient of the request SHOULD From 75b4bc58965a6b3d8172df7b4b5f34904d04b9a9 Mon Sep 17 00:00:00 2001 From: JessonChan Date: Wed, 3 Apr 2019 10:19:09 +0800 Subject: [PATCH 4/4] it's no need to override Trace method. --- controller.go | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/controller.go b/controller.go index 38328c17..0e8853b3 100644 --- a/controller.go +++ b/controller.go @@ -17,6 +17,7 @@ package beego import ( "bytes" "errors" + "fmt" "html/template" "io" "mime/multipart" @@ -27,8 +28,6 @@ import ( "strconv" "strings" - "fmt" - "github.com/astaxie/beego/context" "github.com/astaxie/beego/context/param" "github.com/astaxie/beego/session" @@ -80,15 +79,9 @@ type ControllerComments struct { // ControllerCommentsSlice implements the sort interface type ControllerCommentsSlice []ControllerComments -func (p ControllerCommentsSlice) Len() int { - return len(p) -} -func (p ControllerCommentsSlice) Less(i, j int) bool { - return p[i].Router < p[j].Router -} -func (p ControllerCommentsSlice) Swap(i, j int) { - p[i], p[j] = p[j], p[i] -} +func (p ControllerCommentsSlice) Len() int { return len(p) } +func (p ControllerCommentsSlice) Less(i, j int) bool { return p[i].Router < p[j].Router } +func (p ControllerCommentsSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } // Controller defines some basic http request handler operations, such as // http context, template and view, session and xsrf.