mirror of
https://github.com/minio/minio.git
synced 2025-11-07 04:42:56 -05:00
Migrate to go1.12 to simplify our cmd/http package (#7302)
Simplify the cmd/http package overall by removing custom plain text v/s tls connection detection, by migrating to go1.12 and choose minimum version to be go1.12 Also remove all the vendored deps, since they are not useful anymore.
This commit is contained in:
committed by
kannappanr
parent
4c23e6fa55
commit
313a3a286a
@@ -17,15 +17,13 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"net"
|
||||
"time"
|
||||
)
|
||||
|
||||
// BufConn - is a generic stream-oriented network connection supporting buffered reader and read/write timeout.
|
||||
type BufConn struct {
|
||||
// DeadlineConn - is a generic stream-oriented network connection supporting buffered reader and read/write timeout.
|
||||
type DeadlineConn struct {
|
||||
QuirkConn
|
||||
bufReader *bufio.Reader // buffered reader wraps reader in net.Conn.
|
||||
readTimeout time.Duration // sets the read timeout in the connection.
|
||||
writeTimeout time.Duration // sets the write timeout in the connection.
|
||||
updateBytesReadFunc func(int) // function to be called to update bytes read.
|
||||
@@ -33,42 +31,22 @@ type BufConn struct {
|
||||
}
|
||||
|
||||
// Sets read timeout
|
||||
func (c *BufConn) setReadTimeout() {
|
||||
func (c *DeadlineConn) setReadTimeout() {
|
||||
if c.readTimeout != 0 && c.canSetReadDeadline() {
|
||||
c.SetReadDeadline(time.Now().UTC().Add(c.readTimeout))
|
||||
}
|
||||
}
|
||||
|
||||
func (c *BufConn) setWriteTimeout() {
|
||||
func (c *DeadlineConn) setWriteTimeout() {
|
||||
if c.writeTimeout != 0 {
|
||||
c.SetWriteDeadline(time.Now().UTC().Add(c.writeTimeout))
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveTimeout - removes all configured read and write
|
||||
// timeouts. Used by callers which control net.Conn behavior
|
||||
// themselves.
|
||||
func (c *BufConn) RemoveTimeout() {
|
||||
c.readTimeout = 0
|
||||
c.writeTimeout = 0
|
||||
// Unset read/write timeouts, since we use **bufio** it is not
|
||||
// guaranteed that the underlying Peek/Read operation in-fact
|
||||
// indeed performed a Read() operation on the network. With
|
||||
// that in mind we need to unset any timeouts currently set to
|
||||
// avoid any pre-mature timeouts.
|
||||
c.SetDeadline(time.Time{})
|
||||
}
|
||||
|
||||
// Peek - returns the next n bytes without advancing the reader. It just wraps bufio.Reader.Peek().
|
||||
func (c *BufConn) Peek(n int) ([]byte, error) {
|
||||
c.setReadTimeout()
|
||||
return c.bufReader.Peek(n)
|
||||
}
|
||||
|
||||
// Read - reads data from the connection using wrapped buffered reader.
|
||||
func (c *BufConn) Read(b []byte) (n int, err error) {
|
||||
func (c *DeadlineConn) Read(b []byte) (n int, err error) {
|
||||
c.setReadTimeout()
|
||||
n, err = c.bufReader.Read(b)
|
||||
n, err = c.Conn.Read(b)
|
||||
if err == nil && c.updateBytesReadFunc != nil {
|
||||
c.updateBytesReadFunc(n)
|
||||
}
|
||||
@@ -77,7 +55,7 @@ func (c *BufConn) Read(b []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
// Write - writes data to the connection.
|
||||
func (c *BufConn) Write(b []byte) (n int, err error) {
|
||||
func (c *DeadlineConn) Write(b []byte) (n int, err error) {
|
||||
c.setWriteTimeout()
|
||||
n, err = c.Conn.Write(b)
|
||||
if err == nil && c.updateBytesWrittenFunc != nil {
|
||||
@@ -87,11 +65,10 @@ func (c *BufConn) Write(b []byte) (n int, err error) {
|
||||
return n, err
|
||||
}
|
||||
|
||||
// newBufConn - creates a new connection object wrapping net.Conn.
|
||||
func newBufConn(c net.Conn, readTimeout, writeTimeout time.Duration, maxHeaderBytes int, updateBytesReadFunc, updateBytesWrittenFunc func(int)) *BufConn {
|
||||
return &BufConn{
|
||||
// newDeadlineConn - creates a new connection object wrapping net.Conn with deadlines.
|
||||
func newDeadlineConn(c net.Conn, readTimeout, writeTimeout time.Duration, updateBytesReadFunc, updateBytesWrittenFunc func(int)) *DeadlineConn {
|
||||
return &DeadlineConn{
|
||||
QuirkConn: QuirkConn{Conn: c},
|
||||
bufReader: bufio.NewReaderSize(c, maxHeaderBytes),
|
||||
readTimeout: readTimeout,
|
||||
writeTimeout: writeTimeout,
|
||||
updateBytesReadFunc: updateBytesReadFunc,
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// Test bufconn handles read timeout properly by reading two messages beyond deadline.
|
||||
// Test deadlineconn handles read timeout properly by reading two messages beyond deadline.
|
||||
func TestBuffConnReadTimeout(t *testing.T) {
|
||||
l, err := net.Listen("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
@@ -49,12 +49,12 @@ func TestBuffConnReadTimeout(t *testing.T) {
|
||||
t.Errorf("failed to accept new connection. %v", terr)
|
||||
return
|
||||
}
|
||||
bufconn := newBufConn(tcpConn, 1*time.Second, 1*time.Second, 4096, nil, nil)
|
||||
defer bufconn.Close()
|
||||
deadlineconn := newDeadlineConn(tcpConn, 1*time.Second, 1*time.Second, nil, nil)
|
||||
defer deadlineconn.Close()
|
||||
|
||||
// Read a line
|
||||
var b = make([]byte, 12)
|
||||
_, terr = bufconn.Read(b)
|
||||
_, terr = deadlineconn.Read(b)
|
||||
if terr != nil {
|
||||
t.Errorf("failed to read from client. %v", terr)
|
||||
return
|
||||
@@ -68,7 +68,7 @@ func TestBuffConnReadTimeout(t *testing.T) {
|
||||
// Wait for more than read timeout to simulate processing.
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
_, terr = bufconn.Read(b)
|
||||
_, terr = deadlineconn.Read(b)
|
||||
if terr != nil {
|
||||
t.Errorf("failed to read from client. %v", terr)
|
||||
return
|
||||
@@ -80,14 +80,11 @@ func TestBuffConnReadTimeout(t *testing.T) {
|
||||
}
|
||||
|
||||
// Send a response.
|
||||
_, terr = io.WriteString(bufconn, "messages received\n")
|
||||
_, terr = io.WriteString(deadlineconn, "messages received\n")
|
||||
if terr != nil {
|
||||
t.Errorf("failed to write to client. %v", terr)
|
||||
return
|
||||
}
|
||||
|
||||
// Removes all deadlines if any.
|
||||
bufconn.RemoveTimeout()
|
||||
}()
|
||||
|
||||
c, err := net.Dial("tcp", serverAddr)
|
||||
@@ -17,56 +17,15 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
)
|
||||
|
||||
var sslRequiredErrMsg = []byte("HTTP/1.1 403 Forbidden\r\n\r\nSSL required")
|
||||
|
||||
// HTTP methods.
|
||||
var methods = []string{
|
||||
http.MethodGet,
|
||||
http.MethodHead,
|
||||
http.MethodPost,
|
||||
http.MethodPut,
|
||||
http.MethodPatch,
|
||||
http.MethodDelete,
|
||||
http.MethodConnect,
|
||||
http.MethodOptions,
|
||||
http.MethodTrace,
|
||||
"PRI", // HTTP 2 method
|
||||
}
|
||||
|
||||
func getPlainText(bufConn *BufConn) (bool, error) {
|
||||
defer bufConn.setReadTimeout()
|
||||
|
||||
if bufConn.canSetReadDeadline() {
|
||||
// Set deadline such that we close the connection quickly
|
||||
// of no data was received from the Peek()
|
||||
bufConn.SetReadDeadline(time.Now().UTC().Add(time.Second * 3))
|
||||
}
|
||||
b, err := bufConn.Peek(1)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
for _, method := range methods {
|
||||
if b[0] == method[0] {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
type acceptResult struct {
|
||||
conn net.Conn
|
||||
err error
|
||||
@@ -78,13 +37,11 @@ type httpListener struct {
|
||||
tcpListeners []*net.TCPListener // underlaying TCP listeners.
|
||||
acceptCh chan acceptResult // channel where all TCP listeners write accepted connection.
|
||||
doneCh chan struct{} // done channel for TCP listener goroutines.
|
||||
tlsConfig *tls.Config // TLS configuration
|
||||
tcpKeepAliveTimeout time.Duration
|
||||
readTimeout time.Duration
|
||||
writeTimeout time.Duration
|
||||
maxHeaderBytes int
|
||||
updateBytesReadFunc func(int) // function to be called to update bytes read in BufConn.
|
||||
updateBytesWrittenFunc func(int) // function to be called to update bytes written in BufConn.
|
||||
updateBytesReadFunc func(int) // function to be called to update bytes read in Deadlineconn.
|
||||
updateBytesWrittenFunc func(int) // function to be called to update bytes written in Deadlineconn.
|
||||
}
|
||||
|
||||
// isRoutineNetErr returns true if error is due to a network timeout,
|
||||
@@ -107,7 +64,7 @@ func isRoutineNetErr(err error) bool {
|
||||
return err == io.EOF || err.Error() == "EOF"
|
||||
}
|
||||
|
||||
// start - starts separate goroutine for each TCP listener. A valid insecure/TLS HTTP new connection is passed to httpListener.acceptCh.
|
||||
// start - starts separate goroutine for each TCP listener. A valid new connection is passed to httpListener.acceptCh.
|
||||
func (listener *httpListener) start() {
|
||||
listener.acceptCh = make(chan acceptResult)
|
||||
listener.doneCh = make(chan struct{})
|
||||
@@ -134,36 +91,10 @@ func (listener *httpListener) start() {
|
||||
tcpConn.SetKeepAlive(true)
|
||||
tcpConn.SetKeepAlivePeriod(listener.tcpKeepAliveTimeout)
|
||||
|
||||
bufconn := newBufConn(tcpConn, listener.readTimeout, listener.writeTimeout, listener.maxHeaderBytes,
|
||||
listener.updateBytesReadFunc, listener.updateBytesWrittenFunc)
|
||||
if listener.tlsConfig != nil {
|
||||
ok, err := getPlainText(bufconn)
|
||||
if err != nil {
|
||||
// Peek could fail legitimately when clients abruptly close
|
||||
// connection. E.g. Chrome browser opens connections speculatively to
|
||||
// speed up loading of a web page. Peek may also fail due to network
|
||||
// saturation on a transport with read timeout set. All other kind of
|
||||
// errors should be logged for further investigation. Thanks @brendanashworth.
|
||||
if !isRoutineNetErr(err) {
|
||||
reqInfo := (&logger.ReqInfo{}).AppendTags("remoteAddr", bufconn.RemoteAddr().String())
|
||||
reqInfo.AppendTags("localAddr", bufconn.LocalAddr().String())
|
||||
ctx := logger.SetReqInfo(context.Background(), reqInfo)
|
||||
logger.LogIf(ctx, err)
|
||||
}
|
||||
bufconn.Close()
|
||||
return
|
||||
}
|
||||
deadlineConn := newDeadlineConn(tcpConn, listener.readTimeout,
|
||||
listener.writeTimeout, listener.updateBytesReadFunc, listener.updateBytesWrittenFunc)
|
||||
|
||||
if ok {
|
||||
// As TLS is configured and we got plain text HTTP request,
|
||||
// return 403 (forbidden) error.
|
||||
bufconn.Write(sslRequiredErrMsg)
|
||||
bufconn.Close()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
send(acceptResult{bufconn, nil}, doneCh)
|
||||
send(acceptResult{deadlineConn, nil}, doneCh)
|
||||
}
|
||||
|
||||
// Closure to handle TCPListener until done channel is closed.
|
||||
@@ -244,11 +175,9 @@ func (listener *httpListener) Addrs() (addrs []net.Addr) {
|
||||
// * listen to multiple addresses
|
||||
// * controls incoming connections only doing HTTP protocol
|
||||
func newHTTPListener(serverAddrs []string,
|
||||
tlsConfig *tls.Config,
|
||||
tcpKeepAliveTimeout time.Duration,
|
||||
readTimeout time.Duration,
|
||||
writeTimeout time.Duration,
|
||||
maxHeaderBytes int,
|
||||
updateBytesReadFunc func(int),
|
||||
updateBytesWrittenFunc func(int)) (listener *httpListener, err error) {
|
||||
|
||||
@@ -284,11 +213,9 @@ func newHTTPListener(serverAddrs []string,
|
||||
|
||||
listener = &httpListener{
|
||||
tcpListeners: tcpListeners,
|
||||
tlsConfig: tlsConfig,
|
||||
tcpKeepAliveTimeout: tcpKeepAliveTimeout,
|
||||
readTimeout: readTimeout,
|
||||
writeTimeout: writeTimeout,
|
||||
maxHeaderBytes: maxHeaderBytes,
|
||||
updateBytesReadFunc: updateBytesReadFunc,
|
||||
updateBytesWrittenFunc: updateBytesWrittenFunc,
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -34,17 +33,6 @@ import (
|
||||
|
||||
var serverPort uint32 = 60000
|
||||
|
||||
// fail - as t.Fatalf() is not goroutine safe, this function behaves like t.Fatalf().
|
||||
func fail(t *testing.T, template string, args ...interface{}) {
|
||||
fmt.Printf(template, args...)
|
||||
fmt.Println()
|
||||
t.Fail()
|
||||
}
|
||||
|
||||
func getNextPort() string {
|
||||
return strconv.Itoa(int(atomic.AddUint32(&serverPort, 1)))
|
||||
}
|
||||
|
||||
var getCert = func(*tls.ClientHelloInfo) (*tls.Certificate, error) {
|
||||
certificate, err := getTLSCert()
|
||||
if err != nil {
|
||||
@@ -106,19 +94,8 @@ rr3DRiUP6V/10CZ/ImeSJ72k69VuTw9vq2HzB4x6pqxF2X7JQSLUCS2wfNN13N0d
|
||||
return tls.X509KeyPair(certPEMBlock, keyPEMBlock)
|
||||
}
|
||||
|
||||
func getTLSConfig(t *testing.T) *tls.Config {
|
||||
tlsCert, err := getTLSCert()
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to parse private/certificate data. %v\n", err)
|
||||
}
|
||||
tlsConfig := &tls.Config{
|
||||
PreferServerCipherSuites: true,
|
||||
MinVersion: tls.VersionTLS12,
|
||||
NextProtos: []string{"http/1.1"},
|
||||
}
|
||||
tlsConfig.Certificates = append(tlsConfig.Certificates, tlsCert)
|
||||
|
||||
return tlsConfig
|
||||
func getNextPort() string {
|
||||
return strconv.Itoa(int(atomic.AddUint32(&serverPort, 1)))
|
||||
}
|
||||
|
||||
func getNonLoopBackIP(t *testing.T) string {
|
||||
@@ -154,11 +131,8 @@ func getNonLoopBackIP(t *testing.T) string {
|
||||
}
|
||||
|
||||
func TestNewHTTPListener(t *testing.T) {
|
||||
tlsConfig := getTLSConfig(t)
|
||||
|
||||
testCases := []struct {
|
||||
serverAddrs []string
|
||||
tlsConfig *tls.Config
|
||||
tcpKeepAliveTimeout time.Duration
|
||||
readTimeout time.Duration
|
||||
writeTimeout time.Duration
|
||||
@@ -166,24 +140,22 @@ func TestNewHTTPListener(t *testing.T) {
|
||||
updateBytesWrittenFunc func(int)
|
||||
expectedErr bool
|
||||
}{
|
||||
{[]string{"93.184.216.34:65432"}, nil, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, true},
|
||||
{[]string{"example.org:65432"}, nil, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, true},
|
||||
{[]string{"unknown-host"}, nil, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, true},
|
||||
{[]string{"unknown-host:65432"}, nil, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, true},
|
||||
{[]string{"localhost:65432", "93.184.216.34:65432"}, nil, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, true},
|
||||
{[]string{"localhost:65432", "unknown-host:65432"}, nil, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, true},
|
||||
{[]string{"localhost:0"}, nil, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, false},
|
||||
{[]string{"localhost:0"}, tlsConfig, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, false},
|
||||
{[]string{"93.184.216.34:65432"}, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, true},
|
||||
{[]string{"example.org:65432"}, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, true},
|
||||
{[]string{"unknown-host"}, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, true},
|
||||
{[]string{"unknown-host:65432"}, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, true},
|
||||
{[]string{"localhost:65432", "93.184.216.34:65432"}, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, true},
|
||||
{[]string{"localhost:65432", "unknown-host:65432"}, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, true},
|
||||
{[]string{"localhost:0"}, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, false},
|
||||
{[]string{"localhost:0"}, time.Duration(0), time.Duration(0), time.Duration(0), nil, nil, false},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
listener, err := newHTTPListener(
|
||||
testCase.serverAddrs,
|
||||
testCase.tlsConfig,
|
||||
testCase.tcpKeepAliveTimeout,
|
||||
testCase.readTimeout,
|
||||
testCase.writeTimeout,
|
||||
DefaultMaxHeaderBytes,
|
||||
testCase.updateBytesReadFunc,
|
||||
testCase.updateBytesWrittenFunc,
|
||||
)
|
||||
@@ -203,29 +175,25 @@ func TestNewHTTPListener(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHTTPListenerStartClose(t *testing.T) {
|
||||
tlsConfig := getTLSConfig(t)
|
||||
nonLoopBackIP := getNonLoopBackIP(t)
|
||||
|
||||
testCases := []struct {
|
||||
serverAddrs []string
|
||||
tlsConfig *tls.Config
|
||||
}{
|
||||
{[]string{"localhost:0"}, nil},
|
||||
{[]string{nonLoopBackIP + ":0"}, nil},
|
||||
{[]string{"127.0.0.1:0", nonLoopBackIP + ":0"}, nil},
|
||||
{[]string{"localhost:0"}, tlsConfig},
|
||||
{[]string{nonLoopBackIP + ":0"}, tlsConfig},
|
||||
{[]string{"127.0.0.1:0", nonLoopBackIP + ":0"}, tlsConfig},
|
||||
{[]string{"localhost:0"}},
|
||||
{[]string{nonLoopBackIP + ":0"}},
|
||||
{[]string{"127.0.0.1:0", nonLoopBackIP + ":0"}},
|
||||
{[]string{"localhost:0"}},
|
||||
{[]string{nonLoopBackIP + ":0"}},
|
||||
{[]string{"127.0.0.1:0", nonLoopBackIP + ":0"}},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
listener, err := newHTTPListener(
|
||||
testCase.serverAddrs,
|
||||
testCase.tlsConfig,
|
||||
time.Duration(0),
|
||||
time.Duration(0),
|
||||
time.Duration(0),
|
||||
DefaultMaxHeaderBytes,
|
||||
nil, nil,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -245,7 +213,6 @@ func TestHTTPListenerStartClose(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHTTPListenerAddr(t *testing.T) {
|
||||
tlsConfig := getTLSConfig(t)
|
||||
nonLoopBackIP := getNonLoopBackIP(t)
|
||||
var casePorts []string
|
||||
for i := 0; i < 6; i++ {
|
||||
@@ -254,25 +221,22 @@ func TestHTTPListenerAddr(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
serverAddrs []string
|
||||
tlsConfig *tls.Config
|
||||
expectedAddr string
|
||||
}{
|
||||
{[]string{"localhost:" + casePorts[0]}, nil, "127.0.0.1:" + casePorts[0]},
|
||||
{[]string{nonLoopBackIP + ":" + casePorts[1]}, nil, nonLoopBackIP + ":" + casePorts[1]},
|
||||
{[]string{"127.0.0.1:" + casePorts[2], nonLoopBackIP + ":" + casePorts[2]}, nil, "0.0.0.0:" + casePorts[2]},
|
||||
{[]string{"localhost:" + casePorts[3]}, tlsConfig, "127.0.0.1:" + casePorts[3]},
|
||||
{[]string{nonLoopBackIP + ":" + casePorts[4]}, tlsConfig, nonLoopBackIP + ":" + casePorts[4]},
|
||||
{[]string{"127.0.0.1:" + casePorts[5], nonLoopBackIP + ":" + casePorts[5]}, tlsConfig, "0.0.0.0:" + casePorts[5]},
|
||||
{[]string{"localhost:" + casePorts[0]}, "127.0.0.1:" + casePorts[0]},
|
||||
{[]string{nonLoopBackIP + ":" + casePorts[1]}, nonLoopBackIP + ":" + casePorts[1]},
|
||||
{[]string{"127.0.0.1:" + casePorts[2], nonLoopBackIP + ":" + casePorts[2]}, "0.0.0.0:" + casePorts[2]},
|
||||
{[]string{"localhost:" + casePorts[3]}, "127.0.0.1:" + casePorts[3]},
|
||||
{[]string{nonLoopBackIP + ":" + casePorts[4]}, nonLoopBackIP + ":" + casePorts[4]},
|
||||
{[]string{"127.0.0.1:" + casePorts[5], nonLoopBackIP + ":" + casePorts[5]}, "0.0.0.0:" + casePorts[5]},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
listener, err := newHTTPListener(
|
||||
testCase.serverAddrs,
|
||||
testCase.tlsConfig,
|
||||
time.Duration(0),
|
||||
time.Duration(0),
|
||||
time.Duration(0),
|
||||
DefaultMaxHeaderBytes,
|
||||
nil, nil,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -289,7 +253,6 @@ func TestHTTPListenerAddr(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestHTTPListenerAddrs(t *testing.T) {
|
||||
tlsConfig := getTLSConfig(t)
|
||||
nonLoopBackIP := getNonLoopBackIP(t)
|
||||
var casePorts []string
|
||||
for i := 0; i < 6; i++ {
|
||||
@@ -298,25 +261,22 @@ func TestHTTPListenerAddrs(t *testing.T) {
|
||||
|
||||
testCases := []struct {
|
||||
serverAddrs []string
|
||||
tlsConfig *tls.Config
|
||||
expectedAddrs set.StringSet
|
||||
}{
|
||||
{[]string{"localhost:" + casePorts[0]}, nil, set.CreateStringSet("127.0.0.1:" + casePorts[0])},
|
||||
{[]string{nonLoopBackIP + ":" + casePorts[1]}, nil, set.CreateStringSet(nonLoopBackIP + ":" + casePorts[1])},
|
||||
{[]string{"127.0.0.1:" + casePorts[2], nonLoopBackIP + ":" + casePorts[2]}, nil, set.CreateStringSet("127.0.0.1:"+casePorts[2], nonLoopBackIP+":"+casePorts[2])},
|
||||
{[]string{"localhost:" + casePorts[3]}, tlsConfig, set.CreateStringSet("127.0.0.1:" + casePorts[3])},
|
||||
{[]string{nonLoopBackIP + ":" + casePorts[4]}, tlsConfig, set.CreateStringSet(nonLoopBackIP + ":" + casePorts[4])},
|
||||
{[]string{"127.0.0.1:" + casePorts[5], nonLoopBackIP + ":" + casePorts[5]}, tlsConfig, set.CreateStringSet("127.0.0.1:"+casePorts[5], nonLoopBackIP+":"+casePorts[5])},
|
||||
{[]string{"localhost:" + casePorts[0]}, set.CreateStringSet("127.0.0.1:" + casePorts[0])},
|
||||
{[]string{nonLoopBackIP + ":" + casePorts[1]}, set.CreateStringSet(nonLoopBackIP + ":" + casePorts[1])},
|
||||
{[]string{"127.0.0.1:" + casePorts[2], nonLoopBackIP + ":" + casePorts[2]}, set.CreateStringSet("127.0.0.1:"+casePorts[2], nonLoopBackIP+":"+casePorts[2])},
|
||||
{[]string{"localhost:" + casePorts[3]}, set.CreateStringSet("127.0.0.1:" + casePorts[3])},
|
||||
{[]string{nonLoopBackIP + ":" + casePorts[4]}, set.CreateStringSet(nonLoopBackIP + ":" + casePorts[4])},
|
||||
{[]string{"127.0.0.1:" + casePorts[5], nonLoopBackIP + ":" + casePorts[5]}, set.CreateStringSet("127.0.0.1:"+casePorts[5], nonLoopBackIP+":"+casePorts[5])},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
listener, err := newHTTPListener(
|
||||
testCase.serverAddrs,
|
||||
testCase.tlsConfig,
|
||||
time.Duration(0),
|
||||
time.Duration(0),
|
||||
time.Duration(0),
|
||||
DefaultMaxHeaderBytes,
|
||||
nil, nil,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -337,69 +297,6 @@ func TestHTTPListenerAddrs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTPListenerAcceptTLSError(t *testing.T) {
|
||||
tlsConfig := getTLSConfig(t)
|
||||
nonLoopBackIP := getNonLoopBackIP(t)
|
||||
|
||||
testCases := []struct {
|
||||
serverAddrs []string
|
||||
tlsConfig *tls.Config
|
||||
request string
|
||||
}{
|
||||
{[]string{"127.0.0.1:0", nonLoopBackIP + ":0"}, tlsConfig, "GET / HTTP/1.0\n"},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
listener, err := newHTTPListener(
|
||||
testCase.serverAddrs,
|
||||
testCase.tlsConfig,
|
||||
time.Duration(0),
|
||||
time.Duration(0),
|
||||
time.Duration(0),
|
||||
DefaultMaxHeaderBytes,
|
||||
nil, nil,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Test %d: error: expected = <nil>, got = %v", i+1, err)
|
||||
}
|
||||
|
||||
for _, serverAddr := range listener.Addrs() {
|
||||
conn, err := net.Dial("tcp", serverAddr.String())
|
||||
if err != nil {
|
||||
t.Fatalf("Test %d: error: expected = <nil>, got = %v", i+1, err)
|
||||
}
|
||||
|
||||
if _, err = io.WriteString(conn, testCase.request); err != nil {
|
||||
t.Fatalf("Test %d: request send: expected = <nil>, got = %v", i+1, err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
serverConn, aerr := listener.Accept()
|
||||
if aerr == nil {
|
||||
fail(t, "Test %d: accept: expected = <error>, got = <nil>", i+1)
|
||||
}
|
||||
if serverConn != nil {
|
||||
fail(t, "Test %d: accept: server expected = <nil>, got = %v", i+1, serverConn)
|
||||
}
|
||||
}()
|
||||
|
||||
buf := make([]byte, len(sslRequiredErrMsg))
|
||||
n, err := io.ReadFull(conn, buf)
|
||||
if err != nil {
|
||||
t.Fatalf("Test %d: reply read: expected = <nil> got = %v", i+1, err)
|
||||
} else if n != len(buf) {
|
||||
t.Fatalf("Test %d: reply length: expected = %v got = %v", i+1, len(buf), n)
|
||||
} else if !bytes.Equal(buf, sslRequiredErrMsg) {
|
||||
t.Fatalf("Test %d: reply: expected = %v got = %v", i+1, string(sslRequiredErrMsg), string(buf))
|
||||
}
|
||||
|
||||
conn.Close()
|
||||
}
|
||||
|
||||
listener.Close()
|
||||
}
|
||||
}
|
||||
|
||||
type myTimeoutErr struct {
|
||||
timeout bool
|
||||
}
|
||||
|
||||
@@ -92,11 +92,9 @@ func (srv *Server) Start() (err error) {
|
||||
var listener *httpListener
|
||||
listener, err = newHTTPListener(
|
||||
addrs,
|
||||
tlsConfig,
|
||||
tcpKeepAliveTimeout,
|
||||
readTimeout,
|
||||
writeTimeout,
|
||||
srv.MaxHeaderBytes,
|
||||
srv.UpdateBytesReadFunc,
|
||||
srv.UpdateBytesWrittenFunc,
|
||||
)
|
||||
|
||||
@@ -37,29 +37,29 @@ func TestPrepareUpdateMessage(t *testing.T) {
|
||||
{-72 * time.Hour, "another_update_url", ""},
|
||||
{0, "another_update_url", ""},
|
||||
{time.Hour, "", ""},
|
||||
{1 * time.Second, "my_download_url", "now"},
|
||||
{2 * time.Second, "my_download_url", "1 second ago"},
|
||||
{0 * time.Second, "my_download_url", "now"},
|
||||
{1 * time.Second, "my_download_url", "1 second ago"},
|
||||
{37 * time.Second, "my_download_url", "37 seconds ago"},
|
||||
{60 * time.Second, "my_download_url", "60 seconds ago"},
|
||||
{60 * time.Second, "my_download_url", "1 minute ago"},
|
||||
{61 * time.Second, "my_download_url", "1 minute ago"},
|
||||
|
||||
// Testcase index 10
|
||||
{37 * time.Minute, "my_download_url", "37 minutes ago"},
|
||||
{1 * time.Hour, "my_download_url", "60 minutes ago"},
|
||||
{1 * time.Hour, "my_download_url", "1 hour ago"},
|
||||
{61 * time.Minute, "my_download_url", "1 hour ago"},
|
||||
{122 * time.Minute, "my_download_url", "2 hours ago"},
|
||||
{24 * time.Hour, "my_download_url", "24 hours ago"},
|
||||
{24 * time.Hour, "my_download_url", "1 day ago"},
|
||||
{25 * time.Hour, "my_download_url", "1 day ago"},
|
||||
{49 * time.Hour, "my_download_url", "2 days ago"},
|
||||
{7 * 24 * time.Hour, "my_download_url", "7 days ago"},
|
||||
{7 * 24 * time.Hour, "my_download_url", "1 week ago"},
|
||||
{8 * 24 * time.Hour, "my_download_url", "1 week ago"},
|
||||
{15 * 24 * time.Hour, "my_download_url", "2 weeks ago"},
|
||||
|
||||
// Testcase index 20
|
||||
{30 * 24 * time.Hour, "my_download_url", "4 weeks ago"},
|
||||
{30 * 24 * time.Hour, "my_download_url", "1 month ago"},
|
||||
{31 * 24 * time.Hour, "my_download_url", "1 month ago"},
|
||||
{61 * 24 * time.Hour, "my_download_url", "2 months ago"},
|
||||
{360 * 24 * time.Hour, "my_download_url", "12 months ago"},
|
||||
{360 * 24 * time.Hour, "my_download_url", "1 year ago"},
|
||||
{361 * 24 * time.Hour, "my_download_url", "1 year ago"},
|
||||
{2 * 365 * 24 * time.Hour, "my_download_url", "2 years ago"},
|
||||
}
|
||||
@@ -74,17 +74,17 @@ func TestPrepareUpdateMessage(t *testing.T) {
|
||||
// fmt.Println(output)
|
||||
switch {
|
||||
case testCase.dlURL == "" && output != "":
|
||||
t.Errorf("Testcase %d: no newer release available but got an update message: %s", i, output)
|
||||
t.Errorf("Testcase %d: no newer release available but got an update message: %s", i+1, output)
|
||||
case output == "" && testCase.dlURL != "" && testCase.older > 0:
|
||||
t.Errorf("Testcase %d: newer release is available but got empty update message!", i)
|
||||
t.Errorf("Testcase %d: newer release is available but got empty update message!", i+1)
|
||||
case output == "" && (testCase.dlURL == "" || testCase.older <= 0):
|
||||
// Valid no update message case. No further
|
||||
// validation needed.
|
||||
continue
|
||||
case !strings.Contains(output, line1):
|
||||
t.Errorf("Testcase %d: output '%s' did not contain line 1: '%s'", i, output, line1)
|
||||
t.Errorf("Testcase %d: output '%s' did not contain line 1: '%s'", i+1, output, line1)
|
||||
case !strings.Contains(output, line2):
|
||||
t.Errorf("Testcase %d: output '%s' did not contain line 2: '%s'", i, output, line2)
|
||||
t.Errorf("Testcase %d: output '%s' did not contain line 2: '%s'", i+1, output, line2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user