github.com/xmplusdev/xmcore@v1.8.11-0.20240412132628-5518b55526af/transport/internet/headers/http/http_test.go (about) 1 package http_test 2 3 import ( 4 "bufio" 5 "bytes" 6 "context" 7 "crypto/rand" 8 "strings" 9 "testing" 10 "time" 11 12 "github.com/xmplusdev/xmcore/common" 13 "github.com/xmplusdev/xmcore/common/buf" 14 "github.com/xmplusdev/xmcore/common/net" 15 . "github.com/xmplusdev/xmcore/transport/internet/headers/http" 16 ) 17 18 func TestReaderWriter(t *testing.T) { 19 cache := buf.New() 20 b := buf.New() 21 common.Must2(b.WriteString("abcd" + ENDING)) 22 writer := NewHeaderWriter(b) 23 err := writer.Write(cache) 24 common.Must(err) 25 if v := cache.Len(); v != 8 { 26 t.Error("cache len: ", v) 27 } 28 _, err = cache.Write([]byte{'e', 'f', 'g'}) 29 common.Must(err) 30 31 reader := &HeaderReader{} 32 _, err = reader.Read(cache) 33 if err != nil && !strings.HasPrefix(err.Error(), "malformed HTTP request") { 34 t.Error("unknown error ", err) 35 } 36 } 37 38 func TestRequestHeader(t *testing.T) { 39 auth, err := NewAuthenticator(context.Background(), &Config{ 40 Request: &RequestConfig{ 41 Uri: []string{"/"}, 42 Header: []*Header{ 43 { 44 Name: "Test", 45 Value: []string{"Value"}, 46 }, 47 }, 48 }, 49 }) 50 common.Must(err) 51 52 cache := buf.New() 53 err = auth.GetClientWriter().Write(cache) 54 common.Must(err) 55 56 if cache.String() != "GET / HTTP/1.1\r\nTest: Value\r\n\r\n" { 57 t.Error("cache: ", cache.String()) 58 } 59 } 60 61 func TestLongRequestHeader(t *testing.T) { 62 payload := make([]byte, buf.Size+2) 63 common.Must2(rand.Read(payload[:buf.Size-2])) 64 copy(payload[buf.Size-2:], ENDING) 65 payload = append(payload, []byte("abcd")...) 66 67 reader := HeaderReader{} 68 _, err := reader.Read(bytes.NewReader(payload)) 69 70 if err != nil && !(strings.HasPrefix(err.Error(), "invalid") || strings.HasPrefix(err.Error(), "malformed")) { 71 t.Error("unknown error ", err) 72 } 73 } 74 75 func TestConnection(t *testing.T) { 76 auth, err := NewAuthenticator(context.Background(), &Config{ 77 Request: &RequestConfig{ 78 Method: &Method{Value: "Post"}, 79 Uri: []string{"/testpath"}, 80 Header: []*Header{ 81 { 82 Name: "Host", 83 Value: []string{"www.example.com", "www.google.com"}, 84 }, 85 { 86 Name: "User-Agent", 87 Value: []string{"Test-Agent"}, 88 }, 89 }, 90 }, 91 Response: &ResponseConfig{ 92 Version: &Version{ 93 Value: "1.1", 94 }, 95 Status: &Status{ 96 Code: "404", 97 Reason: "Not Found", 98 }, 99 }, 100 }) 101 common.Must(err) 102 103 listener, err := net.Listen("tcp", "127.0.0.1:0") 104 common.Must(err) 105 106 go func() { 107 conn, err := listener.Accept() 108 common.Must(err) 109 authConn := auth.Server(conn) 110 b := make([]byte, 256) 111 for { 112 n, err := authConn.Read(b) 113 if err != nil { 114 break 115 } 116 _, err = authConn.Write(b[:n]) 117 common.Must(err) 118 } 119 }() 120 121 conn, err := net.DialTCP("tcp", nil, listener.Addr().(*net.TCPAddr)) 122 common.Must(err) 123 124 authConn := auth.Client(conn) 125 defer authConn.Close() 126 127 authConn.Write([]byte("Test payload")) 128 authConn.Write([]byte("Test payload 2")) 129 130 expectedResponse := "Test payloadTest payload 2" 131 actualResponse := make([]byte, 256) 132 deadline := time.Now().Add(time.Second * 5) 133 totalBytes := 0 134 for { 135 n, err := authConn.Read(actualResponse[totalBytes:]) 136 common.Must(err) 137 totalBytes += n 138 if totalBytes >= len(expectedResponse) || time.Now().After(deadline) { 139 break 140 } 141 } 142 143 if string(actualResponse[:totalBytes]) != expectedResponse { 144 t.Error("response: ", string(actualResponse[:totalBytes])) 145 } 146 } 147 148 func TestConnectionInvPath(t *testing.T) { 149 auth, err := NewAuthenticator(context.Background(), &Config{ 150 Request: &RequestConfig{ 151 Method: &Method{Value: "Post"}, 152 Uri: []string{"/testpath"}, 153 Header: []*Header{ 154 { 155 Name: "Host", 156 Value: []string{"www.example.com", "www.google.com"}, 157 }, 158 { 159 Name: "User-Agent", 160 Value: []string{"Test-Agent"}, 161 }, 162 }, 163 }, 164 Response: &ResponseConfig{ 165 Version: &Version{ 166 Value: "1.1", 167 }, 168 Status: &Status{ 169 Code: "404", 170 Reason: "Not Found", 171 }, 172 }, 173 }) 174 common.Must(err) 175 176 authR, err := NewAuthenticator(context.Background(), &Config{ 177 Request: &RequestConfig{ 178 Method: &Method{Value: "Post"}, 179 Uri: []string{"/testpathErr"}, 180 Header: []*Header{ 181 { 182 Name: "Host", 183 Value: []string{"www.example.com", "www.google.com"}, 184 }, 185 { 186 Name: "User-Agent", 187 Value: []string{"Test-Agent"}, 188 }, 189 }, 190 }, 191 Response: &ResponseConfig{ 192 Version: &Version{ 193 Value: "1.1", 194 }, 195 Status: &Status{ 196 Code: "404", 197 Reason: "Not Found", 198 }, 199 }, 200 }) 201 common.Must(err) 202 203 listener, err := net.Listen("tcp", "127.0.0.1:0") 204 common.Must(err) 205 206 go func() { 207 conn, err := listener.Accept() 208 common.Must(err) 209 authConn := auth.Server(conn) 210 b := make([]byte, 256) 211 for { 212 n, err := authConn.Read(b) 213 if err != nil { 214 authConn.Close() 215 break 216 } 217 _, err = authConn.Write(b[:n]) 218 common.Must(err) 219 } 220 }() 221 222 conn, err := net.DialTCP("tcp", nil, listener.Addr().(*net.TCPAddr)) 223 common.Must(err) 224 225 authConn := authR.Client(conn) 226 defer authConn.Close() 227 228 authConn.Write([]byte("Test payload")) 229 authConn.Write([]byte("Test payload 2")) 230 231 expectedResponse := "Test payloadTest payload 2" 232 actualResponse := make([]byte, 256) 233 deadline := time.Now().Add(time.Second * 5) 234 totalBytes := 0 235 for { 236 n, err := authConn.Read(actualResponse[totalBytes:]) 237 if err == nil { 238 t.Error("Error Expected", err) 239 } else { 240 return 241 } 242 totalBytes += n 243 if totalBytes >= len(expectedResponse) || time.Now().After(deadline) { 244 break 245 } 246 } 247 } 248 249 func TestConnectionInvReq(t *testing.T) { 250 auth, err := NewAuthenticator(context.Background(), &Config{ 251 Request: &RequestConfig{ 252 Method: &Method{Value: "Post"}, 253 Uri: []string{"/testpath"}, 254 Header: []*Header{ 255 { 256 Name: "Host", 257 Value: []string{"www.example.com", "www.google.com"}, 258 }, 259 { 260 Name: "User-Agent", 261 Value: []string{"Test-Agent"}, 262 }, 263 }, 264 }, 265 Response: &ResponseConfig{ 266 Version: &Version{ 267 Value: "1.1", 268 }, 269 Status: &Status{ 270 Code: "404", 271 Reason: "Not Found", 272 }, 273 }, 274 }) 275 common.Must(err) 276 277 listener, err := net.Listen("tcp", "127.0.0.1:0") 278 common.Must(err) 279 280 go func() { 281 conn, err := listener.Accept() 282 common.Must(err) 283 authConn := auth.Server(conn) 284 b := make([]byte, 256) 285 for { 286 n, err := authConn.Read(b) 287 if err != nil { 288 authConn.Close() 289 break 290 } 291 _, err = authConn.Write(b[:n]) 292 common.Must(err) 293 } 294 }() 295 296 conn, err := net.DialTCP("tcp", nil, listener.Addr().(*net.TCPAddr)) 297 common.Must(err) 298 299 conn.Write([]byte("ABCDEFGHIJKMLN\r\n\r\n")) 300 l, _, err := bufio.NewReader(conn).ReadLine() 301 common.Must(err) 302 if !strings.HasPrefix(string(l), "HTTP/1.1 400 Bad Request") { 303 t.Error("Resp to non http conn", string(l)) 304 } 305 }