123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- package util
- import (
- "compress/gzip"
- "context"
- "crypto/x509"
- "encoding/json"
- "encoding/xml"
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "net"
- "net/http"
- "os"
- "os/signal"
- "syscall"
- "time"
- "crypto/tls"
- )
- const (
- // RequestTimeOut http request timeout (second)
- RequestTimeOut = 30
- )
- // RouterHandler hander
- type RouterHandler struct {
- Method string
- Router string
- Hander http.Handler
- }
- // Message HTTP response
- type Message struct {
- StatusCode int
- Body []byte
- Header http.Header
- Cookies []*http.Cookie
- }
- func header(w io.Writer, contentType string) {
- w.(http.ResponseWriter).Header().Set(`Content-Type`, contentType)
- w.(http.ResponseWriter).Header().Set(`X-Powered-By`, LibName+`/`+LibVersion)
- w.(http.ResponseWriter).WriteHeader(http.StatusOK)
- }
- // Redirect redirect
- func Redirect(w http.ResponseWriter, url string) {
- w.Header().Set(`Location`, url)
- w.WriteHeader(http.StatusFound)
- }
- // GetRealIP get real IP from Request
- func GetRealIP(req *http.Request) (ip string) {
- if ips := req.Header["X-Real-Ip"]; ips != nil {
- ip = ips[0]
- }
- return
- }
- // WriteJSON response JSON data.
- func WriteJSON(w io.Writer, response interface{}) error {
- header(w, `application/json; charset=utf-8`)
- return json.NewEncoder(w).Encode(response)
- }
- // WriteXML response XML data.
- func WriteXML(w http.ResponseWriter, response interface{}) error {
- header(w, `application/xml; charset=utf-8`)
- return xml.NewEncoder(w).Encode(response)
- }
- // WriteBytes response bytes
- func WriteBytes(w http.ResponseWriter, response interface{}) error {
- header(w, `text/html; charset=utf-8`)
- w.Write(response.([]byte))
- return nil
- }
- // WriteBytesContentType response bytes and Content-Type
- func WriteBytesContentType(w http.ResponseWriter, response interface{}, contentType string) error {
- header(w, contentType)
- w.Write(response.([]byte))
- return nil
- }
- // WriteCtxJSON response JSON data.
- func WriteCtxJSON(ctx context.Context, w http.ResponseWriter, response interface{}) error {
- return WriteJSON(w, response)
- }
- // WriteCtxXML response XML data.
- func WriteCtxXML(ctx context.Context, w http.ResponseWriter, response interface{}) error {
- return WriteXML(w, response)
- }
- // WriteCtxBytes response text data.
- func WriteCtxBytes(ctx context.Context, w http.ResponseWriter, response interface{}) error {
- return WriteBytes(w, response)
- }
- // ResponseJSON reply JSON
- func ResponseJSON(reply *ReplyData, err error, req *http.Request, w http.ResponseWriter) error {
- if err != nil {
- return WriteJSON(w, ErrReplyData(ErrException, err.Error()))
- }
- return WriteJSON(w, reply)
- }
- // HTTPListenAndServe new server and start
- func HTTPListenAndServe(addr string, router http.Handler) {
- server := &http.Server{
- Addr: addr,
- Handler: router,
- ReadTimeout: 30 * time.Second,
- WriteTimeout: 30 * time.Second,
- MaxHeaderBytes: 1 << 20,
- }
- // Interrupt handler.
- errc := make(chan error)
- go func() {
- c := make(chan os.Signal)
- signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
- errc <- fmt.Errorf("%s", <-c)
- }()
- // HTTP transport.
- go func() {
- log.Println("HTTP Server listen on", addr)
- //logger.Log("Protocol", "HTTP", "addr", addr)
- errc <- server.ListenAndServe()
- log.Println("Exit HTTP server", "Quit")
- }()
- // Run!
- log.Println("Exit", <-errc)
- }
- // newHTTPRequest http request
- func newHTTPRequest(method, uri, certPath, keyPath string, header map[string]string, cookies []*http.Cookie, body io.Reader) (res *http.Response, err error) {
- t := &http.Transport{
- Dial: func(netw, addr string) (net.Conn, error) {
- conn, err := net.DialTimeout(netw, addr, time.Second*RequestTimeOut)
- if err != nil {
- return nil, err
- }
- conn.SetDeadline(time.Now().Add(time.Second * RequestTimeOut))
- return conn, nil
- },
- ResponseHeaderTimeout: time.Second * RequestTimeOut,
- }
- if certPath != "" {
- cert, e := tls.LoadX509KeyPair(certPath, keyPath)
- if e != nil {
- t.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
- } else {
- pool := x509.NewCertPool()
- t.TLSClientConfig = &tls.Config{InsecureSkipVerify: true, Certificates: []tls.Certificate{cert}, RootCAs: pool}
- }
- }
- client := &http.Client{Transport: t}
- var (
- req *http.Request
- )
- if cookies != nil {
- }
- if body != nil {
- req, err = http.NewRequest(method, uri, body)
- } else {
- req, err = http.NewRequest(method, uri, nil)
- }
- if err != nil {
- return
- }
- for k := range header {
- req.Header.Add(k, header[k])
- }
- res, err = client.Do(req)
- return
- }
- func readBody(res *http.Response) (msg Message, err error) {
- var (
- body []byte
- reader io.Reader
- )
- encoding := res.Header.Get("Content-Encoding")
- switch encoding {
- case "gzip":
- reader, err = gzip.NewReader(res.Body)
- if err == nil {
- body, err = ioutil.ReadAll(reader)
- }
- default:
- body, err = ioutil.ReadAll(res.Body)
- }
- if err != nil {
- return
- }
- msg.StatusCode = res.StatusCode
- msg.Header = res.Header
- msg.Body = body
- return
- }
- // Post HTTP request POST
- func Post(uri, certPath, keyPath string, header map[string]string, data io.Reader) (msg Message, err error) {
- var res *http.Response
- if res, err = newHTTPRequest("POST", uri, certPath, keyPath, header, nil, data); err != nil {
- return
- }
- defer res.Body.Close()
- msg, err = readBody(res)
- msg.Cookies = res.Cookies()
- return
- }
- // Get HTTP request GET
- func Get(uri, certPath, keyPath string, header map[string]string) (msg Message, err error) {
- var res *http.Response
- if res, err = newHTTPRequest("GET", uri, certPath, keyPath, header, nil, nil); err != nil {
- return
- }
- defer res.Body.Close()
- msg, err = readBody(res)
- msg.Cookies = res.Cookies()
- return
- }
- // SetCookie set http cookie
- func SetCookie(w http.ResponseWriter, name, value, path string, maxAge int) {
- cookie := &http.Cookie{
- Name: name,
- Value: value,
- Path: path,
- HttpOnly: false,
- MaxAge: maxAge}
- http.SetCookie(w, cookie)
- }
|