1
0
mirror of https://github.com/go-micro/go-micro.git synced 2024-11-24 08:02:32 +02:00
go-micro/transport/http_transport.go
David Brouwer a3980c2308
feat: add test framework & refactor RPC server (#2579)
Co-authored-by: Rene Jochum <rene@jochum.dev>
2022-10-20 13:00:50 +02:00

171 lines
3.2 KiB
Go

package transport
import (
"bufio"
"crypto/tls"
"net"
"net/http"
"go-micro.dev/v4/logger"
maddr "go-micro.dev/v4/util/addr"
mnet "go-micro.dev/v4/util/net"
mls "go-micro.dev/v4/util/tls"
)
type httpTransport struct {
opts Options
}
func NewHTTPTransport(opts ...Option) *httpTransport {
options := Options{
BuffSizeH2: DefaultBufSizeH2,
Logger: logger.DefaultLogger,
}
for _, o := range opts {
o(&options)
}
return &httpTransport{opts: options}
}
func (h *httpTransport) Init(opts ...Option) error {
for _, o := range opts {
o(&h.opts)
}
return nil
}
func (h *httpTransport) Dial(addr string, opts ...DialOption) (Client, error) {
dopts := DialOptions{
Timeout: DefaultDialTimeout,
}
for _, opt := range opts {
opt(&dopts)
}
var (
conn net.Conn
err error
)
if h.opts.Secure || h.opts.TLSConfig != nil {
config := h.opts.TLSConfig
if config == nil {
config = &tls.Config{
InsecureSkipVerify: dopts.InsecureSkipVerify,
}
}
config.NextProtos = []string{"http/1.1"}
conn, err = newConn(func(addr string) (net.Conn, error) {
return tls.DialWithDialer(&net.Dialer{Timeout: dopts.Timeout}, "tcp", addr, config)
})(addr)
} else {
conn, err = newConn(func(addr string) (net.Conn, error) {
return net.DialTimeout("tcp", addr, dopts.Timeout)
})(addr)
}
if err != nil {
return nil, err
}
return &httpTransportClient{
ht: h,
addr: addr,
conn: conn,
buff: bufio.NewReader(conn),
dialOpts: dopts,
req: make(chan *http.Request, 100),
local: conn.LocalAddr().String(),
remote: conn.RemoteAddr().String(),
}, nil
}
func (h *httpTransport) Listen(addr string, opts ...ListenOption) (Listener, error) {
var options ListenOptions
for _, o := range opts {
o(&options)
}
var (
list net.Listener
err error
)
switch listener := getNetListener(&options); {
// Extracted listener from context
case listener != nil:
getList := func(addr string) (net.Listener, error) {
return listener, nil
}
list, err = mnet.Listen(addr, getList)
// Needs to create self signed certificate
case h.opts.Secure || h.opts.TLSConfig != nil:
config := h.opts.TLSConfig
getList := func(addr string) (net.Listener, error) {
if config != nil {
return tls.Listen("tcp", addr, config)
}
hosts := []string{addr}
// 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}
}
}
// generate a certificate
cert, err := mls.Certificate(hosts...)
if err != nil {
return nil, err
}
config = &tls.Config{
Certificates: []tls.Certificate{cert},
MinVersion: tls.VersionTLS12,
}
return tls.Listen("tcp", addr, config)
}
list, err = mnet.Listen(addr, getList)
// Create new basic net listener
default:
getList := func(addr string) (net.Listener, error) {
return net.Listen("tcp", addr)
}
list, err = mnet.Listen(addr, getList)
}
if err != nil {
return nil, err
}
return &httpTransportListener{
ht: h,
listener: list,
}, nil
}
func (h *httpTransport) Options() Options {
return h.opts
}
func (h *httpTransport) String() string {
return "http"
}