diff options
author | Matus Fabian <matfabia@cisco.com> | 2024-06-20 17:08:26 +0200 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2024-07-23 15:22:34 +0000 |
commit | 8ca6ce6fe1e65c8b57b9c0910dfd1243db0e49b9 (patch) | |
tree | da860f9fdeab192a4f90cc96c55bace986fef2a8 /extras/hs-test | |
parent | 1f870c9bdc4f2ce4076b1faeb42878a41125fd76 (diff) |
http: return more than data from server app
Server app could return headers in front of body/data buffer.
Offers apis for building and serialization of headers section.
HTTP layer now only add Date, Server and Content-Lengths headers,
rest is up to app. Well known header names are predefined.
Type: improvement
Change-Id: If778bdfc9acf6b0d11a48f0a745a3a56c96c2436
Signed-off-by: Matus Fabian <matfabia@cisco.com>
Diffstat (limited to 'extras/hs-test')
-rw-r--r-- | extras/hs-test/http_test.go | 123 | ||||
-rw-r--r-- | extras/hs-test/infra/utils.go | 9 |
2 files changed, 119 insertions, 13 deletions
diff --git a/extras/hs-test/http_test.go b/extras/hs-test/http_test.go index a5694bfb54b..e20efd6f35c 100644 --- a/extras/hs-test/http_test.go +++ b/extras/hs-test/http_test.go @@ -9,7 +9,6 @@ import ( "time" . "fd.io/hs-test/infra" - . "github.com/onsi/ginkgo/v2" ) func init() { @@ -21,7 +20,7 @@ func init() { HttpContentLengthTest, HttpStaticBuildInUrlGetIfListTest, HttpStaticBuildInUrlGetVersionTest, HttpStaticMacTimeTest, HttpStaticBuildInUrlGetVersionVerboseTest, HttpVersionNotSupportedTest, HttpInvalidContentLengthTest, HttpInvalidTargetSyntaxTest, HttpStaticPathTraversalTest, HttpUriDecodeTest, - HttpHeadersTest) + HttpHeadersTest, HttpStaticFileHandler) RegisterNoTopoSoloTests(HttpStaticPromTest, HttpTpsTest, HttpTpsInterruptModeTest) } @@ -89,19 +88,81 @@ func HttpCliConnectErrorTest(s *VethsSuite) { } func HttpStaticPromTest(s *NoTopoSuite) { - finished := make(chan error, 1) query := "stats.prom" vpp := s.GetContainerByName("vpp").VppInstance serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString() s.Log(vpp.Vppctl("http static server uri tcp://" + serverAddress + "/80 url-handlers")) s.Log(vpp.Vppctl("prom enable")) time.Sleep(time.Second * 5) - go func() { - defer GinkgoRecover() - s.StartWget(finished, serverAddress, "80", query, "") - }() - err := <-finished - s.AssertNil(err) + client := NewHttpClient() + req, err := http.NewRequest("GET", "http://"+serverAddress+":80/"+query, nil) + s.AssertNil(err, fmt.Sprint(err)) + resp, err := client.Do(req) + s.AssertNil(err, fmt.Sprint(err)) + defer resp.Body.Close() + s.Log(DumpHttpResp(resp, false)) + s.AssertEqual(200, resp.StatusCode) + s.AssertContains(resp.Header.Get("Content-Type"), "text") + s.AssertContains(resp.Header.Get("Content-Type"), "plain") + s.AssertNotEqual(int64(0), resp.ContentLength) + _, err = io.ReadAll(resp.Body) +} + +func HttpStaticFileHandler(s *NoTopoSuite) { + content := "<http><body><p>Hello</p></body></http>" + content2 := "<http><body><p>Page</p></body></http>" + vpp := s.GetContainerByName("vpp").VppInstance + vpp.Container.Exec("mkdir -p " + wwwRootPath) + vpp.Container.CreateFile(wwwRootPath+"/index.html", content) + vpp.Container.CreateFile(wwwRootPath+"/page.html", content2) + serverAddress := s.GetInterfaceByName(TapInterfaceName).Peer.Ip4AddressString() + s.Log(vpp.Vppctl("http static server www-root " + wwwRootPath + " uri tcp://" + serverAddress + "/80 debug cache-size 2m")) + + client := NewHttpClient() + req, err := http.NewRequest("GET", "http://"+serverAddress+":80/index.html", nil) + s.AssertNil(err, fmt.Sprint(err)) + resp, err := client.Do(req) + s.AssertNil(err, fmt.Sprint(err)) + defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) + s.AssertEqual(200, resp.StatusCode) + s.AssertContains(resp.Header.Get("Content-Type"), "html") + s.AssertContains(resp.Header.Get("Cache-Control"), "max-age=") + s.AssertEqual(int64(len([]rune(content))), resp.ContentLength) + body, err := io.ReadAll(resp.Body) + s.AssertEqual(string(body), content) + o := vpp.Vppctl("show http static server cache verbose") + s.Log(o) + s.AssertContains(o, "index.html") + s.AssertNotContains(o, "page.html") + + resp, err = client.Do(req) + s.AssertNil(err, fmt.Sprint(err)) + defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) + s.AssertEqual(200, resp.StatusCode) + s.AssertContains(resp.Header.Get("Content-Type"), "html") + s.AssertContains(resp.Header.Get("Cache-Control"), "max-age=") + s.AssertEqual(int64(len([]rune(content))), resp.ContentLength) + body, err = io.ReadAll(resp.Body) + s.AssertEqual(string(body), content) + + req, err = http.NewRequest("GET", "http://"+serverAddress+":80/page.html", nil) + s.AssertNil(err, fmt.Sprint(err)) + resp, err = client.Do(req) + s.AssertNil(err, fmt.Sprint(err)) + defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) + s.AssertEqual(200, resp.StatusCode) + s.AssertContains(resp.Header.Get("Content-Type"), "html") + s.AssertContains(resp.Header.Get("Cache-Control"), "max-age=") + s.AssertEqual(int64(len([]rune(content2))), resp.ContentLength) + body, err = io.ReadAll(resp.Body) + s.AssertEqual(string(body), content2) + o = vpp.Vppctl("show http static server cache verbose") + s.Log(o) + s.AssertContains(o, "index.html") + s.AssertContains(o, "page.html") } func HttpStaticPathTraversalTest(s *NoTopoSuite) { @@ -118,7 +179,11 @@ func HttpStaticPathTraversalTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(404, resp.StatusCode) + s.AssertEmpty(resp.Header.Get("Content-Type")) + s.AssertEmpty(resp.Header.Get("Cache-Control")) + s.AssertEqual(int64(0), resp.ContentLength) } func HttpStaticMovedTest(s *NoTopoSuite) { @@ -134,8 +199,12 @@ func HttpStaticMovedTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(301, resp.StatusCode) - s.AssertNotEqual("", resp.Header.Get("Location")) + s.AssertEqual("http://"+serverAddress+"/tmp.aaa/index.html", resp.Header.Get("Location")) + s.AssertEmpty(resp.Header.Get("Content-Type")) + s.AssertEmpty(resp.Header.Get("Cache-Control")) + s.AssertEqual(int64(0), resp.ContentLength) } func HttpStaticNotFoundTest(s *NoTopoSuite) { @@ -150,7 +219,11 @@ func HttpStaticNotFoundTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(404, resp.StatusCode) + s.AssertEmpty(resp.Header.Get("Content-Type")) + s.AssertEmpty(resp.Header.Get("Cache-Control")) + s.AssertEqual(int64(0), resp.ContentLength) } func HttpCliMethodNotAllowedTest(s *NoTopoSuite) { @@ -164,9 +237,11 @@ func HttpCliMethodNotAllowedTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(405, resp.StatusCode) - // TODO: need to be fixed in http code - //s.AssertNotEqual("", resp.Header.Get("Allow")) + s.AssertNotEqual("", resp.Header.Get("Allow"), "server MUST generate an Allow header") + s.AssertEmpty(resp.Header.Get("Content-Type")) + s.AssertEqual(int64(0), resp.ContentLength) } func HttpCliBadRequestTest(s *NoTopoSuite) { @@ -180,7 +255,10 @@ func HttpCliBadRequestTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(400, resp.StatusCode) + s.AssertEmpty(resp.Header.Get("Content-Type")) + s.AssertEqual(int64(0), resp.ContentLength) } func HttpStaticBuildInUrlGetVersionTest(s *NoTopoSuite) { @@ -194,6 +272,7 @@ func HttpStaticBuildInUrlGetVersionTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(200, resp.StatusCode) data, err := io.ReadAll(resp.Body) s.AssertNil(err, fmt.Sprint(err)) @@ -203,6 +282,7 @@ func HttpStaticBuildInUrlGetVersionTest(s *NoTopoSuite) { s.AssertNotContains(string(data), "build_by") s.AssertNotContains(string(data), "build_host") s.AssertNotContains(string(data), "build_dir") + s.AssertContains(resp.Header.Get("Content-Type"), "json") } func HttpStaticBuildInUrlGetVersionVerboseTest(s *NoTopoSuite) { @@ -216,6 +296,7 @@ func HttpStaticBuildInUrlGetVersionVerboseTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(200, resp.StatusCode) data, err := io.ReadAll(resp.Body) s.AssertNil(err, fmt.Sprint(err)) @@ -225,6 +306,7 @@ func HttpStaticBuildInUrlGetVersionVerboseTest(s *NoTopoSuite) { s.AssertContains(string(data), "build_by") s.AssertContains(string(data), "build_host") s.AssertContains(string(data), "build_dir") + s.AssertContains(resp.Header.Get("Content-Type"), "json") } func HttpStaticBuildInUrlGetIfListTest(s *NoTopoSuite) { @@ -238,11 +320,13 @@ func HttpStaticBuildInUrlGetIfListTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(200, resp.StatusCode) data, err := io.ReadAll(resp.Body) s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(string(data), "interface_list") s.AssertContains(string(data), s.GetInterfaceByName(TapInterfaceName).Peer.Name()) + s.AssertContains(resp.Header.Get("Content-Type"), "json") } func HttpStaticBuildInUrlGetIfStatsTest(s *NoTopoSuite) { @@ -256,12 +340,14 @@ func HttpStaticBuildInUrlGetIfStatsTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(200, resp.StatusCode) data, err := io.ReadAll(resp.Body) s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(string(data), "interface_stats") s.AssertContains(string(data), "local0") s.AssertContains(string(data), s.GetInterfaceByName(TapInterfaceName).Peer.Name()) + s.AssertContains(resp.Header.Get("Content-Type"), "json") } func validatePostInterfaceStats(s *NoTopoSuite, data string) { @@ -284,10 +370,12 @@ func HttpStaticBuildInUrlPostIfStatsTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(200, resp.StatusCode) data, err := io.ReadAll(resp.Body) s.AssertNil(err, fmt.Sprint(err)) validatePostInterfaceStats(s, string(data)) + s.AssertContains(resp.Header.Get("Content-Type"), "json") } func HttpStaticMacTimeTest(s *NoTopoSuite) { @@ -302,12 +390,14 @@ func HttpStaticMacTimeTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(200, resp.StatusCode) data, err := io.ReadAll(resp.Body) s.AssertNil(err, fmt.Sprint(err)) s.AssertContains(string(data), "mactime") s.AssertContains(string(data), s.GetInterfaceByName(TapInterfaceName).Ip4AddressString()) s.AssertContains(string(data), s.GetInterfaceByName(TapInterfaceName).HwAddress.String()) + s.AssertContains(resp.Header.Get("Content-Type"), "json") } func HttpInvalidRequestLineTest(s *NoTopoSuite) { @@ -444,7 +534,10 @@ func HttpMethodNotImplementedTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(501, resp.StatusCode) + s.AssertEmpty(resp.Header.Get("Content-Type")) + s.AssertEqual(int64(0), resp.ContentLength) } func HttpVersionNotSupportedTest(s *NoTopoSuite) { @@ -468,12 +561,13 @@ func HttpUriDecodeTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) s.AssertEqual(200, resp.StatusCode) data, err := io.ReadAll(resp.Body) s.AssertNil(err, fmt.Sprint(err)) - s.Log(string(data)) s.AssertNotContains(string(data), "unknown input") s.AssertContains(string(data), "Compiler") + s.AssertContains(resp.Header.Get("Content-Type"), "html") } func HttpHeadersTest(s *NoTopoSuite) { @@ -539,5 +633,8 @@ func HeaderServerTest(s *NoTopoSuite) { resp, err := client.Do(req) s.AssertNil(err, fmt.Sprint(err)) defer resp.Body.Close() + s.Log(DumpHttpResp(resp, true)) + s.AssertEqual(200, resp.StatusCode) s.AssertEqual("http_cli_server", resp.Header.Get("Server")) + s.AssertContains(resp.Header.Get("Content-Type"), "html") } diff --git a/extras/hs-test/infra/utils.go b/extras/hs-test/infra/utils.go index 9619efbbf63..05b7b365487 100644 --- a/extras/hs-test/infra/utils.go +++ b/extras/hs-test/infra/utils.go @@ -5,6 +5,7 @@ import ( "io" "net" "net/http" + "net/http/httputil" "os" "strings" "time" @@ -96,6 +97,14 @@ func NewHttpClient() *http.Client { return client } +func DumpHttpResp(resp *http.Response, body bool) string { + dump, err := httputil.DumpResponse(resp, body) + if err != nil { + return "" + } + return string(dump) +} + func TcpSendReceive(address, data string) (string, error) { conn, err := net.DialTimeout("tcp", address, time.Second*30) if err != nil { |