diff --git a/.travis.yml b/.travis.yml index 03a9d4fb..010b9e03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,7 @@ install: - go get github.com/beego/x2j - go get github.com/couchbase/go-couchbase - go get github.com/beego/goyaml2 + - go get gopkg.in/yaml.v2 - go get github.com/belogik/goes - go get github.com/siddontang/ledisdb/config - go get github.com/siddontang/ledisdb/ledis diff --git a/context/input.go b/context/input.go index 168c709a..81952158 100644 --- a/context/input.go +++ b/context/input.go @@ -37,6 +37,7 @@ var ( acceptsHTMLRegex = regexp.MustCompile(`(text/html|application/xhtml\+xml)(?:,|$)`) acceptsXMLRegex = regexp.MustCompile(`(application/xml|text/xml)(?:,|$)`) acceptsJSONRegex = regexp.MustCompile(`(application/json)(?:,|$)`) + acceptsYAMLRegex = regexp.MustCompile(`(application/x-yaml)(?:,|$)`) maxParam = 50 ) @@ -203,6 +204,10 @@ func (input *BeegoInput) AcceptsXML() bool { func (input *BeegoInput) AcceptsJSON() bool { return acceptsJSONRegex.MatchString(input.Header("Accept")) } +// AcceptsYAML Checks if request accepts json response +func (input *BeegoInput) AcceptsYAML() bool { + return acceptsYAMLRegex.MatchString(input.Header("Accept")) +} // IP returns request client ip. // if in proxy, return first proxy id. diff --git a/context/output.go b/context/output.go index d013b652..3cc6044e 100644 --- a/context/output.go +++ b/context/output.go @@ -30,6 +30,7 @@ import ( "strconv" "strings" "time" + "gopkg.in/yaml.v2" ) // BeegoOutput does work for sending response header. @@ -202,6 +203,20 @@ func (output *BeegoOutput) JSON(data interface{}, hasIndent bool, encoding bool) return output.Body(content) } + +// YAML writes yaml to response body. +func (output *BeegoOutput) YAML(data interface{}) error { + output.Header("Content-Type", "application/application/x-yaml; charset=utf-8") + var content []byte + var err error + content, err = yaml.Marshal(data) + if err != nil { + http.Error(output.Context.ResponseWriter, err.Error(), http.StatusInternalServerError) + return err + } + return output.Body(content) +} + // JSONP writes jsonp to response body. func (output *BeegoOutput) JSONP(data interface{}, hasIndent bool) error { output.Header("Content-Type", "application/javascript; charset=utf-8") diff --git a/controller.go b/controller.go index c375760d..c53889a6 100644 --- a/controller.go +++ b/controller.go @@ -36,6 +36,7 @@ import ( const ( applicationJSON = "application/json" applicationXML = "application/xml" + applicationYAML = "application/x-yaml" textXML = "text/xml" ) @@ -362,6 +363,11 @@ func (c *Controller) ServeXML() { c.Ctx.Output.XML(c.Data["xml"], hasIndent) } +// ServeXML sends xml response. +func (c *Controller) ServeYAML() { + c.Ctx.Output.YAML(c.Data["yaml"]) +} + // ServeFormatted serve Xml OR Json, depending on the value of the Accept header func (c *Controller) ServeFormatted() { accept := c.Ctx.Input.Header("Accept") @@ -370,6 +376,8 @@ func (c *Controller) ServeFormatted() { c.ServeJSON() case applicationXML, textXML: c.ServeXML() + case applicationYAML: + c.ServeYAML() default: c.ServeJSON() } diff --git a/httplib/httplib.go b/httplib/httplib.go index 47464e13..074cf661 100644 --- a/httplib/httplib.go +++ b/httplib/httplib.go @@ -50,6 +50,7 @@ import ( "strings" "sync" "time" + "gopkg.in/yaml.v2" ) var defaultSetting = BeegoHTTPSettings{ @@ -332,6 +333,20 @@ func (b *BeegoHTTPRequest) XMLBody(obj interface{}) (*BeegoHTTPRequest, error) { return b, nil } +// YAMLBody adds request raw body encoding by YAML. +func (b *BeegoHTTPRequest) YAMLBody(obj interface{}) (*BeegoHTTPRequest, error) { + if b.req.Body == nil && obj != nil { + byts, err := yaml.Marshal(obj) + if err != nil { + return b, err + } + b.req.Body = ioutil.NopCloser(bytes.NewReader(byts)) + b.req.ContentLength = int64(len(byts)) + b.req.Header.Set("Content-Type", "application/x+yaml") + } + return b, nil +} + // JSONBody adds request raw body encoding by JSON. func (b *BeegoHTTPRequest) JSONBody(obj interface{}) (*BeegoHTTPRequest, error) { if b.req.Body == nil && obj != nil { @@ -431,12 +446,12 @@ func (b *BeegoHTTPRequest) DoRequest() (resp *http.Response, err error) { } b.buildURL(paramBody) - url, err := url.Parse(b.url) + urlParsed, err := url.Parse(b.url) if err != nil { return nil, err } - b.req.URL = url + b.req.URL = urlParsed trans := b.setting.Transport @@ -581,6 +596,16 @@ func (b *BeegoHTTPRequest) ToXML(v interface{}) error { return xml.Unmarshal(data, v) } +// ToYAML returns the map that marshals from the body bytes as yaml in response . +// it calls Response inner. +func (b *BeegoHTTPRequest) ToYAML(v interface{}) error { + data, err := b.Bytes() + if err != nil { + return err + } + return yaml.Unmarshal(data, v) +} + // Response executes request client gets response mannually. func (b *BeegoHTTPRequest) Response() (*http.Response, error) { return b.getResponse() diff --git a/router.go b/router.go index 7a33a0c4..2e0cea25 100644 --- a/router.go +++ b/router.go @@ -71,7 +71,7 @@ var ( // these beego.Controller's methods shouldn't reflect to AutoRouter exceptMethod = []string{"Init", "Prepare", "Finish", "Render", "RenderString", "RenderBytes", "Redirect", "Abort", "StopRun", "UrlFor", "ServeJSON", "ServeJSONP", - "ServeXML", "Input", "ParseForm", "GetString", "GetStrings", "GetInt", "GetBool", + "ServeYAML", "ServeXML", "Input", "ParseForm", "GetString", "GetStrings", "GetInt", "GetBool", "GetFloat", "GetFile", "SaveToFile", "StartSession", "SetSession", "GetSession", "DelSession", "SessionRegenerateID", "DestroySession", "IsAjax", "GetSecureCookie", "SetSecureCookie", "XsrfToken", "CheckXsrfCookie", "XsrfFormHtml", diff --git a/router_test.go b/router_test.go index 720b4ca8..90104427 100644 --- a/router_test.go +++ b/router_test.go @@ -695,3 +695,30 @@ func beegoResetParams(ctx *context.Context) { func beegoHandleResetParams(ctx *context.Context) { ctx.ResponseWriter.Header().Set("splat", ctx.Input.Param(":splat")) } + +// YAML +type YAMLController struct { + Controller +} + +func (jc *YAMLController) Prepare() { + jc.Data["yaml"] = "prepare" + jc.ServeYAML() +} + +func (jc *YAMLController) Get() { + jc.Data["Username"] = "astaxie" + jc.Ctx.Output.Body([]byte("ok")) +} + +func TestYAMLPrepare(t *testing.T) { + r, _ := http.NewRequest("GET", "/yaml/list", nil) + w := httptest.NewRecorder() + + handler := NewControllerRegister() + handler.Add("/yaml/list", &YAMLController{}) + handler.ServeHTTP(w, r) + if strings.TrimSpace(w.Body.String()) != "prepare" { + t.Errorf(w.Body.String()) + } +}