From e3b2c680853cb9b99bbbc267ee3a330464bd3b94 Mon Sep 17 00:00:00 2001 From: Makis Maropoulos Date: Thu, 7 Jul 2016 17:17:34 +0200 Subject: [PATCH] Parse server's addr before use it --- config/server.go | 32 ++++++++++++++++++++++ context.go | 2 +- http.go | 70 +++++++++++------------------------------------- http_test.go | 50 ++++++++++++++++++++++++++++++++++ iris.go | 2 +- 5 files changed, 100 insertions(+), 56 deletions(-) diff --git a/config/server.go b/config/server.go index 29be03bc..229e8c61 100644 --- a/config/server.go +++ b/config/server.go @@ -3,6 +3,7 @@ package config import ( "os" "strconv" + "strings" "github.com/imdario/mergo" "github.com/kataras/fasthttp" @@ -51,6 +52,37 @@ type Server struct { Virtual bool } +// ServerParseAddr parses the listening addr and returns this +func ServerParseAddr(listeningAddr string) string { + // check if addr has :port, if not do it +:80 ,we need the hostname for many cases + a := listeningAddr + if a == "" { + // check for os environments + if oshost := os.Getenv("HOST"); oshost != "" { + a = oshost + } else if oshost := os.Getenv("ADDR"); oshost != "" { + a = oshost + } else if osport := os.Getenv("PORT"); osport != "" { + a = ":" + osport + } + + if a == "" { + a = DefaultServerAddr + } + + } + if portIdx := strings.IndexByte(a, ':'); portIdx == 0 { + // if contains only :port ,then the : is the first letter, so we dont have setted a hostname, lets set it + a = DefaultServerHostname + a + } + if portIdx := strings.IndexByte(a, ':'); portIdx < 0 { + // missing port part, add it + a = a + ":80" + } + + return a +} + // DefaultServer returns the default configs for the server func DefaultServer() Server { return Server{ListeningAddr: DefaultServerAddr, diff --git a/context.go b/context.go index 1136c1c6..aaebed1d 100644 --- a/context.go +++ b/context.go @@ -220,7 +220,7 @@ func (ctx *Context) HostString() string { func (ctx *Context) VirtualHostname() string { realhost := ctx.HostString() hostname := realhost - virtualhost := ctx.framework.Servers.Main().VirtualHostname() + virtualhost := ctx.framework.Servers.Main().Hostname() if portIdx := strings.IndexByte(hostname, ':'); portIdx > 0 { hostname = hostname[0:portIdx] diff --git a/http.go b/http.go index 66011974..1826a479 100644 --- a/http.go +++ b/http.go @@ -230,7 +230,6 @@ func StatusText(code int) string { var ( errServerPortAlreadyUsed = errors.New("Server can't run, port is already used") errServerAlreadyStarted = errors.New("Server is already started and listening") - errServerConfigMissing = errors.New("Empty Config for server") errServerHandlerMissing = errors.New("Handler is missing from server, can't start without handler") errServerIsClosed = errors.New("Can't close the server, propably is already closed or never started") errServerRemoveUnix = errors.New("Unexpected error when trying to remove unix socket file. Addr: %s | Trace: %s") @@ -256,9 +255,15 @@ type ( // newServer returns a pointer to a Server object, and set it's options if any, nothing more func newServer(cfg config.Server) *Server { s := &Server{Server: &fasthttp.Server{Name: config.ServerName}, Config: cfg} + s.prepare() return s } +// prepare just prepares the listening addr +func (s *Server) prepare() { + s.Config.ListeningAddr = config.ServerParseAddr(s.Config.ListeningAddr) +} + // IsListening returns true if server is listening/started, otherwise false func (s *Server) IsListening() bool { if s == nil { @@ -288,43 +293,28 @@ func (s *Server) Listener() net.Listener { return s.listener } -// Host returns the Listener().Addr().String(), if server is not listening it returns the config.ListeningAddr +// Host returns the registered host for the server func (s *Server) Host() (host string) { - if s.IsListening() { - return s.Listener().Addr().String() - } return s.Config.ListeningAddr - } // Port returns the port which server listening for // if no port given with the ListeningAddr, it returns 80 func (s *Server) Port() (port int) { a := s.Config.ListeningAddr - if portIdx := strings.IndexByte(a, ':'); portIdx == 0 { + if portIdx := strings.IndexByte(a, ':'); portIdx != -1 { p, err := strconv.Atoi(a[portIdx+1:]) if err != nil { port = 80 } else { port = p } + } else { + port = 80 } return } -// VirtualHost returns the s.Config.ListeningAddr -// -func (s *Server) VirtualHost() (host string) { - // check the addr if :8080 do it 0.0.0.0:8080 ,we need the hostname for many cases - a := s.Config.ListeningAddr - //check if contains hostname, we need the full host, :8080 should be : 127.0.0.1:8080 - if portIdx := strings.IndexByte(a, ':'); portIdx == 0 { - // then the : is the first letter, so we dont have setted a hostname, lets set it - s.Config.ListeningAddr = config.DefaultServerHostname + a - } - return s.Config.ListeningAddr -} - // FullHost returns the scheme+host func (s *Server) FullHost() string { scheme := "http://" @@ -332,30 +322,12 @@ func (s *Server) FullHost() string { if s.IsSecure() || (s.Config.CertFile != "" && s.Config.KeyFile != "") { scheme = "https://" } - return scheme + s.VirtualHost() + return scheme + s.Host() } -// Hostname returns the hostname part only, if host == localhost:8080 it will return the localhost -// if server is not listening it returns the config.ListeningAddr's hostname part -func (s *Server) Hostname() (hostname string) { - if s.IsListening() { - fullhost := s.Listener().Addr().String() - hostname = fullhost[0:strings.IndexByte(fullhost, ':')] // no the port - } else { - hostname = s.VirtualHostname() - } - return -} - -// VirtualHostname returns the hostname that user registers, host path maybe differs from the real which is HostString, which taken from a net.listener -func (s *Server) VirtualHostname() (hostname string) { - hostname = s.Config.ListeningAddr - if idx := strings.IndexByte(hostname, ':'); idx > 1 { // at least after second char - hostname = hostname[0:idx] - } else { - hostname = config.DefaultServerHostname - } - return +// Hostname returns the hostname part of the host (host expect port) +func (s *Server) Hostname() string { + return s.Host()[0:strings.IndexByte(s.Host(), ':')] // no the port } func (s *Server) listen() error { @@ -420,17 +392,7 @@ func (s *Server) Open(h fasthttp.RequestHandler) error { return errServerAlreadyStarted.Return() } - if s.Config.ListeningAddr == "" { - return errServerConfigMissing.Return() - } - - // check the addr if :8080 do it 0.0.0.0:8080 ,we need the hostname for many cases - a := s.Config.ListeningAddr - //check if contains hostname, we need the full host, :8080 should be : 127.0.0.1:8080 - if portIdx := strings.IndexByte(a, ':'); portIdx == 0 { - // then the : is the first letter, so we dont have setted a hostname, lets set it - s.Config.ListeningAddr = config.DefaultServerHostname + a - } + s.prepare() // do it again for any case if s.Config.MaxRequestBodySize > config.DefaultMaxRequestBodySize { s.Server.MaxRequestBodySize = int(s.Config.MaxRequestBodySize) @@ -570,7 +532,7 @@ func (s *ServerList) OpenAll() error { break } if i == l { - s.mux.setHostname(s.servers[i].VirtualHostname()) + s.mux.setHostname(s.servers[i].Hostname()) } } diff --git a/http_test.go b/http_test.go index e99f45cf..12d2086f 100644 --- a/http_test.go +++ b/http_test.go @@ -69,6 +69,56 @@ const ( ` ) +func TestServerHost(t *testing.T) { + var server1, server2, server3 Server + var expectedHost1 = "mydomain.com:1993" + var expectedHost2 = "mydomain.com:80" + var expectedHost3 = "127.0.0.1:9090" + server1.Config.ListeningAddr = expectedHost1 + server2.Config.ListeningAddr = "mydomain.com" + server3.Config.ListeningAddr = ":9090" + + server1.prepare() + server2.prepare() + server3.prepare() + + if server1.Host() != expectedHost1 { + t.Fatalf("Expecting server 1's host to be %s but we got %s", expectedHost1, server1.Host()) + } + if server2.Host() != expectedHost2 { + t.Fatalf("Expecting server 2's host to be %s but we got %s", expectedHost2, server2.Host()) + } + if server3.Host() != expectedHost3 { + t.Fatalf("Expecting server 3's host to be %s but we got %s", expectedHost3, server3.Host()) + } +} + +func TestServerHostname(t *testing.T) { + var server Server + var expectedHostname = "mydomain.com" + server.Config.ListeningAddr = expectedHostname + ":1993" + server.prepare() + if server.Hostname() != expectedHostname { + t.Fatalf("Expecting server's hostname to be %s but we got %s", expectedHostname, server.Hostname()) + } +} + +func TestServerPort(t *testing.T) { + var server1, server2 Server + expectedPort1 := 8080 + expectedPort2 := 80 + server1.Config.ListeningAddr = "mydomain.com:8080" + server2.Config.ListeningAddr = "mydomain.com" + server1.prepare() + server2.prepare() + if server1.Port() != expectedPort1 { + t.Fatalf("Expecting server 1's port to be %d but we got %d", expectedPort1, server1.Port()) + } + if server2.Port() != expectedPort2 { + t.Fatalf("Expecting server 2's port to be %d but we got %d", expectedPort2, server2.Port()) + } +} + // Contains the server test for multi running servers func TestMultiRunningServers_v1(t *testing.T) { host := "mydomain.com:443" // you have to add it to your hosts file( for windows, as 127.0.0.1 mydomain.com) diff --git a/iris.go b/iris.go index 578fa141..3b766b1c 100644 --- a/iris.go +++ b/iris.go @@ -656,7 +656,7 @@ func (s *Framework) URL(routeName string, args ...interface{}) (url string) { scheme = "https://" } - host := srv.VirtualHost() + host := srv.Host() arguments := args[0:] // join arrays as arguments