blob: dcfe56199ed709141d429b7ae29c70884cb88ae2 [file] [log] [blame]
Filip Tehlarb15a0002022-11-10 12:34:17 +01001package main
2
Filip Tehlarc204c872022-12-21 08:59:16 +01003import (
Matus Fabian82ad9662024-06-04 19:00:00 +02004 "bytes"
Filip Tehlar8df3de42023-01-27 13:14:34 +01005 "fmt"
Matus Fabian2d1f0e62024-06-06 11:24:36 +02006 "github.com/onsi/gomega/gmeasure"
7 "io"
Matus Fabiand086a362024-06-27 13:20:10 +02008 "net"
Matus Fabianb7a9ed72024-05-10 16:20:40 +02009 "net/http"
Matus Fabiand086a362024-06-27 13:20:10 +020010 "net/http/httptrace"
11 "os"
Matus Fabian5c4c1b62024-06-28 16:11:04 +020012 "sync"
Adrian Villincee15aa2024-03-14 11:42:55 -040013 "time"
14
Adrian Villin4677d922024-06-14 09:32:39 +020015 . "fd.io/hs-test/infra"
Matus Fabian5c4c1b62024-06-28 16:11:04 +020016 . "github.com/onsi/ginkgo/v2"
Filip Tehlarc204c872022-12-21 08:59:16 +010017)
18
Adrian Villincee15aa2024-03-14 11:42:55 -040019func init() {
Adrian Villin4677d922024-06-14 09:32:39 +020020 RegisterVethTests(HttpCliTest, HttpCliConnectErrorTest)
Matus Fabiand086a362024-06-27 13:20:10 +020021 RegisterNoTopoTests(HeaderServerTest, HttpPersistentConnectionTest, HttpPipeliningTest,
Matus Fabianb7a9ed72024-05-10 16:20:40 +020022 HttpStaticMovedTest, HttpStaticNotFoundTest, HttpCliMethodNotAllowedTest,
Matus Fabian82ad9662024-06-04 19:00:00 +020023 HttpCliBadRequestTest, HttpStaticBuildInUrlGetIfStatsTest, HttpStaticBuildInUrlPostIfStatsTest,
24 HttpInvalidRequestLineTest, HttpMethodNotImplementedTest, HttpInvalidHeadersTest,
25 HttpContentLengthTest, HttpStaticBuildInUrlGetIfListTest, HttpStaticBuildInUrlGetVersionTest,
26 HttpStaticMacTimeTest, HttpStaticBuildInUrlGetVersionVerboseTest, HttpVersionNotSupportedTest,
27 HttpInvalidContentLengthTest, HttpInvalidTargetSyntaxTest, HttpStaticPathTraversalTest, HttpUriDecodeTest,
Matus Fabian8ca6ce62024-06-20 17:08:26 +020028 HttpHeadersTest, HttpStaticFileHandler)
Matus Fabianc712de52024-07-24 12:56:14 +020029 RegisterNoTopoSoloTests(HttpStaticPromTest, HttpTpsTest, HttpTpsInterruptModeTest, PromConcurrentConnections,
30 PromMemLeakTest)
Adrian Villincee15aa2024-03-14 11:42:55 -040031}
32
Matus Fabian5409d332024-05-28 13:39:13 +020033const wwwRootPath = "/tmp/www_root"
34
Matus Fabian2d1f0e62024-06-06 11:24:36 +020035func httpDownloadBenchmark(s *HstSuite, experiment *gmeasure.Experiment, data interface{}) {
36 url, isValid := data.(string)
Adrian Villin4677d922024-06-14 09:32:39 +020037 s.AssertEqual(true, isValid)
38 client := NewHttpClient()
Matus Fabian2d1f0e62024-06-06 11:24:36 +020039 req, err := http.NewRequest("GET", url, nil)
Adrian Villin4677d922024-06-14 09:32:39 +020040 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian2d1f0e62024-06-06 11:24:36 +020041 t := time.Now()
42 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +020043 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian2d1f0e62024-06-06 11:24:36 +020044 defer resp.Body.Close()
Adrian Villin4677d922024-06-14 09:32:39 +020045 s.AssertEqual(200, resp.StatusCode)
Matus Fabian2d1f0e62024-06-06 11:24:36 +020046 _, err = io.ReadAll(resp.Body)
47 duration := time.Since(t)
48 experiment.RecordValue("Download Speed", (float64(resp.ContentLength)/1024/1024)/duration.Seconds(), gmeasure.Units("MB/s"), gmeasure.Precision(2))
Matus Fabian2d1f0e62024-06-06 11:24:36 +020049}
50
Adrian Villin1fde9992024-06-24 08:14:05 -040051func HttpTpsInterruptModeTest(s *NoTopoSuite) {
52 HttpTpsTest(s)
53}
54
Matus Fabian2d1f0e62024-06-06 11:24:36 +020055func HttpTpsTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +020056 vpp := s.GetContainerByName("vpp").VppInstance
57 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
Matus Fabian2d1f0e62024-06-06 11:24:36 +020058 url := "http://" + serverAddress + ":8080/test_file_10M"
59
Adrian Villin4677d922024-06-14 09:32:39 +020060 vpp.Vppctl("http tps uri tcp://0.0.0.0/8080")
Matus Fabian2d1f0e62024-06-06 11:24:36 +020061
Adrian Villin4677d922024-06-14 09:32:39 +020062 s.RunBenchmark("HTTP tps 10M", 10, 0, httpDownloadBenchmark, url)
Filip Tehlarb15a0002022-11-10 12:34:17 +010063}
64
Matus Fabiand086a362024-06-27 13:20:10 +020065func HttpPersistentConnectionTest(s *NoTopoSuite) {
66 // testing url handler app do not support multi-thread
67 s.SkipIfMultiWorker()
68 vpp := s.GetContainerByName("vpp").VppInstance
69 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
70 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers"))
71 s.Log(vpp.Vppctl("test-url-handler enable"))
72
73 transport := http.DefaultTransport
74 transport.(*http.Transport).Proxy = nil
75 transport.(*http.Transport).DisableKeepAlives = false
76 client := &http.Client{
77 Transport: transport,
78 Timeout: time.Second * 30,
79 CheckRedirect: func(req *http.Request, via []*http.Request) error {
80 return http.ErrUseLastResponse
81 }}
82
83 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/test1", nil)
84 s.AssertNil(err, fmt.Sprint(err))
85 resp, err := client.Do(req)
86 s.AssertNil(err, fmt.Sprint(err))
87 defer resp.Body.Close()
88 s.Log(DumpHttpResp(resp, true))
89 s.AssertEqual(200, resp.StatusCode)
90 s.AssertEqual(false, resp.Close)
91 body, err := io.ReadAll(resp.Body)
92 s.AssertNil(err, fmt.Sprint(err))
93 s.AssertEqual(string(body), "hello")
94 o1 := vpp.Vppctl("show session verbose proto http state ready")
95 s.Log(o1)
96 s.AssertContains(o1, "ESTABLISHED")
97
98 req, err = http.NewRequest("GET", "http://"+serverAddress+":80/test2", nil)
99 s.AssertNil(err, fmt.Sprint(err))
100 clientTrace := &httptrace.ClientTrace{
101 GotConn: func(info httptrace.GotConnInfo) {
102 s.AssertEqual(true, info.Reused, "connection not reused")
103 },
104 }
105 req = req.WithContext(httptrace.WithClientTrace(req.Context(), clientTrace))
106 resp, err = client.Do(req)
107 s.AssertNil(err, fmt.Sprint(err))
108 defer resp.Body.Close()
109 s.Log(DumpHttpResp(resp, true))
110 s.AssertEqual(200, resp.StatusCode)
111 s.AssertEqual(false, resp.Close)
112 body, err = io.ReadAll(resp.Body)
113 s.AssertNil(err, fmt.Sprint(err))
114 s.AssertEqual(string(body), "some data")
115 s.AssertNil(err, fmt.Sprint(err))
116 o2 := vpp.Vppctl("show session verbose proto http state ready")
117 s.Log(o2)
118 s.AssertContains(o2, "ESTABLISHED")
119 s.AssertEqual(o1, o2)
120}
121
122func HttpPipeliningTest(s *NoTopoSuite) {
123 // testing url handler app do not support multi-thread
124 s.SkipIfMultiWorker()
125 vpp := s.GetContainerByName("vpp").VppInstance
126 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
127 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
128 s.Log(vpp.Vppctl("test-url-handler enable"))
129
130 req1 := "GET /test_delayed HTTP/1.1\r\nHost:" + serverAddress + ":80\r\nUser-Agent:test\r\n\r\n"
131 req2 := "GET /test1 HTTP/1.1\r\nHost:" + serverAddress + ":80\r\nUser-Agent:test\r\n\r\n"
132
133 conn, err := net.DialTimeout("tcp", serverAddress+":80", time.Second*30)
134 s.AssertNil(err, fmt.Sprint(err))
135 defer conn.Close()
136 err = conn.SetDeadline(time.Now().Add(time.Second * 15))
137 s.AssertNil(err, fmt.Sprint(err))
138 n, err := conn.Write([]byte(req1))
139 s.AssertNil(err, fmt.Sprint(err))
140 s.AssertEqual(n, len([]rune(req1)))
141 // send second request a bit later so first is already in progress
142 time.Sleep(500 * time.Millisecond)
143 n, err = conn.Write([]byte(req2))
144 s.AssertNil(err, fmt.Sprint(err))
145 s.AssertEqual(n, len([]rune(req2)))
146 reply := make([]byte, 1024)
147 n, err = conn.Read(reply)
148 s.AssertNil(err, fmt.Sprint(err))
149 s.Log(string(reply))
150 s.AssertContains(string(reply), "delayed data", "first request response not received")
151 s.AssertNotContains(string(reply), "hello", "second request response received")
152 // make sure response for second request is not received later
153 _, err = conn.Read(reply)
154 s.AssertMatchError(err, os.ErrDeadlineExceeded, "second request response received")
155}
156
Adrian Villincee15aa2024-03-14 11:42:55 -0400157func HttpCliTest(s *VethsSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200158 serverContainer := s.GetContainerByName("server-vpp")
159 clientContainer := s.GetContainerByName("client-vpp")
Filip Tehlarb15a0002022-11-10 12:34:17 +0100160
Adrian Villin4677d922024-06-14 09:32:39 +0200161 serverVeth := s.GetInterfaceByName(ServerInterfaceName)
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100162
Adrian Villin4677d922024-06-14 09:32:39 +0200163 serverContainer.VppInstance.Vppctl("http cli server")
Filip Tehlarb15a0002022-11-10 12:34:17 +0100164
Adrian Villin4677d922024-06-14 09:32:39 +0200165 uri := "http://" + serverVeth.Ip4AddressString() + "/80"
Maros Ondrejickaffa3f602023-01-26 10:07:29 +0100166
Adrian Villin4677d922024-06-14 09:32:39 +0200167 o := clientContainer.VppInstance.Vppctl("http cli client" +
Filip Tehlard8944382023-11-27 13:28:36 +0100168 " uri " + uri + " query /show/vlib/graph")
Filip Tehlarb15a0002022-11-10 12:34:17 +0100169
Adrian Villin4677d922024-06-14 09:32:39 +0200170 s.Log(o)
171 s.AssertContains(o, "<html>", "<html> not found in the result!")
Filip Tehlarb15a0002022-11-10 12:34:17 +0100172}
Filip Tehlarc204c872022-12-21 08:59:16 +0100173
Matus Fabian3d008932024-05-13 10:29:11 +0200174func HttpCliConnectErrorTest(s *VethsSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200175 clientContainer := s.GetContainerByName("client-vpp")
Matus Fabian3d008932024-05-13 10:29:11 +0200176
Adrian Villin4677d922024-06-14 09:32:39 +0200177 serverVeth := s.GetInterfaceByName(ServerInterfaceName)
Matus Fabian3d008932024-05-13 10:29:11 +0200178
Adrian Villin4677d922024-06-14 09:32:39 +0200179 uri := "http://" + serverVeth.Ip4AddressString() + "/80"
Matus Fabian3d008932024-05-13 10:29:11 +0200180
Adrian Villin4677d922024-06-14 09:32:39 +0200181 o := clientContainer.VppInstance.Vppctl("http cli client" +
Matus Fabian3d008932024-05-13 10:29:11 +0200182 " uri " + uri + " query /show/vlib/graph")
183
Adrian Villin4677d922024-06-14 09:32:39 +0200184 s.Log(o)
185 s.AssertContains(o, "failed to connect")
Matus Fabian3d008932024-05-13 10:29:11 +0200186}
187
Adrian Villincee15aa2024-03-14 11:42:55 -0400188func HttpStaticPromTest(s *NoTopoSuite) {
Filip Tehlarcc1475c2023-11-29 12:59:05 +0100189 query := "stats.prom"
Adrian Villin4677d922024-06-14 09:32:39 +0200190 vpp := s.GetContainerByName("vpp").VppInstance
191 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
192 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers"))
193 s.Log(vpp.Vppctl("prom enable"))
Adrian Villincee15aa2024-03-14 11:42:55 -0400194 time.Sleep(time.Second * 5)
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200195 client := NewHttpClient()
196 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/"+query, nil)
197 s.AssertNil(err, fmt.Sprint(err))
198 resp, err := client.Do(req)
199 s.AssertNil(err, fmt.Sprint(err))
200 defer resp.Body.Close()
201 s.Log(DumpHttpResp(resp, false))
202 s.AssertEqual(200, resp.StatusCode)
203 s.AssertContains(resp.Header.Get("Content-Type"), "text")
204 s.AssertContains(resp.Header.Get("Content-Type"), "plain")
205 s.AssertNotEqual(int64(0), resp.ContentLength)
206 _, err = io.ReadAll(resp.Body)
207}
208
Matus Fabianc712de52024-07-24 12:56:14 +0200209func promReq(s *NoTopoSuite, url string) {
Matus Fabian5c4c1b62024-06-28 16:11:04 +0200210 client := NewHttpClient()
211 req, err := http.NewRequest("GET", url, nil)
212 s.AssertNil(err, fmt.Sprint(err))
213 resp, err := client.Do(req)
214 s.AssertNil(err, fmt.Sprint(err))
215 defer resp.Body.Close()
216 s.AssertEqual(200, resp.StatusCode)
217 _, err = io.ReadAll(resp.Body)
218}
219
Matus Fabianc712de52024-07-24 12:56:14 +0200220func promReqWg(s *NoTopoSuite, url string, wg *sync.WaitGroup) {
221 defer GinkgoRecover()
222 defer wg.Done()
223 promReq(s, url)
224}
225
Matus Fabian5c4c1b62024-06-28 16:11:04 +0200226func PromConcurrentConnections(s *NoTopoSuite) {
227 vpp := s.GetContainerByName("vpp").VppInstance
228 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
229 url := "http://" + serverAddress + ":80/stats.prom"
230
231 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers"))
232 s.Log(vpp.Vppctl("prom enable"))
233 time.Sleep(time.Second * 5)
234
235 var wg sync.WaitGroup
236 for i := 0; i < 20; i++ {
237 wg.Add(1)
Matus Fabianc712de52024-07-24 12:56:14 +0200238 go promReqWg(s, url, &wg)
Matus Fabian5c4c1b62024-06-28 16:11:04 +0200239 }
240 wg.Wait()
241 s.Log(vpp.Vppctl("show session verbose proto http"))
242}
243
Matus Fabianc712de52024-07-24 12:56:14 +0200244func PromMemLeakTest(s *NoTopoSuite) {
245 s.SkipUnlessLeakCheck()
246
247 vpp := s.GetContainerByName("vpp").VppInstance
248 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
249 url := "http://" + serverAddress + ":80/stats.prom"
250
251 /* no goVPP less noise */
252 vpp.Disconnect()
253
254 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers"))
255 s.Log(vpp.Vppctl("prom enable"))
256 time.Sleep(time.Second * 3)
257
258 /* warmup request (FIB) */
259 promReq(s, url)
260
261 vpp.EnableMemoryTrace()
262 traces1, err := vpp.GetMemoryTrace()
263 s.AssertNil(err, fmt.Sprint(err))
264
265 /* collect stats couple of times */
266 for i := 0; i < 5; i++ {
267 time.Sleep(time.Second * 1)
268 promReq(s, url)
269 }
270
271 /* let's give it some time to clean up sessions */
272 time.Sleep(time.Second * 5)
273
274 traces2, err := vpp.GetMemoryTrace()
275 s.AssertNil(err, fmt.Sprint(err))
276 vpp.MemLeakCheck(traces1, traces2)
277}
278
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200279func HttpStaticFileHandler(s *NoTopoSuite) {
280 content := "<http><body><p>Hello</p></body></http>"
281 content2 := "<http><body><p>Page</p></body></http>"
282 vpp := s.GetContainerByName("vpp").VppInstance
283 vpp.Container.Exec("mkdir -p " + wwwRootPath)
284 vpp.Container.CreateFile(wwwRootPath+"/index.html", content)
285 vpp.Container.CreateFile(wwwRootPath+"/page.html", content2)
286 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
287 s.Log(vpp.Vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + "/80 debug cache-size 2m"))
288
289 client := NewHttpClient()
290 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/index.html", nil)
291 s.AssertNil(err, fmt.Sprint(err))
292 resp, err := client.Do(req)
293 s.AssertNil(err, fmt.Sprint(err))
294 defer resp.Body.Close()
295 s.Log(DumpHttpResp(resp, true))
296 s.AssertEqual(200, resp.StatusCode)
297 s.AssertContains(resp.Header.Get("Content-Type"), "html")
298 s.AssertContains(resp.Header.Get("Cache-Control"), "max-age=")
299 s.AssertEqual(int64(len([]rune(content))), resp.ContentLength)
300 body, err := io.ReadAll(resp.Body)
301 s.AssertEqual(string(body), content)
302 o := vpp.Vppctl("show http static server cache verbose")
303 s.Log(o)
304 s.AssertContains(o, "index.html")
305 s.AssertNotContains(o, "page.html")
306
307 resp, err = client.Do(req)
308 s.AssertNil(err, fmt.Sprint(err))
309 defer resp.Body.Close()
310 s.Log(DumpHttpResp(resp, true))
311 s.AssertEqual(200, resp.StatusCode)
312 s.AssertContains(resp.Header.Get("Content-Type"), "html")
313 s.AssertContains(resp.Header.Get("Cache-Control"), "max-age=")
314 s.AssertEqual(int64(len([]rune(content))), resp.ContentLength)
315 body, err = io.ReadAll(resp.Body)
316 s.AssertEqual(string(body), content)
317
318 req, err = http.NewRequest("GET", "http://"+serverAddress+":80/page.html", nil)
319 s.AssertNil(err, fmt.Sprint(err))
320 resp, err = client.Do(req)
321 s.AssertNil(err, fmt.Sprint(err))
322 defer resp.Body.Close()
323 s.Log(DumpHttpResp(resp, true))
324 s.AssertEqual(200, resp.StatusCode)
325 s.AssertContains(resp.Header.Get("Content-Type"), "html")
326 s.AssertContains(resp.Header.Get("Cache-Control"), "max-age=")
327 s.AssertEqual(int64(len([]rune(content2))), resp.ContentLength)
328 body, err = io.ReadAll(resp.Body)
329 s.AssertEqual(string(body), content2)
330 o = vpp.Vppctl("show http static server cache verbose")
331 s.Log(o)
332 s.AssertContains(o, "index.html")
333 s.AssertContains(o, "page.html")
Filip Tehlarcc1475c2023-11-29 12:59:05 +0100334}
335
Matus Fabian5409d332024-05-28 13:39:13 +0200336func HttpStaticPathTraversalTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200337 vpp := s.GetContainerByName("vpp").VppInstance
338 vpp.Container.Exec("mkdir -p " + wwwRootPath)
339 vpp.Container.Exec("mkdir -p " + "/tmp/secret_folder")
340 vpp.Container.CreateFile("/tmp/secret_folder/secret_file.txt", "secret")
341 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
342 s.Log(vpp.Vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + "/80 debug"))
Matus Fabian5409d332024-05-28 13:39:13 +0200343
Adrian Villin4677d922024-06-14 09:32:39 +0200344 client := NewHttpClient()
Matus Fabian5409d332024-05-28 13:39:13 +0200345 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/../secret_folder/secret_file.txt", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200346 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian5409d332024-05-28 13:39:13 +0200347 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200348 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian5409d332024-05-28 13:39:13 +0200349 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200350 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200351 s.AssertEqual(404, resp.StatusCode)
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200352 s.AssertEmpty(resp.Header.Get("Content-Type"))
353 s.AssertEmpty(resp.Header.Get("Cache-Control"))
354 s.AssertEqual(int64(0), resp.ContentLength)
Matus Fabian5409d332024-05-28 13:39:13 +0200355}
356
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200357func HttpStaticMovedTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200358 vpp := s.GetContainerByName("vpp").VppInstance
359 vpp.Container.Exec("mkdir -p " + wwwRootPath + "/tmp.aaa")
360 vpp.Container.CreateFile(wwwRootPath+"/tmp.aaa/index.html", "<http><body><p>Hello</p></body></http>")
361 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
362 s.Log(vpp.Vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + "/80 debug"))
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200363
Adrian Villin4677d922024-06-14 09:32:39 +0200364 client := NewHttpClient()
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200365 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/tmp.aaa", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200366 s.AssertNil(err, fmt.Sprint(err))
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200367 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200368 s.AssertNil(err, fmt.Sprint(err))
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200369 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200370 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200371 s.AssertEqual(301, resp.StatusCode)
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200372 s.AssertEqual("http://"+serverAddress+"/tmp.aaa/index.html", resp.Header.Get("Location"))
373 s.AssertEmpty(resp.Header.Get("Content-Type"))
374 s.AssertEmpty(resp.Header.Get("Cache-Control"))
375 s.AssertEqual(int64(0), resp.ContentLength)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200376}
377
378func HttpStaticNotFoundTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200379 vpp := s.GetContainerByName("vpp").VppInstance
380 vpp.Container.Exec("mkdir -p " + wwwRootPath)
381 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
382 s.Log(vpp.Vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + "/80 debug"))
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200383
Adrian Villin4677d922024-06-14 09:32:39 +0200384 client := NewHttpClient()
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200385 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/notfound.html", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200386 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian595d8cb2024-05-17 11:28:43 +0200387 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200388 s.AssertNil(err, fmt.Sprint(err))
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200389 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200390 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200391 s.AssertEqual(404, resp.StatusCode)
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200392 s.AssertEmpty(resp.Header.Get("Content-Type"))
393 s.AssertEmpty(resp.Header.Get("Cache-Control"))
394 s.AssertEqual(int64(0), resp.ContentLength)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200395}
396
397func HttpCliMethodNotAllowedTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200398 vpp := s.GetContainerByName("vpp").VppInstance
399 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
400 vpp.Vppctl("http cli server")
Matus Fabian616201a2024-05-02 11:17:15 +0200401
Adrian Villin4677d922024-06-14 09:32:39 +0200402 client := NewHttpClient()
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200403 req, err := http.NewRequest("POST", "http://"+serverAddress+":80/test", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200404 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian595d8cb2024-05-17 11:28:43 +0200405 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200406 s.AssertNil(err, fmt.Sprint(err))
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200407 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200408 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200409 s.AssertEqual(405, resp.StatusCode)
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200410 s.AssertNotEqual("", resp.Header.Get("Allow"), "server MUST generate an Allow header")
411 s.AssertEmpty(resp.Header.Get("Content-Type"))
412 s.AssertEqual(int64(0), resp.ContentLength)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200413}
414
415func HttpCliBadRequestTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200416 vpp := s.GetContainerByName("vpp").VppInstance
417 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
418 vpp.Vppctl("http cli server")
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200419
Adrian Villin4677d922024-06-14 09:32:39 +0200420 client := NewHttpClient()
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200421 req, err := http.NewRequest("GET", "http://"+serverAddress+":80", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200422 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian595d8cb2024-05-17 11:28:43 +0200423 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200424 s.AssertNil(err, fmt.Sprint(err))
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200425 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200426 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200427 s.AssertEqual(400, resp.StatusCode)
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200428 s.AssertEmpty(resp.Header.Get("Content-Type"))
429 s.AssertEqual(int64(0), resp.ContentLength)
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200430}
431
Matus Fabian82ad9662024-06-04 19:00:00 +0200432func HttpStaticBuildInUrlGetVersionTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200433 vpp := s.GetContainerByName("vpp").VppInstance
434 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
435 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
Matus Fabian82ad9662024-06-04 19:00:00 +0200436
Adrian Villin4677d922024-06-14 09:32:39 +0200437 client := NewHttpClient()
Matus Fabian82ad9662024-06-04 19:00:00 +0200438 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/version.json", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200439 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200440 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200441 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200442 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200443 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200444 s.AssertEqual(200, resp.StatusCode)
Matus Fabian82ad9662024-06-04 19:00:00 +0200445 data, err := io.ReadAll(resp.Body)
Adrian Villin4677d922024-06-14 09:32:39 +0200446 s.AssertNil(err, fmt.Sprint(err))
447 s.AssertContains(string(data), "vpp_details")
448 s.AssertContains(string(data), "version")
449 s.AssertContains(string(data), "build_date")
450 s.AssertNotContains(string(data), "build_by")
451 s.AssertNotContains(string(data), "build_host")
452 s.AssertNotContains(string(data), "build_dir")
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200453 s.AssertContains(resp.Header.Get("Content-Type"), "json")
Matus Fabian82ad9662024-06-04 19:00:00 +0200454}
455
456func HttpStaticBuildInUrlGetVersionVerboseTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200457 vpp := s.GetContainerByName("vpp").VppInstance
458 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
459 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
Matus Fabian82ad9662024-06-04 19:00:00 +0200460
Adrian Villin4677d922024-06-14 09:32:39 +0200461 client := NewHttpClient()
Matus Fabian82ad9662024-06-04 19:00:00 +0200462 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/version.json?verbose=true", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200463 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200464 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200465 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200466 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200467 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200468 s.AssertEqual(200, resp.StatusCode)
Matus Fabian82ad9662024-06-04 19:00:00 +0200469 data, err := io.ReadAll(resp.Body)
Adrian Villin4677d922024-06-14 09:32:39 +0200470 s.AssertNil(err, fmt.Sprint(err))
471 s.AssertContains(string(data), "vpp_details")
472 s.AssertContains(string(data), "version")
473 s.AssertContains(string(data), "build_date")
474 s.AssertContains(string(data), "build_by")
475 s.AssertContains(string(data), "build_host")
476 s.AssertContains(string(data), "build_dir")
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200477 s.AssertContains(resp.Header.Get("Content-Type"), "json")
Matus Fabian82ad9662024-06-04 19:00:00 +0200478}
479
480func HttpStaticBuildInUrlGetIfListTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200481 vpp := s.GetContainerByName("vpp").VppInstance
482 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
483 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
Matus Fabian82ad9662024-06-04 19:00:00 +0200484
Adrian Villin4677d922024-06-14 09:32:39 +0200485 client := NewHttpClient()
Matus Fabian82ad9662024-06-04 19:00:00 +0200486 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/interface_list.json", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200487 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200488 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200489 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200490 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200491 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200492 s.AssertEqual(200, resp.StatusCode)
Matus Fabian82ad9662024-06-04 19:00:00 +0200493 data, err := io.ReadAll(resp.Body)
Adrian Villin4677d922024-06-14 09:32:39 +0200494 s.AssertNil(err, fmt.Sprint(err))
495 s.AssertContains(string(data), "interface_list")
496 s.AssertContains(string(data), s.GetInterfaceByName(TapInterfaceName).Peer.Name())
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200497 s.AssertContains(resp.Header.Get("Content-Type"), "json")
Matus Fabian82ad9662024-06-04 19:00:00 +0200498}
499
500func HttpStaticBuildInUrlGetIfStatsTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200501 vpp := s.GetContainerByName("vpp").VppInstance
502 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
503 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
Matus Fabian82ad9662024-06-04 19:00:00 +0200504
Adrian Villin4677d922024-06-14 09:32:39 +0200505 client := NewHttpClient()
Matus Fabian82ad9662024-06-04 19:00:00 +0200506 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/interface_stats.json", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200507 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200508 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200509 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200510 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200511 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200512 s.AssertEqual(200, resp.StatusCode)
Matus Fabian82ad9662024-06-04 19:00:00 +0200513 data, err := io.ReadAll(resp.Body)
Adrian Villin4677d922024-06-14 09:32:39 +0200514 s.AssertNil(err, fmt.Sprint(err))
515 s.AssertContains(string(data), "interface_stats")
516 s.AssertContains(string(data), "local0")
517 s.AssertContains(string(data), s.GetInterfaceByName(TapInterfaceName).Peer.Name())
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200518 s.AssertContains(resp.Header.Get("Content-Type"), "json")
Matus Fabian82ad9662024-06-04 19:00:00 +0200519}
520
521func validatePostInterfaceStats(s *NoTopoSuite, data string) {
Adrian Villin4677d922024-06-14 09:32:39 +0200522 s.AssertContains(data, "interface_stats")
523 s.AssertContains(data, s.GetInterfaceByName(TapInterfaceName).Peer.Name())
524 s.AssertNotContains(data, "error")
525 s.AssertNotContains(data, "local0")
Matus Fabian82ad9662024-06-04 19:00:00 +0200526}
527
528func HttpStaticBuildInUrlPostIfStatsTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200529 vpp := s.GetContainerByName("vpp").VppInstance
530 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
531 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
532 body := []byte(s.GetInterfaceByName(TapInterfaceName).Peer.Name())
Matus Fabian82ad9662024-06-04 19:00:00 +0200533
Adrian Villin4677d922024-06-14 09:32:39 +0200534 client := NewHttpClient()
Matus Fabian82ad9662024-06-04 19:00:00 +0200535 req, err := http.NewRequest("POST",
536 "http://"+serverAddress+":80/interface_stats.json", bytes.NewBuffer(body))
Adrian Villin4677d922024-06-14 09:32:39 +0200537 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200538 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200539 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200540 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200541 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200542 s.AssertEqual(200, resp.StatusCode)
Matus Fabian82ad9662024-06-04 19:00:00 +0200543 data, err := io.ReadAll(resp.Body)
Adrian Villin4677d922024-06-14 09:32:39 +0200544 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200545 validatePostInterfaceStats(s, string(data))
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200546 s.AssertContains(resp.Header.Get("Content-Type"), "json")
Matus Fabian82ad9662024-06-04 19:00:00 +0200547}
548
549func HttpStaticMacTimeTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200550 vpp := s.GetContainerByName("vpp").VppInstance
551 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
552 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
553 s.Log(vpp.Vppctl("mactime enable-disable " + s.GetInterfaceByName(TapInterfaceName).Peer.Name()))
Matus Fabian82ad9662024-06-04 19:00:00 +0200554
Adrian Villin4677d922024-06-14 09:32:39 +0200555 client := NewHttpClient()
Matus Fabian82ad9662024-06-04 19:00:00 +0200556 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/mactime.json", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200557 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200558 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200559 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200560 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200561 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200562 s.AssertEqual(200, resp.StatusCode)
Matus Fabian82ad9662024-06-04 19:00:00 +0200563 data, err := io.ReadAll(resp.Body)
Adrian Villin4677d922024-06-14 09:32:39 +0200564 s.AssertNil(err, fmt.Sprint(err))
565 s.AssertContains(string(data), "mactime")
566 s.AssertContains(string(data), s.GetInterfaceByName(TapInterfaceName).Ip4AddressString())
567 s.AssertContains(string(data), s.GetInterfaceByName(TapInterfaceName).HwAddress.String())
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200568 s.AssertContains(resp.Header.Get("Content-Type"), "json")
Matus Fabian82ad9662024-06-04 19:00:00 +0200569}
570
571func HttpInvalidRequestLineTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200572 vpp := s.GetContainerByName("vpp").VppInstance
573 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
574 vpp.Vppctl("http cli server")
Matus Fabian82ad9662024-06-04 19:00:00 +0200575
Adrian Villin4677d922024-06-14 09:32:39 +0200576 resp, err := TcpSendReceive(serverAddress+":80", "GET / HTTP/1.1")
577 s.AssertNil(err, fmt.Sprint(err))
578 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "invalid framing not allowed")
Matus Fabian82ad9662024-06-04 19:00:00 +0200579
Adrian Villin4677d922024-06-14 09:32:39 +0200580 resp, err = TcpSendReceive(serverAddress+":80", "GET / HTTP/1.1\r\n")
581 s.AssertNil(err, fmt.Sprint(err))
582 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "invalid framing not allowed")
Matus Fabian82ad9662024-06-04 19:00:00 +0200583
Adrian Villin4677d922024-06-14 09:32:39 +0200584 resp, err = TcpSendReceive(serverAddress+":80", "GET /\r\n\r\n")
585 s.AssertNil(err, fmt.Sprint(err))
586 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "HTTP-version must be present")
Matus Fabian82ad9662024-06-04 19:00:00 +0200587
Adrian Villin4677d922024-06-14 09:32:39 +0200588 resp, err = TcpSendReceive(serverAddress+":80", "GET HTTP/1.1\r\n\r\n")
589 s.AssertNil(err, fmt.Sprint(err))
590 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "request-target must be present")
Matus Fabian82ad9662024-06-04 19:00:00 +0200591
Adrian Villin4677d922024-06-14 09:32:39 +0200592 resp, err = TcpSendReceive(serverAddress+":80", "GET HTTP/1.1\r\n\r\n")
593 s.AssertNil(err, fmt.Sprint(err))
594 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "request-target must be present")
Matus Fabian82ad9662024-06-04 19:00:00 +0200595
Adrian Villin4677d922024-06-14 09:32:39 +0200596 resp, err = TcpSendReceive(serverAddress+":80", "GET / HTTP/x\r\n\r\n")
597 s.AssertNil(err, fmt.Sprint(err))
598 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "'HTTP/x' invalid http version not allowed")
Matus Fabian82ad9662024-06-04 19:00:00 +0200599
Adrian Villin4677d922024-06-14 09:32:39 +0200600 resp, err = TcpSendReceive(serverAddress+":80", "GET / HTTP1.1\r\n\r\n")
601 s.AssertNil(err, fmt.Sprint(err))
602 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "'HTTP1.1' invalid http version not allowed")
Matus Fabian82ad9662024-06-04 19:00:00 +0200603}
604
605func HttpInvalidTargetSyntaxTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200606 vpp := s.GetContainerByName("vpp").VppInstance
607 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
608 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
Matus Fabian82ad9662024-06-04 19:00:00 +0200609
Adrian Villin4677d922024-06-14 09:32:39 +0200610 resp, err := TcpSendReceive(serverAddress+":80", "GET /interface|stats.json HTTP/1.1\r\n\r\n")
611 s.AssertNil(err, fmt.Sprint(err))
612 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "'|' not allowed in target path")
Matus Fabian82ad9662024-06-04 19:00:00 +0200613
Adrian Villin4677d922024-06-14 09:32:39 +0200614 resp, err = TcpSendReceive(serverAddress+":80", "GET /interface#stats.json HTTP/1.1\r\n\r\n")
615 s.AssertNil(err, fmt.Sprint(err))
616 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "'#' not allowed in target path")
Matus Fabian82ad9662024-06-04 19:00:00 +0200617
Adrian Villin4677d922024-06-14 09:32:39 +0200618 resp, err = TcpSendReceive(serverAddress+":80", "GET /interface%stats.json HTTP/1.1\r\n\r\n")
619 s.AssertNil(err, fmt.Sprint(err))
620 s.AssertContains(resp, "HTTP/1.1 400 Bad Request",
Matus Fabian82ad9662024-06-04 19:00:00 +0200621 "after '%' there must be two hex-digit characters in target path")
622
Adrian Villin4677d922024-06-14 09:32:39 +0200623 resp, err = TcpSendReceive(serverAddress+":80", "GET /interface%1stats.json HTTP/1.1\r\n\r\n")
624 s.AssertNil(err, fmt.Sprint(err))
625 s.AssertContains(resp, "HTTP/1.1 400 Bad Request",
Matus Fabian82ad9662024-06-04 19:00:00 +0200626 "after '%' there must be two hex-digit characters in target path")
627
Adrian Villin4677d922024-06-14 09:32:39 +0200628 resp, err = TcpSendReceive(serverAddress+":80", "GET /interface%Bstats.json HTTP/1.1\r\n\r\n")
629 s.AssertNil(err, fmt.Sprint(err))
630 s.AssertContains(resp, "HTTP/1.1 400 Bad Request",
Matus Fabian82ad9662024-06-04 19:00:00 +0200631 "after '%' there must be two hex-digit characters in target path")
632
Adrian Villin4677d922024-06-14 09:32:39 +0200633 resp, err = TcpSendReceive(serverAddress+":80", "GET /interface%stats.json%B HTTP/1.1\r\n\r\n")
634 s.AssertNil(err, fmt.Sprint(err))
635 s.AssertContains(resp, "HTTP/1.1 400 Bad Request",
Matus Fabian82ad9662024-06-04 19:00:00 +0200636 "after '%' there must be two hex-digit characters in target path")
637
Adrian Villin4677d922024-06-14 09:32:39 +0200638 resp, err = TcpSendReceive(serverAddress+":80", "GET /version.json?verbose>true HTTP/1.1\r\n\r\n")
639 s.AssertNil(err, fmt.Sprint(err))
640 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "'>' not allowed in target query")
Matus Fabian82ad9662024-06-04 19:00:00 +0200641
Adrian Villin4677d922024-06-14 09:32:39 +0200642 resp, err = TcpSendReceive(serverAddress+":80", "GET /version.json?verbose%true HTTP/1.1\r\n\r\n")
643 s.AssertNil(err, fmt.Sprint(err))
644 s.AssertContains(resp, "HTTP/1.1 400 Bad Request",
Matus Fabian82ad9662024-06-04 19:00:00 +0200645 "after '%' there must be two hex-digit characters in target query")
646
Adrian Villin4677d922024-06-14 09:32:39 +0200647 resp, err = TcpSendReceive(serverAddress+":80", "GET /version.json?verbose=%1 HTTP/1.1\r\n\r\n")
648 s.AssertNil(err, fmt.Sprint(err))
649 s.AssertContains(resp, "HTTP/1.1 400 Bad Request",
Matus Fabian82ad9662024-06-04 19:00:00 +0200650 "after '%' there must be two hex-digit characters in target query")
651}
652
653func HttpInvalidContentLengthTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200654 vpp := s.GetContainerByName("vpp").VppInstance
655 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
656 vpp.Vppctl("http cli server")
Matus Fabian82ad9662024-06-04 19:00:00 +0200657
Adrian Villin4677d922024-06-14 09:32:39 +0200658 resp, err := TcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nContent-Length:\r\n\r\n")
659 s.AssertNil(err, fmt.Sprint(err))
660 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "Content-Length value must be present")
Matus Fabian82ad9662024-06-04 19:00:00 +0200661
Adrian Villin4677d922024-06-14 09:32:39 +0200662 resp, err = TcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nContent-Length: \r\n\r\n")
663 s.AssertNil(err, fmt.Sprint(err))
664 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "Content-Length value must be present")
Matus Fabian82ad9662024-06-04 19:00:00 +0200665
Adrian Villin4677d922024-06-14 09:32:39 +0200666 resp, err = TcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nContent-Length: a\r\n\r\n")
667 s.AssertNil(err, fmt.Sprint(err))
668 s.AssertContains(resp, "HTTP/1.1 400 Bad Request",
Matus Fabian82ad9662024-06-04 19:00:00 +0200669 "Content-Length value other than digit not allowed")
670}
671
672func HttpContentLengthTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200673 vpp := s.GetContainerByName("vpp").VppInstance
674 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
675 s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers debug"))
676 ifName := s.GetInterfaceByName(TapInterfaceName).Peer.Name()
Matus Fabian82ad9662024-06-04 19:00:00 +0200677
Adrian Villin4677d922024-06-14 09:32:39 +0200678 resp, err := TcpSendReceive(serverAddress+":80",
Matus Fabian82ad9662024-06-04 19:00:00 +0200679 "POST /interface_stats.json HTTP/1.1\r\nContent-Length:4\r\n\r\n"+ifName)
Adrian Villin4677d922024-06-14 09:32:39 +0200680 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200681 validatePostInterfaceStats(s, resp)
682
Adrian Villin4677d922024-06-14 09:32:39 +0200683 resp, err = TcpSendReceive(serverAddress+":80",
Matus Fabian82ad9662024-06-04 19:00:00 +0200684 "POST /interface_stats.json HTTP/1.1\r\n Content-Length: 4 \r\n\r\n"+ifName)
Adrian Villin4677d922024-06-14 09:32:39 +0200685 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200686 validatePostInterfaceStats(s, resp)
687
Adrian Villin4677d922024-06-14 09:32:39 +0200688 resp, err = TcpSendReceive(serverAddress+":80",
Matus Fabian82ad9662024-06-04 19:00:00 +0200689 "POST /interface_stats.json HTTP/1.1\r\n\tContent-Length:\t\t4\r\n\r\n"+ifName)
Adrian Villin4677d922024-06-14 09:32:39 +0200690 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200691 validatePostInterfaceStats(s, resp)
692}
693
694func HttpMethodNotImplementedTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200695 vpp := s.GetContainerByName("vpp").VppInstance
696 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
697 vpp.Vppctl("http cli server")
Matus Fabian82ad9662024-06-04 19:00:00 +0200698
Adrian Villin4677d922024-06-14 09:32:39 +0200699 client := NewHttpClient()
Matus Fabian82ad9662024-06-04 19:00:00 +0200700 req, err := http.NewRequest("OPTIONS", "http://"+serverAddress+":80/show/version", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200701 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200702 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200703 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200704 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200705 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200706 s.AssertEqual(501, resp.StatusCode)
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200707 s.AssertEmpty(resp.Header.Get("Content-Type"))
708 s.AssertEqual(int64(0), resp.ContentLength)
Matus Fabian82ad9662024-06-04 19:00:00 +0200709}
710
711func HttpVersionNotSupportedTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200712 vpp := s.GetContainerByName("vpp").VppInstance
713 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
714 vpp.Vppctl("http cli server")
Matus Fabian82ad9662024-06-04 19:00:00 +0200715
Adrian Villin4677d922024-06-14 09:32:39 +0200716 resp, err := TcpSendReceive(serverAddress+":80", "GET / HTTP/2\r\n\r\n")
717 s.AssertNil(err, fmt.Sprint(err))
718 s.AssertContains(resp, "HTTP/1.1 505 HTTP Version Not Supported")
Matus Fabian82ad9662024-06-04 19:00:00 +0200719}
720
721func HttpUriDecodeTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200722 vpp := s.GetContainerByName("vpp").VppInstance
723 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
724 vpp.Vppctl("http cli server")
Matus Fabian82ad9662024-06-04 19:00:00 +0200725
Adrian Villin4677d922024-06-14 09:32:39 +0200726 client := NewHttpClient()
Matus Fabian82ad9662024-06-04 19:00:00 +0200727 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/sh%6fw%20versio%6E%20verbose", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200728 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200729 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200730 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian82ad9662024-06-04 19:00:00 +0200731 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200732 s.Log(DumpHttpResp(resp, true))
Adrian Villin4677d922024-06-14 09:32:39 +0200733 s.AssertEqual(200, resp.StatusCode)
Matus Fabian82ad9662024-06-04 19:00:00 +0200734 data, err := io.ReadAll(resp.Body)
Adrian Villin4677d922024-06-14 09:32:39 +0200735 s.AssertNil(err, fmt.Sprint(err))
Adrian Villin4677d922024-06-14 09:32:39 +0200736 s.AssertNotContains(string(data), "unknown input")
737 s.AssertContains(string(data), "Compiler")
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200738 s.AssertContains(resp.Header.Get("Content-Type"), "html")
Matus Fabian82ad9662024-06-04 19:00:00 +0200739}
740
741func HttpHeadersTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200742 vpp := s.GetContainerByName("vpp").VppInstance
743 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
744 vpp.Vppctl("http cli server")
Matus Fabian82ad9662024-06-04 19:00:00 +0200745
Adrian Villin4677d922024-06-14 09:32:39 +0200746 resp, err := TcpSendReceive(
Matus Fabian82ad9662024-06-04 19:00:00 +0200747 serverAddress+":80",
748 "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser-Agent:test\r\nAccept:text/xml\r\nAccept:\ttext/plain\t \r\nAccept:text/html\r\n\r\n")
Adrian Villin4677d922024-06-14 09:32:39 +0200749 s.AssertNil(err, fmt.Sprint(err))
750 s.AssertContains(resp, "HTTP/1.1 200 OK")
751 s.AssertContains(resp, "Content-Type: text / plain")
752 s.AssertNotContains(resp, "<html>", "html content received instead of plain text")
Matus Fabian82ad9662024-06-04 19:00:00 +0200753}
754
755func HttpInvalidHeadersTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200756 vpp := s.GetContainerByName("vpp").VppInstance
757 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
758 vpp.Vppctl("http cli server")
Matus Fabian82ad9662024-06-04 19:00:00 +0200759
Adrian Villin4677d922024-06-14 09:32:39 +0200760 resp, err := TcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nUser-Agent: test\r\n")
761 s.AssertNil(err, fmt.Sprint(err))
762 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "Header section must end with CRLF CRLF")
Matus Fabian82ad9662024-06-04 19:00:00 +0200763
Adrian Villin4677d922024-06-14 09:32:39 +0200764 resp, err = TcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser@Agent:test\r\n\r\n")
765 s.AssertNil(err, fmt.Sprint(err))
766 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "'@' not allowed in field name")
Matus Fabian82ad9662024-06-04 19:00:00 +0200767
Adrian Villin4677d922024-06-14 09:32:39 +0200768 resp, err = TcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser-Agent\r\n\r\n")
769 s.AssertNil(err, fmt.Sprint(err))
770 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "incomplete field line not allowed")
Matus Fabian82ad9662024-06-04 19:00:00 +0200771
Adrian Villin4677d922024-06-14 09:32:39 +0200772 resp, err = TcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\n: test\r\n\r\n")
773 s.AssertNil(err, fmt.Sprint(err))
774 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "empty field name not allowed")
Matus Fabian82ad9662024-06-04 19:00:00 +0200775
Adrian Villin4677d922024-06-14 09:32:39 +0200776 resp, err = TcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\rUser-Agent:test\r\n\r\n")
777 s.AssertNil(err, fmt.Sprint(err))
778 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "invalid field line end not allowed")
Matus Fabian82ad9662024-06-04 19:00:00 +0200779
Adrian Villin4677d922024-06-14 09:32:39 +0200780 resp, err = TcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\nUser-Agent:test\r\n\r\n")
781 s.AssertNil(err, fmt.Sprint(err))
782 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "invalid field line end not allowed")
Matus Fabian82ad9662024-06-04 19:00:00 +0200783
Adrian Villin4677d922024-06-14 09:32:39 +0200784 resp, err = TcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser-Agent:\r\n\r\n")
785 s.AssertNil(err, fmt.Sprint(err))
786 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "empty field value not allowed")
Matus Fabian82ad9662024-06-04 19:00:00 +0200787
Adrian Villin4677d922024-06-14 09:32:39 +0200788 resp, err = TcpSendReceive(serverAddress+":80", "GET /show/version HTTP/1.1\r\nHost:"+serverAddress+":80\r\nUser-Agent: \r\n\r\n")
789 s.AssertNil(err, fmt.Sprint(err))
790 s.AssertContains(resp, "HTTP/1.1 400 Bad Request", "empty field value not allowed")
Matus Fabian82ad9662024-06-04 19:00:00 +0200791}
792
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200793func HeaderServerTest(s *NoTopoSuite) {
Adrian Villin4677d922024-06-14 09:32:39 +0200794 vpp := s.GetContainerByName("vpp").VppInstance
795 serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString()
796 vpp.Vppctl("http cli server")
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200797
Adrian Villin4677d922024-06-14 09:32:39 +0200798 client := NewHttpClient()
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200799 req, err := http.NewRequest("GET", "http://"+serverAddress+":80/show/version", nil)
Adrian Villin4677d922024-06-14 09:32:39 +0200800 s.AssertNil(err, fmt.Sprint(err))
Matus Fabian595d8cb2024-05-17 11:28:43 +0200801 resp, err := client.Do(req)
Adrian Villin4677d922024-06-14 09:32:39 +0200802 s.AssertNil(err, fmt.Sprint(err))
Matus Fabianb7a9ed72024-05-10 16:20:40 +0200803 defer resp.Body.Close()
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200804 s.Log(DumpHttpResp(resp, true))
805 s.AssertEqual(200, resp.StatusCode)
Adrian Villin4677d922024-06-14 09:32:39 +0200806 s.AssertEqual("http_cli_server", resp.Header.Get("Server"))
Matus Fabian8ca6ce62024-06-20 17:08:26 +0200807 s.AssertContains(resp.Header.Get("Content-Type"), "html")
Matus Fabian616201a2024-05-02 11:17:15 +0200808}