github.com/google/go-safeweb@v0.0.0-20231219055052-64d8cfc90fbb/internal/requesttesting/headers/host_test.go (about) 1 // Copyright 2020 Google LLC 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 // https://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 headers 16 17 import ( 18 "context" 19 "net/http" 20 "testing" 21 22 "github.com/google/go-safeweb/internal/requesttesting" 23 ) 24 25 func TestHostHeader(t *testing.T) { 26 var tests = []struct { 27 name string 28 request []byte 29 want string 30 }{ 31 { 32 name: "Basic", 33 request: []byte("GET / HTTP/1.1\r\n" + 34 "Host: localhost:8080\r\n" + 35 "\r\n"), 36 want: "localhost:8080", 37 }, 38 { 39 // https://tools.ietf.org/html/rfc7230#section-5.3.2 40 name: "AbsoluteFormURL", 41 request: []byte("GET http://y.com/asdf HTTP/1.1\r\n" + 42 "Host: x.com\r\n" + 43 "\r\n"), 44 want: "y.com", 45 }, 46 { 47 // https://tools.ietf.org/html/rfc7230#section-5.3.3 48 name: "AuthorityForm", 49 request: []byte("GET y.com:123/asdf HTTP/1.1\r\n" + 50 "Host: x.com\r\n" + 51 "\r\n"), 52 want: "x.com", 53 }, 54 { 55 name: "NoDoubleSlash", 56 request: []byte("GET http:y.com/asdf HTTP/1.1\r\n" + 57 "Host: x.com\r\n" + 58 "\r\n"), 59 want: "x.com", 60 }, 61 { 62 name: "NoSchemaOnlyDoubleSlash", 63 request: []byte("GET //y.com/asdf HTTP/1.1\r\n" + 64 "Host: x.com\r\n" + 65 "\r\n"), 66 want: "x.com", 67 }, 68 } 69 70 for _, tt := range tests { 71 t.Run(tt.name, func(t *testing.T) { 72 resp, err := requesttesting.MakeRequest(context.Background(), tt.request, func(r *http.Request) { 73 if len(r.Header) != 0 { 74 t.Errorf("len(r.Header) got: %v want: 0", len(r.Header)) 75 } 76 77 if r.Host != tt.want { 78 t.Errorf("r.Host got: %q want: %q", r.Host, tt.want) 79 } 80 }) 81 if err != nil { 82 t.Fatalf("MakeRequest() got err: %v", err) 83 } 84 85 if got, want := extractStatus(resp), statusOK; !matchStatus(got, want) { 86 t.Errorf("status code got: %q want: %q", got, want) 87 } 88 }) 89 } 90 } 91 92 func TestHostHeaderMultiple(t *testing.T) { 93 request := []byte("GET / HTTP/1.1\r\n" + 94 "Host: x.com\r\n" + 95 "Host: y.com\r\n" + 96 "\r\n") 97 98 resp, err := requesttesting.MakeRequest(context.Background(), request, nil) 99 if err != nil { 100 t.Fatalf("MakeRequest() got err: %v", err) 101 } 102 103 if got, want := extractStatus(resp), statusBadRequestPrefix; !matchStatus(got, want) { 104 t.Errorf("status code got: %q want: %q", got, want) 105 } 106 } 107 108 func TestAbsoluteFormURLInvalidSchema(t *testing.T) { 109 // When sending a request using the absolute 110 // form as the request target, any schema is currently 111 // accepted. 112 // 113 // The desired behavior would instead be to only 114 // accept http or https as schemas and to respond 115 // with a 400 (Bad Request) when the server receives 116 // any other schema. 117 118 request := []byte("GET x://y.com/asdf HTTP/1.1\r\n" + 119 "Host: x.com\r\n" + 120 "\r\n") 121 122 t.Run("Current behavior", func(t *testing.T) { 123 resp, err := requesttesting.MakeRequest(context.Background(), request, func(r *http.Request) { 124 if len(r.Header) != 0 { 125 t.Errorf("len(r.Header) got: %v want: 0", len(r.Header)) 126 } 127 128 if want := "y.com"; r.Host != want { 129 t.Errorf("r.Host got: %q want: %q", r.Host, want) 130 } 131 }) 132 if err != nil { 133 t.Fatalf("MakeRequest() got err: %v want: nil", err) 134 } 135 136 if got, want := extractStatus(resp), statusOK; !matchStatus(got, want) { 137 t.Errorf("status code got: %q want: %q", got, want) 138 } 139 }) 140 141 t.Run("Desired behavior", func(t *testing.T) { 142 t.Skip() 143 resp, err := requesttesting.MakeRequest(context.Background(), request, func(r *http.Request) { 144 t.Error("Expected handler to not be called!") 145 }) 146 if err != nil { 147 t.Fatalf("MakeRequest() got err: %v want: nil", err) 148 } 149 150 if got, want := extractStatus(resp), statusBadRequestPrefix; !matchStatus(got, want) { 151 t.Errorf("status code got: %q want: %q", got, want) 152 } 153 }) 154 }