Documentation ¶
Overview ¶
Author: recallsong
Email: songruiguo@qq.com
Description: httpc是一个简单的发起http请求的客户端库
Index ¶
- Constants
- Variables
- func MustBeCalledForCbAfterSend(callbacks ...Callback)
- func MustBeCalledForCbBeforeSend(callbacks ...Callback)
- type BodyReaders
- type Callback
- type Context
- func (c *Context) AddCbAfterSend(cb Callback) *Context
- func (c *Context) AddCbBeforeSend(cb Callback) *Context
- func (c *Context) AddCbOnError(cb Callback) *Context
- func (c *Context) AddCbOnRetring(cb Callback) *Context
- func (c *Context) Copy() *Context
- func (c *Context) EnableCookie(enable bool) *Context
- func (c *Context) SetCheckRedirect(cr func(req *http.Request, via []*http.Request) error) *Context
- func (c *Context) SetClient(client *http.Client) *Context
- func (c *Context) SetConnectReadTimeout(connectTimeout time.Duration, readTimeout time.Duration) *Context
- func (c *Context) SetProxy(proxy func(*http.Request) (*url.URL, error)) *Context
- func (c *Context) SetRetryConfig(retries int, interval time.Duration, factor float64) *Context
- func (c *Context) SetTLSClientConfig(config *tls.Config) *Context
- func (c *Context) SetTotalTimeout(timeout time.Duration) *Context
- type FilePath
- type HttpC
- func (c *HttpC) AddCookie(ck *http.Cookie) *HttpC
- func (c *HttpC) AddHeader(key, value string) *HttpC
- func (c *HttpC) BasicAuth(userName, password string) *HttpC
- func (c *HttpC) Body(body interface{}, mediaType ...string) *HttpC
- func (c *HttpC) ContentType(value string) *HttpC
- func (c *HttpC) Delete(out interface{}, mediaType ...string) error
- func (c *HttpC) DumpRequest(dumpBody ...bool) string
- func (c *HttpC) DumpResponse(dumpBody ...bool) string
- func (c *HttpC) EscapedPath(path interface{}) *HttpC
- func (c *HttpC) Get(out interface{}, mediaType ...string) error
- func (c *HttpC) Header(key, value string) *HttpC
- func (c *HttpC) Options(out interface{}, mediaType ...string) error
- func (c *HttpC) Patch(out interface{}, mediaType ...string) error
- func (c *HttpC) Path(path string) *HttpC
- func (c *HttpC) Post(out interface{}, mediaType ...string) error
- func (c *HttpC) Put(out interface{}, mediaType ...string) error
- func (c *HttpC) Query(name, value string) *HttpC
- func (c *HttpC) Reset() *HttpC
- func (c *HttpC) SetContext(context *Context) *HttpC
- func (c *HttpC) String() string
- func (c *HttpC) SuccessStatus(sucStatus int) *HttpC
- type ReqBodyReader
- type RespBodyReader
- type SaveInfo
Examples ¶
Constants ¶
const ( POST = "POST" GET = "GET" HEAD = "HEAD" PUT = "PUT" DELETE = "DELETE" PATCH = "PATCH" OPTIONS = "OPTIONS" )
支持的HTTP method
const ( TypeTextHtml = "text/html" TypeTextPlain = "text/plain" TypeApplicationJson = "application/json" TypeApplicationXml = "application/xml" TypeApplicationForm = "application/x-www-form-urlencoded" TypeApplicationStream = "application/octet-stream" TypeMultipartFormData = "multipart/form-data" )
支持的ContentType类型
Variables ¶
var DefaultContext = NewContext()
DefaultContext 默认的请求上下文
var ( // ErrReqBodyType 请求的Body数据类型错误 ErrReqBodyType = errors.New("invalid request body type") )
var ( // ErrRespOutType 接收响应Body的数据类型错误 ErrRespOutType = errors.New("invalid response output type") )
var GlobalReqBodyMediaReaders = map[string]ReqBodyReader{
TypeApplicationJson: jsonReqBodyReader,
TypeApplicationXml: xmlReqBodyReader,
TypeApplicationForm: formValuesReqBodyReader,
TypeMultipartFormData: multipartReqBodyReader,
}
GlobalReqBodyMediaReaders 默认的根据MediaType获取RequestBody的Reader映射
var GlobalReqBodyTypeReaders = map[reflect.Type]ReqBodyReader{ reflect.TypeOf(""): stringReqBodyReader, reflect.TypeOf([]byte(nil)): bytesReqBodyReader, reflect.TypeOf(url.Values(nil)): urlValuesReqBodyReader, }
GlobalReqBodyTypeReaders 默认的根据类型获取RequestBody的Reader映射
var GlobalRespBodyMediaReaders = map[string]RespBodyReader{
TypeApplicationJson: readAllRespWrapper(jsonRespBodyReader),
TypeApplicationXml: readAllRespWrapper(xmlRespBodyReader),
TypeApplicationStream: streamRespBodyReader,
}
GlobalRespBodyMediaReaders 默认的根据MediaType获取ResponseBody的Reader映射
var GlobalRespBodyTypeReaders = map[reflect.Type]RespBodyReader{ reflect.TypeOf((*string)(nil)): readAllRespWrapper(stringRespBodyReader), reflect.TypeOf((*[]byte)(nil)): readAllRespWrapper(bytesRespBodyReader), reflect.TypeOf((**http.Response)(nil)): responseReader, reflect.TypeOf((FilePath)("")): downloadRespBodyReader, reflect.TypeOf((*SaveInfo)(nil)): downloadRespBodyReader, reflect.TypeOf(SaveInfo{}): downloadRespBodyReader, }
GlobalRespBodyTypeReaders 默认的根据类型获取ResponseBody的Reader映射
Functions ¶
func MustBeCalledForCbAfterSend ¶ added in v0.1.5
func MustBeCalledForCbAfterSend(callbacks ...Callback)
func MustBeCalledForCbBeforeSend ¶ added in v0.1.5
func MustBeCalledForCbBeforeSend(callbacks ...Callback)
Types ¶
type BodyReaders ¶
type BodyReaders struct { ReqBodyTypeReaders map[reflect.Type]ReqBodyReader // 根据类型获取reader ReqBodyMediaReaders map[string]ReqBodyReader // 根据MediaType获取reader RespBodyTypeReaders map[reflect.Type]RespBodyReader // 根据类型获取reader RespBodyMediaReaders map[string]RespBodyReader // 根据MediaType获取reader }
BodyReaders 请求体读取器
type Context ¶
type Context struct { Client *http.Client // 请求的客户端 BodyReaders *BodyReaders // 获取请求和响应中的body的reader CbBeforeSend []Callback // 在发送请求前调用 CbAfterSend []Callback // 在发送请求后调用 CbOnError []Callback // 在发生错误时调用 CbOnRetring []Callback // 在请求重试时调用 Retries int // 重试次数,-1表示一直重试 RetryInterval time.Duration // 重试间隔 RetryFactor float64 // 重试因子,影响每次重试的时间间隔 }
Context http请求上下文,管理所有请求公用的对象
func (*Context) AddCbAfterSend ¶
AddCbAfterSend 添加发送请求后的通知回调函数
func (*Context) AddCbBeforeSend ¶
AddCbBeforeSend 添加发送请求前的通知回调函数
func (*Context) AddCbOnError ¶
AddCbOnError 添加发生错误时的通知回调函数
func (*Context) AddCbOnRetring ¶
AddCbOnRetring 添加请求重试的通知回调函数
func (*Context) EnableCookie ¶
EnableCookie 启用CookieJar
func (*Context) SetCheckRedirect ¶
SetCheckRedirect 设置CheckRedirect
func (*Context) SetConnectReadTimeout ¶
func (c *Context) SetConnectReadTimeout(connectTimeout time.Duration, readTimeout time.Duration) *Context
SetConnectReadTimeout 设置请求的连接超时和读数据超时
func (*Context) SetRetryConfig ¶
SetRetryConfig 设置重试的配置
func (*Context) SetTLSClientConfig ¶
SetTLSClientConfig 设置TLSClientConfig
type HttpC ¶
type HttpC struct { Context *Context // 上下文 Request *http.Request // 请求 Response *http.Response // 响应 BaseURL string // 请求url基地址 URL string // 请求的url QueryData url.Values // 请求url的query参数 SendMediaType string // 请求的ContentType Data interface{} // 要发送的数据体 Error error // 请求发生的错误 SucStatus int // 指定成功的状态码,不匹配则以Error的形式返回 }
HttpC 发起http请求的Client
Example (Body_reader) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "reflect" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() ctx := httpc.NewContext() ctx.BodyReaders = httpc.NewBodyReaders() ctx.BodyReaders.RespBodyTypeReaders[reflect.TypeOf((*int)(nil))] = func(resp *http.Response, reader io.ReadCloser, typ reflect.Type, out interface{}) error { output := out.(*int) *output = resp.StatusCode return nil } // 返回响应状态码 var status int err := httpc.New(baseUrl).Path("hello"). SetContext(ctx). Get(&status) fmt.Println(err, status) }
Output: <nil> 200
Example (Context) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() ctx := httpc.NewContext(). AddCbBeforeSend(func(client *httpc.HttpC, args ...interface{}) error { // fmt.Println(client.DumpRequest()) fmt.Println("before request") return nil }). AddCbAfterSend(func(client *httpc.HttpC, args ...interface{}) error { // fmt.Println(client.DumpResponse()) fmt.Println("after response") return nil }). AddCbOnError(func(client *httpc.HttpC, args ...interface{}) error { // fmt.Println(client.Error) fmt.Println("on error") return nil }). SetConnectReadTimeout(30*time.Second, 30*time.Second) var resp string err := httpc.New(baseUrl).Path("hello").Query("name", "Song").SetContext(ctx).SuccessStatus(200).Get(&resp) fmt.Println(err, resp) }
Output: before request after response <nil> Hello, Song
Example (Download) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "os" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() // 默认方式保存文件 err := httpc.New(baseUrl).Body("xxx").Path("echo").Post(httpc.FilePath("download1.txt")) fmt.Println(err) _, err = os.Stat("download1.txt") if os.IsNotExist(err) { fmt.Println(err) } // 保存文件的另一种方式 err = httpc.New(baseUrl).Body("zzz").Path("echo").Post(&httpc.SaveInfo{ Path: "download2.txt", Override: true, Mode: 0777}) fmt.Println(err) _, err = os.Stat("download2.txt") if os.IsNotExist(err) { fmt.Println(err) } }
Output:
Example (Dump) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() var resp []byte // 构建更复杂的请求 err := httpc.New(baseUrl).Path("/dump").Query("param", "value"). Header("MyHeader", "HeaderValue"). AddCookie(&http.Cookie{Name: "cook", Value: "testcook"}). Body("body data").Post(&resp) fmt.Println(err) // fmt.Println(string(resp)) }
Output: <nil>
Example (Error) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() err := httpc.New(baseUrl).Path("not_exist"). SetContext(httpc.NewContext().AddCbOnError(func(client *httpc.HttpC, args ...interface{}) error { fmt.Println("on error: ", client.Error) return nil })). SuccessStatus(200).Get(nil) fmt.Println(err) }
Output: on error: error http status 404 , expect 200 error http status 404 , expect 200
Example (FormBody) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "net/url" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() // struct body sbody := struct { Name string `form:"name"` Age int `form:"age"` }{ Name: "RecallSong", Age: 18, } var resp string // 发送form参数 err := httpc.New(baseUrl).Path("echo"). Body(sbody, httpc.TypeApplicationForm). // 将结构体转变为form格式的数据体 Post(&resp) fmt.Println(err) fmt.Println(resp) // map body mbody := map[string]interface{}{ "name": "RecallSong", "age": 19, } err = httpc.New(baseUrl).Path("echo"). Body(mbody, httpc.TypeApplicationForm). // 将map变为form格式的数据体 Post(&resp) fmt.Println(err) fmt.Println(resp) // url.Values body ubody := url.Values{} ubody.Set("name", "RecallSong") ubody.Set("age", "20") err = httpc.New(baseUrl).Path("echo"). Body(ubody). // 将url.Values类型转变form格式的数据体 Post(&resp) fmt.Println(err) fmt.Println(resp) }
Output: <nil> age=18&name=RecallSong <nil> age=19&name=RecallSong <nil> age=20&name=RecallSong
Example (Gzip) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() // 测试重试请求 var resp string err := httpc.New(baseUrl).Path("gzip").Get(&resp) fmt.Println(err) fmt.Println(resp) }
Output: <nil> Hello Hello Hello Hello
Example (Hello) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() var resp string // 请求 {baseUrl}/hello?name=RecallSong, 并将返回数据读入到resp变量 err := httpc.New(baseUrl).Path("hello").Query("name", "RecallSong").Get(&resp) fmt.Println(err) fmt.Println(resp) }
Output: <nil> Hello, RecallSong
Example (MapBody) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() body := map[string]interface{}{ "name": "RecallSong", "age": 18, } var resp map[string]interface{} // 根据请求的Content-Type自动对数据进行转换 err := httpc.New(baseUrl).Path("json"). ContentType(httpc.TypeApplicationJson). Body(body). // body转变为 {"name":"RecallSong","age":18} Post(&resp) // 根据响应中的Content-Type,将返回的数据解析到resp中 fmt.Println(err) fmt.Println(resp["name"], resp["age"]) // 如果请求或响应没有指定Content-Type,或是错误的Content-Type,也可以强制指定转换格式类型 err = httpc.New(baseUrl).Path("json"). Body(body, httpc.TypeApplicationJson). // body转变为 {"name":"RecallSong","age":18} Post(&resp, httpc.TypeApplicationJson) // 将返回的数据按json格式解析到map中 fmt.Println(err) fmt.Println(resp["name"], resp["age"]) }
Output: <nil> RecallSong 18 <nil> RecallSong 18
Example (Mutipart_map) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "os" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() file, err := os.Open("doc.go") if err != nil { fmt.Println(err) return } defer file.Close() body := map[string]interface{}{ "file": file, "name": "RecallSong", "age": 18, "file2": httpc.FilePath("doc.go:hello.go"), //上传doc.go文件,参数名为file2,文件名为hello.go } var resp string err = httpc.New(baseUrl).Path("echo"). Body(body, httpc.TypeMultipartFormData).Post(&resp) fmt.Println(err) // fmt.Println(resp) }
Output: <nil>
Example (Mutipart_struct) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "os" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() file, err := os.Open("doc.go") if err != nil { fmt.Println(err) return } defer file.Close() body := struct { Name string `form:"name"` Address []string `form:"address"` Age int `form:"age"` File *os.File `form:"file" file:"hello.go"` File2 httpc.FilePath `form:"file2"` }{ Name: "RecallSong", Address: []string{"HangZhou", "WenZhou"}, Age: 18, File: file, File2: httpc.FilePath("doc.go:hello2.go"), //上传doc.go文件,参数名为file2,文件名为hello2.go } var resp string err = httpc.New(baseUrl).Path("echo"). Body(body, httpc.TypeMultipartFormData).Post(&resp) fmt.Println(err) // fmt.Println(resp) }
Output: <nil>
Example (Path) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "strings" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() req := httpc.New(baseUrl).EscapedPath("recall/song").EscapedPath(18).DumpRequest() fmt.Println(strings.Contains(req, "/recall%2Fsong/18")) }
Output: true
Example (Response) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() var resp *http.Response // 请求 {baseUrl}/hello?name=RecallSong, 并将返回数据读入到resp变量 err := httpc.New(baseUrl).Path("hello").Query("name", "RecallSong").Get(&resp) if err != nil { fmt.Println(err) } else { defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) fmt.Println(resp.Status) fmt.Println(err, string(body)) } }
Output: 200 OK <nil> Hello, RecallSong
Example (Retry) ¶
package main import ( "fmt" "time" "gitee.com/pengdacn/httpc" ) func main() { // 测试重试请求 err := httpc.New("http://not_exist/").Path("not_exist"). SetContext(httpc.NewContext().AddCbOnRetring(func(c *httpc.HttpC, args ...interface{}) error { fmt.Printf("retring %v, next interval %v\n", args[0], args[1]) return nil }).SetRetryConfig(3, time.Second, 2)). Get(nil) fmt.Println(err) }
Output: retring 1, next interval 2s retring 2, next interval 4s retring 3, next interval 8s Get http://not_exist/not_exist: dial tcp: lookup not_exist: no such host
Example (StructBody) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } type Person struct { Name string `json:"name" form:"name" xml:"name"` Age int `json:"age" form:"age" xml:"age"` } func main() { baseUrl := startServer() defer stopServer() body := Person{Name: "RecallSong", Age: 18} var resp Person // 可以使用结构体来传递数据 err := httpc.New(baseUrl).Path("echo"). Body(body, httpc.TypeApplicationJson). Post(&resp, httpc.TypeApplicationJson) fmt.Println(err) fmt.Println(resp.Name, resp.Age) }
Output: <nil> RecallSong 18
Example (Timeout) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } func main() { baseUrl := startServer() defer stopServer() // 测试读数据超时 err := httpc.New(baseUrl).Path("timeout"). SetContext(httpc.NewContext().SetConnectReadTimeout(time.Second, 1*time.Second)). Get(nil) fmt.Println(err != nil) }
Output: true
Example (XmlBody) ¶
package main import ( "bytes" "compress/gzip" "fmt" "io/ioutil" "net/http" "net/http/httptest" "net/http/httputil" "time" "gitee.com/pengdacn/httpc" ) type Handler struct { Method string Func func(w http.ResponseWriter, r *http.Request) } var server *httptest.Server func startServer() string { server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if handler, ok := routers[r.URL.Path]; ok { if handler.Method != "" && handler.Method != r.Method { http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } handler.Func(w, r) } else { http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } })) return server.URL } func stopServer() { server.Close() } var routers = map[string]Handler{ "/hello": Handler{ Method: "GET", Func: func(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, "+r.URL.Query().Get("name")) }, }, "/dump": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := httputil.DumpRequest(r, true) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } fmt.Fprintln(w, string(bytes)) }, }, "/echo": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Write(bytes) }, }, "/json": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/json; charset=UTF-8") w.Write(bytes) }, }, "/xml": Handler{ Method: "POST", Func: func(w http.ResponseWriter, r *http.Request) { bytes, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) return } w.Header().Add("Content-Type", "application/xml; charset=UTF-8") w.Write(bytes) }, }, "/error": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) }, }, "/timeout": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { time.Sleep(2 * time.Second) fmt.Fprintln(w, "Hello") }, }, "/gzip": Handler{ Func: func(w http.ResponseWriter, r *http.Request) { var buffer bytes.Buffer gw := gzip.NewWriter(&buffer) fmt.Fprintln(gw, "Hello Hello Hello Hello") gw.Close() byt := buffer.Bytes() w.Header().Add("Content-Type", "text/html; charset=utf-8") w.Header().Add("Content-Length", fmt.Sprint(len(byt))) w.Header().Add("Content-Encoding", "gzip") w.Write(byt) }, }, } type Person struct { Name string `json:"name" form:"name" xml:"name"` Age int `json:"age" form:"age" xml:"age"` } func main() { baseUrl := startServer() defer stopServer() body := Person{Name: "RecallSong", Age: 18} var resp Person // 发送和接收xml数据 err := httpc.New(baseUrl).Path("xml"). Body(body, httpc.TypeApplicationXml). // 数据转变为xml格式 Post(&resp) fmt.Println(err) fmt.Println(resp) }
Output: <nil> {RecallSong 18}
func (*HttpC) ContentType ¶
ContentType 设置http头中的Content-Type
func (*HttpC) DumpRequest ¶
DumpRequest 将http请求明细输出为string
func (*HttpC) DumpResponse ¶
DumpResponse 将http请求明细输出为string
func (*HttpC) EscapedPath ¶
EscapedPath 对path进行url编码后,再追加到当前的url上
func (*HttpC) SuccessStatus ¶
SuccessStatus 设置成功的状态码
type ReqBodyReader ¶
type ReqBodyReader func(req *http.Request, typ reflect.Type, data interface{}) (io.ReadCloser, error)
ReqBodyReader 根据类型将数据转换为reader
type RespBodyReader ¶
type RespBodyReader func(resp *http.Response, reader io.ReadCloser, typ reflect.Type, out interface{}) error
RespBodyReader 根据类型将数据读取到out中