Browse Source

pkg/httputil: add "GetHostname"

Signed-off-by: Gyuho Lee <gyuhox@gmail.com>
Gyuho Lee 7 years ago
parent
commit
418bb92963
2 changed files with 80 additions and 2 deletions
  1. 30 2
      pkg/httputil/httputil.go
  2. 50 0
      pkg/httputil/httputil_test.go

+ 30 - 2
pkg/httputil/httputil.go

@@ -1,22 +1,50 @@
+// Copyright 2018 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
 // Copyright 2015 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// borrowed from golang/net/context/ctxhttp/cancelreq.go
-
 // Package httputil provides HTTP utility functions.
 package httputil
 
 import (
 	"io"
 	"io/ioutil"
+	"net"
 	"net/http"
 )
 
 // GracefulClose drains http.Response.Body until it hits EOF
 // and closes it. This prevents TCP/TLS connections from closing,
 // therefore available for reuse.
+// Borrowed from golang/net/context/ctxhttp/cancelreq.go.
 func GracefulClose(resp *http.Response) {
 	io.Copy(ioutil.Discard, resp.Body)
 	resp.Body.Close()
 }
+
+// GetHostname returns the hostname from request Host field.
+// It returns empty string, if Host field contains invalid
+// value (e.g. "localhost:::" with too many colons).
+func GetHostname(req *http.Request) string {
+	if req == nil {
+		return ""
+	}
+	h, _, err := net.SplitHostPort(req.Host)
+	if err != nil {
+		return req.Host
+	}
+	return h
+}

+ 50 - 0
pkg/httputil/httputil_test.go

@@ -0,0 +1,50 @@
+// Copyright 2018 The etcd Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package httputil
+
+import (
+	"net/http"
+	"testing"
+)
+
+func TestGetHostname(t *testing.T) {
+	tt := []struct {
+		req  *http.Request
+		host string
+	}{
+		{&http.Request{Host: "localhost"}, "localhost"},
+		{&http.Request{Host: "localhost:2379"}, "localhost"},
+		{&http.Request{Host: "localhost."}, "localhost."},
+		{&http.Request{Host: "localhost.:2379"}, "localhost."},
+		{&http.Request{Host: "127.0.0.1"}, "127.0.0.1"},
+		{&http.Request{Host: "127.0.0.1:2379"}, "127.0.0.1"},
+
+		{&http.Request{Host: "localhos"}, "localhos"},
+		{&http.Request{Host: "localhos:2379"}, "localhos"},
+		{&http.Request{Host: "localhos."}, "localhos."},
+		{&http.Request{Host: "localhos.:2379"}, "localhos."},
+		{&http.Request{Host: "1.2.3.4"}, "1.2.3.4"},
+		{&http.Request{Host: "1.2.3.4:2379"}, "1.2.3.4"},
+
+		// too many colons in address
+		{&http.Request{Host: "localhost:::::"}, "localhost:::::"},
+	}
+	for i := range tt {
+		hv := GetHostname(tt[i].req)
+		if hv != tt[i].host {
+			t.Errorf("#%d: %q expected host %q, got '%v'", i, tt[i].req.Host, tt[i].host, hv)
+		}
+	}
+}