2015-05-20 23:57:19 +02:00
|
|
|
package transport
|
|
|
|
|
|
|
|
import (
|
2015-06-01 19:55:27 +02:00
|
|
|
"bufio"
|
2016-01-18 02:10:04 +02:00
|
|
|
"crypto/tls"
|
2015-05-20 23:57:19 +02:00
|
|
|
"net"
|
|
|
|
"net/http"
|
2016-01-18 02:10:04 +02:00
|
|
|
|
2024-06-04 22:40:43 +02:00
|
|
|
"go-micro.dev/v5/logger"
|
|
|
|
maddr "go-micro.dev/v5/util/addr"
|
|
|
|
mnet "go-micro.dev/v5/util/net"
|
|
|
|
mls "go-micro.dev/v5/util/tls"
|
2015-05-20 23:57:19 +02:00
|
|
|
)
|
|
|
|
|
2016-01-18 02:10:04 +02:00
|
|
|
type httpTransport struct {
|
|
|
|
opts Options
|
|
|
|
}
|
2015-05-20 23:57:19 +02:00
|
|
|
|
2022-10-20 13:00:50 +02:00
|
|
|
func NewHTTPTransport(opts ...Option) *httpTransport {
|
|
|
|
options := Options{
|
|
|
|
BuffSizeH2: DefaultBufSizeH2,
|
|
|
|
Logger: logger.DefaultLogger,
|
2016-07-28 20:12:56 +02:00
|
|
|
}
|
|
|
|
|
2022-10-20 13:00:50 +02:00
|
|
|
for _, o := range opts {
|
|
|
|
o(&options)
|
2018-07-29 11:55:46 +02:00
|
|
|
}
|
2019-08-24 21:12:04 +02:00
|
|
|
|
2022-10-20 13:00:50 +02:00
|
|
|
return &httpTransport{opts: options}
|
2015-11-24 02:52:59 +02:00
|
|
|
}
|
|
|
|
|
2022-10-20 13:00:50 +02:00
|
|
|
func (h *httpTransport) Init(opts ...Option) error {
|
|
|
|
for _, o := range opts {
|
|
|
|
o(&h.opts)
|
2018-07-29 11:55:46 +02:00
|
|
|
}
|
2019-08-24 21:12:04 +02:00
|
|
|
|
2018-07-29 11:55:46 +02:00
|
|
|
return nil
|
2015-05-21 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2015-06-01 19:55:27 +02:00
|
|
|
func (h *httpTransport) Dial(addr string, opts ...DialOption) (Client, error) {
|
2016-01-03 23:25:03 +02:00
|
|
|
dopts := DialOptions{
|
|
|
|
Timeout: DefaultDialTimeout,
|
2015-06-01 19:55:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, opt := range opts {
|
|
|
|
opt(&dopts)
|
|
|
|
}
|
|
|
|
|
2022-09-30 20:32:55 +02:00
|
|
|
var (
|
|
|
|
conn net.Conn
|
|
|
|
err error
|
|
|
|
)
|
2016-01-18 02:10:04 +02:00
|
|
|
|
|
|
|
if h.opts.Secure || h.opts.TLSConfig != nil {
|
|
|
|
config := h.opts.TLSConfig
|
|
|
|
if config == nil {
|
|
|
|
config = &tls.Config{
|
2022-10-20 13:00:50 +02:00
|
|
|
InsecureSkipVerify: dopts.InsecureSkipVerify,
|
2016-01-18 02:10:04 +02:00
|
|
|
}
|
|
|
|
}
|
2022-09-30 20:32:55 +02:00
|
|
|
|
2019-05-24 18:05:31 +02:00
|
|
|
config.NextProtos = []string{"http/1.1"}
|
2022-09-30 20:32:55 +02:00
|
|
|
|
2019-01-02 17:24:17 +02:00
|
|
|
conn, err = newConn(func(addr string) (net.Conn, error) {
|
|
|
|
return tls.DialWithDialer(&net.Dialer{Timeout: dopts.Timeout}, "tcp", addr, config)
|
|
|
|
})(addr)
|
2016-01-18 02:10:04 +02:00
|
|
|
} else {
|
2019-01-02 17:24:17 +02:00
|
|
|
conn, err = newConn(func(addr string) (net.Conn, error) {
|
|
|
|
return net.DialTimeout("tcp", addr, dopts.Timeout)
|
|
|
|
})(addr)
|
2016-01-18 02:10:04 +02:00
|
|
|
}
|
|
|
|
|
2016-01-03 23:25:03 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-05-23 21:04:16 +02:00
|
|
|
return &httpTransportClient{
|
2015-06-01 19:55:27 +02:00
|
|
|
ht: h,
|
|
|
|
addr: addr,
|
|
|
|
conn: conn,
|
|
|
|
buff: bufio.NewReader(conn),
|
|
|
|
dialOpts: dopts,
|
2022-10-20 13:00:50 +02:00
|
|
|
req: make(chan *http.Request, 100),
|
2018-11-14 21:41:13 +02:00
|
|
|
local: conn.LocalAddr().String(),
|
|
|
|
remote: conn.RemoteAddr().String(),
|
2015-05-20 23:57:19 +02:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2016-01-18 02:10:04 +02:00
|
|
|
func (h *httpTransport) Listen(addr string, opts ...ListenOption) (Listener, error) {
|
|
|
|
var options ListenOptions
|
|
|
|
for _, o := range opts {
|
|
|
|
o(&options)
|
|
|
|
}
|
|
|
|
|
2022-09-30 20:32:55 +02:00
|
|
|
var (
|
|
|
|
list net.Listener
|
|
|
|
err error
|
|
|
|
)
|
2016-01-18 02:10:04 +02:00
|
|
|
|
2022-10-20 13:00:50 +02:00
|
|
|
switch listener := getNetListener(&options); {
|
|
|
|
// Extracted listener from context
|
|
|
|
case listener != nil:
|
|
|
|
getList := func(addr string) (net.Listener, error) {
|
2022-07-30 11:56:14 +02:00
|
|
|
return listener, nil
|
|
|
|
}
|
|
|
|
|
2022-10-20 13:00:50 +02:00
|
|
|
list, err = mnet.Listen(addr, getList)
|
|
|
|
|
|
|
|
// Needs to create self signed certificate
|
|
|
|
case h.opts.Secure || h.opts.TLSConfig != nil:
|
2016-01-18 02:10:04 +02:00
|
|
|
config := h.opts.TLSConfig
|
2016-03-02 16:20:28 +02:00
|
|
|
|
2022-10-20 13:00:50 +02:00
|
|
|
getList := func(addr string) (net.Listener, error) {
|
|
|
|
if config != nil {
|
|
|
|
return tls.Listen("tcp", addr, config)
|
|
|
|
}
|
|
|
|
|
|
|
|
hosts := []string{addr}
|
2016-06-05 17:13:29 +02:00
|
|
|
|
2022-10-20 13:00:50 +02:00
|
|
|
// check if its a valid host:port
|
|
|
|
if host, _, err := net.SplitHostPort(addr); err == nil {
|
|
|
|
if len(host) == 0 {
|
|
|
|
hosts = maddr.IPs()
|
|
|
|
} else {
|
|
|
|
hosts = []string{host}
|
2016-03-02 16:20:28 +02:00
|
|
|
}
|
2016-01-18 02:10:04 +02:00
|
|
|
}
|
2022-10-20 13:00:50 +02:00
|
|
|
|
|
|
|
// generate a certificate
|
|
|
|
cert, err := mls.Certificate(hosts...)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
config = &tls.Config{
|
|
|
|
Certificates: []tls.Certificate{cert},
|
|
|
|
MinVersion: tls.VersionTLS12,
|
|
|
|
}
|
|
|
|
|
2016-03-02 16:20:28 +02:00
|
|
|
return tls.Listen("tcp", addr, config)
|
2016-01-18 02:10:04 +02:00
|
|
|
}
|
2016-03-02 16:20:28 +02:00
|
|
|
|
2022-10-20 13:00:50 +02:00
|
|
|
list, err = mnet.Listen(addr, getList)
|
|
|
|
|
|
|
|
// Create new basic net listener
|
|
|
|
default:
|
|
|
|
getList := func(addr string) (net.Listener, error) {
|
2016-03-02 16:20:28 +02:00
|
|
|
return net.Listen("tcp", addr)
|
|
|
|
}
|
|
|
|
|
2022-10-20 13:00:50 +02:00
|
|
|
list, err = mnet.Listen(addr, getList)
|
2016-01-18 02:10:04 +02:00
|
|
|
}
|
|
|
|
|
2015-05-20 23:57:19 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2015-05-23 21:04:16 +02:00
|
|
|
return &httpTransportListener{
|
2016-07-28 20:12:56 +02:00
|
|
|
ht: h,
|
2022-09-30 20:32:55 +02:00
|
|
|
listener: list,
|
2015-05-20 23:57:19 +02:00
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2018-08-08 19:57:29 +02:00
|
|
|
func (h *httpTransport) Options() Options {
|
|
|
|
return h.opts
|
|
|
|
}
|
|
|
|
|
2015-12-19 23:56:14 +02:00
|
|
|
func (h *httpTransport) String() string {
|
|
|
|
return "http"
|
|
|
|
}
|