github.com/google/cloudprober@v0.11.3/probes/http/request_test.go (about) 1 // Copyright 2019-2020 The Cloudprober Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package http 16 17 import ( 18 "fmt" 19 "net" 20 "testing" 21 22 "github.com/golang/protobuf/proto" 23 configpb "github.com/google/cloudprober/probes/http/proto" 24 "github.com/google/cloudprober/probes/options" 25 "github.com/google/cloudprober/targets" 26 "github.com/google/cloudprober/targets/endpoint" 27 ) 28 29 func TestHostWithPort(t *testing.T) { 30 for _, test := range []struct { 31 host string 32 port int 33 wantHostPort string 34 }{ 35 { 36 host: "target1.ns.cluster.local", 37 wantHostPort: "target1.ns.cluster.local", 38 }, 39 { 40 host: "target1.ns.cluster.local", 41 port: 8080, 42 wantHostPort: "target1.ns.cluster.local:8080", 43 }, 44 } { 45 t.Run(fmt.Sprintf("host:%s,port:%d", test.host, test.port), func(t *testing.T) { 46 hostPort := hostWithPort(test.host, test.port) 47 if hostPort != test.wantHostPort { 48 t.Errorf("hostPort: %s, want: %s", hostPort, test.wantHostPort) 49 } 50 }) 51 } 52 } 53 54 func TestURLHostAndHeaderForTarget(t *testing.T) { 55 for _, test := range []struct { 56 name string 57 fqdn string 58 probeHostHeader string 59 port int 60 wantHostHeader string 61 wantURLHost string 62 }{ 63 { 64 name: "target1", 65 fqdn: "target1.ns.cluster.local", 66 probeHostHeader: "svc.target", 67 port: 8080, 68 wantHostHeader: "svc.target", 69 wantURLHost: "target1.ns.cluster.local", 70 }, 71 { 72 name: "target1", 73 fqdn: "target1.ns.cluster.local", 74 probeHostHeader: "", 75 port: 8080, 76 wantHostHeader: "target1.ns.cluster.local:8080", 77 wantURLHost: "target1.ns.cluster.local", 78 }, 79 { 80 name: "target1", 81 fqdn: "target1.ns.cluster.local", 82 probeHostHeader: "", 83 port: 0, 84 wantHostHeader: "target1.ns.cluster.local", 85 wantURLHost: "target1.ns.cluster.local", 86 }, 87 { 88 name: "target1", 89 fqdn: "", 90 probeHostHeader: "", 91 port: 8080, 92 wantHostHeader: "target1:8080", 93 wantURLHost: "target1", 94 }, 95 { 96 name: "target1", 97 fqdn: "", 98 probeHostHeader: "", 99 port: 0, 100 wantHostHeader: "target1", 101 wantURLHost: "target1", 102 }, 103 } { 104 t.Run(fmt.Sprintf("test:%+v", test), func(t *testing.T) { 105 target := endpoint.Endpoint{ 106 Name: test.name, 107 Labels: map[string]string{"fqdn": test.fqdn}, 108 } 109 110 hostHeader := hostHeaderForTarget(target, test.probeHostHeader, test.port) 111 if hostHeader != test.wantHostHeader { 112 t.Errorf("Got host header: %s, want header: %s", hostHeader, test.wantHostHeader) 113 } 114 115 urlHost := urlHostForTarget(target) 116 if urlHost != test.wantURLHost { 117 t.Errorf("Got URL host: %s, want URL host: %s", urlHost, test.wantURLHost) 118 } 119 }) 120 } 121 } 122 123 func TestRelURLforTarget(t *testing.T) { 124 for _, test := range []struct { 125 targetURLLabel string 126 probeURL string 127 wantRelURL string 128 }{ 129 { 130 // Both set, probe URL wins. 131 targetURLLabel: "/target-url", 132 probeURL: "/metrics", 133 wantRelURL: "/metrics", 134 }, 135 { 136 // Only target label set. 137 targetURLLabel: "/target-url", 138 probeURL: "", 139 wantRelURL: "/target-url", 140 }, 141 { 142 // Nothing set, we get nothing. 143 targetURLLabel: "", 144 probeURL: "", 145 wantRelURL: "", 146 }, 147 } { 148 t.Run(fmt.Sprintf("test:%+v", test), func(t *testing.T) { 149 target := endpoint.Endpoint{ 150 Name: "test-target", 151 Labels: map[string]string{relURLLabel: test.targetURLLabel}, 152 } 153 154 relURL := relURLForTarget(target, test.probeURL) 155 if relURL != test.wantRelURL { 156 t.Errorf("Got URL: %s, want: %s", relURL, test.wantRelURL) 157 } 158 }) 159 } 160 } 161 162 // Following tests are more comprehensive tests for request URL and host header. 163 type testData struct { 164 desc string 165 targetName string 166 targetFQDN string // Make target have this "fqdn" label. 167 resolvedIP string // IP that will be returned by the test resolve function. 168 169 // Probe configuration parameters 170 resolveFirst bool 171 probeHost string 172 173 // Used by TestURLHostAndHeaderForTarget to verify URL host, and 174 // TestRequestHostAndURL to build URL to verify. 175 wantURLHost string 176 } 177 178 func createRequestAndVerify(t *testing.T, td testData, probePort, targetPort, expectedPort int, resolveF resolveFunc) { 179 t.Helper() 180 181 p := &Probe{ 182 protocol: "http", 183 c: &configpb.ProbeConf{ 184 ResolveFirst: proto.Bool(td.resolveFirst), 185 }, 186 opts: &options.Options{Targets: targets.StaticTargets(td.targetName)}, 187 } 188 189 if probePort != 0 { 190 p.c.Port = proto.Int32(int32(probePort)) 191 } 192 193 if td.probeHost != "" { 194 p.c.Headers = append(p.c.Headers, &configpb.ProbeConf_Header{ 195 Name: proto.String("Host"), 196 Value: proto.String(td.probeHost), 197 }) 198 } 199 200 target := endpoint.Endpoint{ 201 Name: td.targetName, 202 Port: targetPort, 203 Labels: map[string]string{ 204 "fqdn": td.targetFQDN, 205 }, 206 } 207 req := p.httpRequestForTarget(target, resolveF) 208 209 wantURL := fmt.Sprintf("http://%s", hostWithPort(td.wantURLHost, expectedPort)) 210 if req.URL.String() != wantURL { 211 t.Errorf("HTTP req URL: %s, wanted: %s", req.URL.String(), wantURL) 212 } 213 214 // Note that we test hostHeaderForTarget independently. 215 wantHostHeader := hostHeaderForTarget(target, td.probeHost, expectedPort) 216 if req.Host != wantHostHeader { 217 t.Errorf("HTTP req.Host: %s, wanted: %s", req.Host, wantHostHeader) 218 } 219 } 220 221 func testRequestHostAndURLWithDifferentPorts(t *testing.T, td testData) { 222 t.Helper() 223 224 var resolveF resolveFunc 225 if td.resolveFirst { 226 resolveF = func(target string, ipVer int) (net.IP, error) { 227 return net.ParseIP(td.resolvedIP), nil 228 } 229 } 230 231 for _, ports := range []struct { 232 probePort int 233 targetPort int 234 expectedPort int 235 }{ 236 { 237 probePort: 0, 238 targetPort: 0, 239 expectedPort: 0, 240 }, 241 { 242 probePort: 8080, 243 targetPort: 9313, 244 expectedPort: 8080, // probe port wins 245 }, 246 { 247 probePort: 0, 248 targetPort: 9313, 249 expectedPort: 9313, // target port wins 250 }, 251 } { 252 t.Run(fmt.Sprintf("%s_probe_port_%d_endpoint_port_%d", td.desc, ports.probePort, ports.targetPort), func(t *testing.T) { 253 createRequestAndVerify(t, td, ports.probePort, ports.targetPort, ports.expectedPort, resolveF) 254 }) 255 } 256 } 257 258 func TestRequestHostAndURL(t *testing.T) { 259 tests := []testData{ 260 { 261 desc: "no_resolve_first,no_probe_host_header", 262 targetName: "test-target.com", 263 wantURLHost: "test-target.com", 264 }, 265 { 266 desc: "no_resolve_first,fqdn,no_probe_host_header", 267 targetName: "test-target.com", 268 targetFQDN: "test.svc.cluster.local", 269 wantURLHost: "test.svc.cluster.local", 270 }, 271 { 272 desc: "no_resolve_first,host_header", 273 targetName: "test-target.com", 274 probeHost: "test-host", 275 wantURLHost: "test-target.com", 276 }, 277 { 278 desc: "ipv6_literal_host,no_probe_host_header", 279 targetName: "2600:2d00:4030:a47:c0a8:210d:0:0", // IPv6 literal host 280 wantURLHost: "[2600:2d00:4030:a47:c0a8:210d:0:0]", 281 }, 282 { 283 desc: "resolve_first,no_probe_host_header", 284 targetName: "localhost", 285 resolveFirst: true, 286 resolvedIP: "127.0.0.1", 287 wantURLHost: "127.0.0.1", 288 }, 289 { 290 desc: "resolve_first,ipv6,no_probe_host_header", 291 targetName: "localhost", 292 resolveFirst: true, 293 resolvedIP: "2600:2d00:4030:a47:c0a8:210d:0:0", // Resolved IP 294 wantURLHost: "[2600:2d00:4030:a47:c0a8:210d::]", // IPv6 literal host 295 }, 296 { 297 desc: "resolve_first,probe_host_header", 298 targetName: "localhost", 299 resolveFirst: true, 300 probeHost: "test-host", 301 resolvedIP: "127.0.0.1", 302 wantURLHost: "127.0.0.1", 303 }, 304 } 305 306 for _, td := range tests { 307 t.Run(td.desc, func(t *testing.T) { 308 testRequestHostAndURLWithDifferentPorts(t, td) 309 }) 310 } 311 }