-
-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
new: request processor (see JSON and XML and /_examples/8_bind_req_se…
…nd_res)\n Also: allow more than one methods to be passed on muxie.Methods().Handle/HandleFunc to register the same handler for specific methods
- Loading branch information
Showing
9 changed files
with
358 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/xml" | ||
"fmt" | ||
"net/http" | ||
|
||
"github.com/kataras/muxie" | ||
) | ||
|
||
// Read more at https://golang.org/pkg/encoding/xml | ||
type person struct { | ||
XMLName xml.Name `json:"-" xml:"person"` // element name | ||
Name string `json:"name" xml:"name,attr"` // ,attr for attribute. | ||
Age int `json:"age" xml:"age,attr"` // ,attr attribute. | ||
Description string `json:"description" xml:"description"` // inner element name, value is its body. | ||
} | ||
|
||
func main() { | ||
mux := muxie.NewMux() | ||
mux.PathCorrection = true | ||
|
||
// Read from incoming request. | ||
mux.Handle("/save", muxie.Methods(). | ||
HandleFunc("POST, PUT", func(w http.ResponseWriter, r *http.Request) { | ||
var p person | ||
// muxie.Bind(r, muxie.JSON,...) for JSON. | ||
// You can implement your own Binders by implementing the muxie.Binder interface like the muxie.JSON/XML. | ||
err := muxie.Bind(r, muxie.XML, &p) | ||
if err != nil { | ||
http.Error(w, fmt.Sprintf("unable to read body: %v", err), http.StatusInternalServerError) | ||
return | ||
} | ||
|
||
fmt.Fprintf(w, "Go value of the request body:\n%#+v\n", p) | ||
})) | ||
|
||
// Send a response. | ||
mux.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) { | ||
send := person{Name: "kataras", Age: 25, Description: "software engineer"} | ||
|
||
// muxie.Dispatch(w, muxie.JSON,...) for JSON. | ||
// You can implement your own Dispatchers by implementing the muxie.Dispatcher interface like the muxie.JSON/XML. | ||
err := muxie.Dispatch(w, muxie.XML, send) | ||
if err != nil { | ||
|
||
http.Error(w, fmt.Sprintf("unable to send the value of %#+v. Error: %v", send, err), http.StatusInternalServerError) | ||
return | ||
} | ||
}) | ||
|
||
fmt.Println(`Server started at http://localhost:8080\n | ||
:: How to... | ||
Read from incoming request | ||
request: | ||
POST or PUT: http://localhost:8080/save | ||
request body: | ||
<person name="kataras" age="25"><description>software engineer</description></person> | ||
request header: | ||
"Content-Type": "text/xml" | ||
response: | ||
Go value of the request body: | ||
main.person{XMLName:xml.Name{Space:"", Local:"person"}, Name:"kataras", Age:25, Description:"software engineer"} | ||
Send a response | ||
request: | ||
GET: http://localhost:8080/get | ||
response header: | ||
"Content-Type": "text/xml; charset=utf-8" (can be modified by muxie.Charset variable) | ||
response: | ||
<person name="kataras" age="25"> | ||
<description>software engineer</description> | ||
</person>`) | ||
http.ListenAndServe(":8080", mux) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
package muxie | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"encoding/xml" | ||
"io/ioutil" | ||
"net/http" | ||
) | ||
|
||
var ( | ||
Charset = "utf-8" | ||
|
||
JSON = &jsonProcessor{Prefix: nil, Indent: "", UnescapeHTML: false} | ||
XML = &xmlProcessor{Indent: ""} | ||
) | ||
|
||
func withCharset(cType string) string { | ||
return cType + "; charset=" + Charset | ||
} | ||
|
||
type Binder interface { | ||
Bind(*http.Request, interface{}) error | ||
} | ||
|
||
func Bind(r *http.Request, b Binder, ptrOut interface{}) error { | ||
return b.Bind(r, ptrOut) | ||
} | ||
|
||
type Dispatcher interface { | ||
// no io.Writer because we need to set the headers here, | ||
// Binder and Processor are only for HTTP. | ||
Dispatch(http.ResponseWriter, interface{}) error | ||
} | ||
|
||
func Dispatch(w http.ResponseWriter, d Dispatcher, v interface{}) error { | ||
return d.Dispatch(w, v) | ||
} | ||
|
||
type Processor interface { | ||
Binder | ||
Dispatcher | ||
} | ||
|
||
var ( | ||
newLineB byte = '\n' | ||
// the html codes for unescaping | ||
ltHex = []byte("\\u003c") | ||
lt = []byte("<") | ||
|
||
gtHex = []byte("\\u003e") | ||
gt = []byte(">") | ||
|
||
andHex = []byte("\\u0026") | ||
and = []byte("&") | ||
) | ||
|
||
type jsonProcessor struct { | ||
Prefix []byte | ||
Indent string | ||
UnescapeHTML bool | ||
} | ||
|
||
var _ Processor = (*jsonProcessor)(nil) | ||
|
||
func (p *jsonProcessor) Bind(r *http.Request, v interface{}) error { | ||
b, err := ioutil.ReadAll(r.Body) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return json.Unmarshal(b, v) | ||
} | ||
|
||
func (p *jsonProcessor) Dispatch(w http.ResponseWriter, v interface{}) error { | ||
var ( | ||
result []byte | ||
err error | ||
) | ||
|
||
if indent := p.Indent; indent != "" { | ||
marshalIndent := json.MarshalIndent | ||
|
||
result, err = marshalIndent(v, "", indent) | ||
result = append(result, newLineB) | ||
} else { | ||
marshal := json.Marshal | ||
result, err = marshal(v) | ||
} | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
if p.UnescapeHTML { | ||
result = bytes.Replace(result, ltHex, lt, -1) | ||
result = bytes.Replace(result, gtHex, gt, -1) | ||
result = bytes.Replace(result, andHex, and, -1) | ||
} | ||
|
||
if len(p.Prefix) > 0 { | ||
result = append([]byte(p.Prefix), result...) | ||
} | ||
|
||
w.Header().Set("Content-Type", withCharset("application/json")) | ||
_, err = w.Write(result) | ||
return err | ||
} | ||
|
||
type xmlProcessor struct { | ||
Indent string | ||
} | ||
|
||
var _ Processor = (*xmlProcessor)(nil) | ||
|
||
func (p *xmlProcessor) Bind(r *http.Request, v interface{}) error { | ||
b, err := ioutil.ReadAll(r.Body) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return xml.Unmarshal(b, v) | ||
} | ||
|
||
func (p *xmlProcessor) Dispatch(w http.ResponseWriter, v interface{}) error { | ||
var ( | ||
result []byte | ||
err error | ||
) | ||
|
||
if indent := p.Indent; indent != "" { | ||
marshalIndent := xml.MarshalIndent | ||
|
||
result, err = marshalIndent(v, "", indent) | ||
result = append(result, newLineB) | ||
} else { | ||
marshal := xml.Marshal | ||
result, err = marshal(v) | ||
} | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
w.Header().Set("Content-Type", withCharset("text/xml")) | ||
_, err = w.Write(result) | ||
return err | ||
} |
Oops, something went wrong.