Merge branch 'main' of ssh://git.makemake.in:5566/kzkzzzz/mycommon
commit
89708b5201
|
@ -3,7 +3,6 @@ package httpc
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.makemake.in/kzkzzzz/mycommon/mylog"
|
||||
|
@ -21,18 +20,34 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
defaultClient = NewWithRedirect(false)
|
||||
noRedirectClient = NewWithRedirect(true)
|
||||
defaultClient = New()
|
||||
noRedirectClient = New(WithNoRedirect())
|
||||
}
|
||||
|
||||
func NewTransport() *http.Transport {
|
||||
func Client() *HttpClient {
|
||||
return defaultClient
|
||||
}
|
||||
|
||||
func NoRedirectClient() *HttpClient {
|
||||
return noRedirectClient
|
||||
}
|
||||
|
||||
func NewTransport(maxConn int, idleTimeout time.Duration) *http.Transport {
|
||||
if maxConn <= 0 {
|
||||
panic("max connection <= 0")
|
||||
}
|
||||
|
||||
if idleTimeout <= 0 {
|
||||
panic("idle timeout <= 0")
|
||||
}
|
||||
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.MaxIdleConns = 0
|
||||
tr.MaxConnsPerHost = 0
|
||||
tr.MaxIdleConnsPerHost = 2048
|
||||
tr.IdleConnTimeout = time.Second * 90
|
||||
tr.MaxIdleConnsPerHost = maxConn
|
||||
tr.IdleConnTimeout = idleTimeout
|
||||
tr.DisableKeepAlives = false
|
||||
tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: false}
|
||||
//tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: false}
|
||||
return tr
|
||||
}
|
||||
|
||||
|
@ -46,29 +61,43 @@ type Request struct {
|
|||
}
|
||||
|
||||
type HttpClient struct {
|
||||
config *Config
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
func NewWithRedirect(noRedirect bool) *HttpClient {
|
||||
tr := NewTransport()
|
||||
func New(opts ...ConfigOpt) *HttpClient {
|
||||
config := &Config{}
|
||||
for _, opt := range opts {
|
||||
opt(config)
|
||||
}
|
||||
|
||||
if config.timeout <= 0 {
|
||||
config.timeout = time.Second * 6
|
||||
}
|
||||
|
||||
if config.transport == nil {
|
||||
config.transport = NewTransport(3072, time.Second*90)
|
||||
}
|
||||
|
||||
if config.client == nil {
|
||||
client := &http.Client{
|
||||
Transport: tr,
|
||||
Timeout: time.Second * 6,
|
||||
Transport: config.transport,
|
||||
Timeout: config.timeout,
|
||||
}
|
||||
|
||||
if noRedirect {
|
||||
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
if config.redirectFn != nil {
|
||||
client.CheckRedirect = config.redirectFn
|
||||
}
|
||||
|
||||
h := &HttpClient{client: client}
|
||||
return h
|
||||
}
|
||||
config.client = client
|
||||
}
|
||||
|
||||
func NewWithClient(httpClient *http.Client) *HttpClient {
|
||||
h := &HttpClient{client: httpClient}
|
||||
return h
|
||||
hc := &HttpClient{
|
||||
config: config,
|
||||
client: config.client,
|
||||
}
|
||||
|
||||
return hc
|
||||
}
|
||||
|
||||
func (h *HttpClient) SetProxy(pr string) *HttpClient {
|
||||
|
@ -81,7 +110,7 @@ func (h *HttpClient) SetProxy(pr string) *HttpClient {
|
|||
return h
|
||||
}
|
||||
|
||||
func (h *HttpClient) Request(ctx context.Context) *Request {
|
||||
func (h *HttpClient) NewRequest(ctx context.Context) *Request {
|
||||
r := &Request{
|
||||
ctx: ctx,
|
||||
header: nil,
|
||||
|
@ -91,22 +120,14 @@ func (h *HttpClient) Request(ctx context.Context) *Request {
|
|||
return r
|
||||
}
|
||||
|
||||
func PcRequest(ctx context.Context) *Request {
|
||||
return defaultClient.PcRequest(ctx)
|
||||
}
|
||||
|
||||
func MobileRequest(ctx context.Context) *Request {
|
||||
return defaultClient.MobileRequest(ctx)
|
||||
}
|
||||
|
||||
func (h *HttpClient) PcRequest(ctx context.Context) *Request {
|
||||
r := h.Request(ctx)
|
||||
func (h *HttpClient) NewPcRequest(ctx context.Context) *Request {
|
||||
r := h.NewRequest(ctx)
|
||||
r.SetHeaderPcAgent()
|
||||
return r
|
||||
}
|
||||
|
||||
func (h *HttpClient) MobileRequest(ctx context.Context) *Request {
|
||||
r := h.Request(ctx)
|
||||
func (h *HttpClient) NewMobileRequest(ctx context.Context) *Request {
|
||||
r := h.NewRequest(ctx)
|
||||
r.SetHeaderMobileAgent()
|
||||
return r
|
||||
}
|
||||
|
@ -195,7 +216,10 @@ func (r *Request) Do(method, rawUrl string) (*Response, error) {
|
|||
|
||||
req.URL.RawQuery = query.Encode()
|
||||
|
||||
if r.contentType != "" {
|
||||
req.Header.Set("Content-Type", r.contentType)
|
||||
}
|
||||
|
||||
for k := range r.header {
|
||||
req.Header.Set(k, r.header.Get(k))
|
||||
}
|
||||
|
@ -211,9 +235,11 @@ func (r *Request) Do(method, rawUrl string) (*Response, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if r.httpClient.config.noCheckStatus == false {
|
||||
if res.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("status code err: %d (%s)", res.StatusCode, body)
|
||||
}
|
||||
}
|
||||
|
||||
resp := &Response{
|
||||
body: body,
|
||||
|
@ -223,14 +249,6 @@ func (r *Request) Do(method, rawUrl string) (*Response, error) {
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
func Client() *HttpClient {
|
||||
return defaultClient
|
||||
}
|
||||
|
||||
func NoRedirectClient() *HttpClient {
|
||||
return noRedirectClient
|
||||
}
|
||||
|
||||
func (r *Request) SetHeaderPcAgent() *Request {
|
||||
r.SetHeader(HeaderUserAgent, PcUserAgent)
|
||||
return r
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package httpc
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
type (
|
||||
Config struct {
|
||||
timeout time.Duration
|
||||
client *http.Client
|
||||
transport *http.Transport
|
||||
redirectFn func(req *http.Request, via []*http.Request) error
|
||||
noCheckStatus bool
|
||||
}
|
||||
|
||||
ConfigOpt func(c *Config)
|
||||
)
|
||||
|
||||
func WithTimout(v time.Duration) ConfigOpt {
|
||||
return func(c *Config) {
|
||||
c.timeout = v
|
||||
}
|
||||
}
|
||||
|
||||
func WithClient(v *http.Client) ConfigOpt {
|
||||
return func(c *Config) {
|
||||
c.client = v
|
||||
}
|
||||
}
|
||||
|
||||
func WithTransport(v *http.Transport) ConfigOpt {
|
||||
return func(c *Config) {
|
||||
c.transport = v
|
||||
}
|
||||
}
|
||||
|
||||
func WithRedirectFn(v func(req *http.Request, via []*http.Request) error) ConfigOpt {
|
||||
return func(c *Config) {
|
||||
c.redirectFn = v
|
||||
}
|
||||
}
|
||||
|
||||
func WithNoRedirect() ConfigOpt {
|
||||
return func(c *Config) {
|
||||
c.redirectFn = func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithNoCheckStatus(v bool) ConfigOpt {
|
||||
return func(c *Config) {
|
||||
c.noCheckStatus = v
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue