]>
Commit | Line | Data |
---|---|---|
4e0938ef | 1 | /* |
bde978a6 | 2 | * Copyright (C) 1996-2015 The Squid Software Foundation and contributors |
4e0938ef AJ |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
f7f3304a | 9 | #include "squid.h" |
e1f7507e | 10 | |
c21ad0f5 | 11 | #include <cppunit/TestAssert.h> |
12 | ||
ec6f82c1 | 13 | #include "HttpHeader.h" |
c21ad0f5 | 14 | #include "HttpRequest.h" |
b6149797 | 15 | #include "mime_header.h" |
602d9612 | 16 | #include "testHttpRequest.h" |
7f861c77 AJ |
17 | #include "unitTestMain.h" |
18 | ||
c21ad0f5 | 19 | CPPUNIT_TEST_SUITE_REGISTRATION( testHttpRequest ); |
20 | ||
0f9db2d6 AJ |
21 | /** wrapper for testing HttpRequest object private and protected functions */ |
22 | class PrivateHttpRequest : public HttpRequest | |
23 | { | |
24 | public: | |
84ae6223 | 25 | bool doSanityCheckStartLine(const char *b, const size_t h, Http::StatusCode *e) { return sanityCheckStartLine(b,h,e); }; |
0f9db2d6 AJ |
26 | }; |
27 | ||
c21ad0f5 | 28 | /* init memory pools */ |
29 | ||
16555581 | 30 | void |
31 | testHttpRequest::setUp() | |
c21ad0f5 | 32 | { |
16555581 | 33 | Mem::Init(); |
0f9db2d6 | 34 | httpHeaderInitModule(); |
16555581 | 35 | } |
c21ad0f5 | 36 | |
37 | /* | |
38 | * Test creating an HttpRequest object from a Url and method | |
39 | */ | |
40 | void | |
41 | testHttpRequest::testCreateFromUrlAndMethod() | |
42 | { | |
43 | /* vanilla url */ | |
f45dd259 | 44 | unsigned short expected_port; |
c21ad0f5 | 45 | char * url = xstrdup("http://foo:90/bar"); |
c2a7cefd | 46 | HttpRequest *aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_GET); |
c21ad0f5 | 47 | expected_port = 90; |
48 | HttpRequest *nullRequest = NULL; | |
5c51bffb | 49 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 50 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); |
5c51bffb | 51 | CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host())); |
30abd221 | 52 | CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest->urlpath); |
4e3f4dc7 | 53 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
30abd221 | 54 | CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url)); |
c21ad0f5 | 55 | xfree(url); |
cc192b50 | 56 | |
c21ad0f5 | 57 | /* vanilla url, different method */ |
58 | url = xstrdup("http://foo/bar"); | |
c2a7cefd | 59 | aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_PUT); |
c21ad0f5 | 60 | expected_port = 80; |
5c51bffb | 61 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 62 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_PUT); |
5c51bffb | 63 | CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host())); |
30abd221 | 64 | CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest->urlpath); |
4e3f4dc7 | 65 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
30abd221 | 66 | CPPUNIT_ASSERT_EQUAL(String("http://foo/bar"), String(url)); |
a0b3b22c | 67 | xfree(url); |
cc192b50 | 68 | |
c21ad0f5 | 69 | /* a connect url with non-CONNECT data */ |
70 | url = xstrdup(":foo/bar"); | |
c2a7cefd | 71 | aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_CONNECT); |
c21ad0f5 | 72 | xfree(url); |
73 | CPPUNIT_ASSERT_EQUAL(nullRequest, aRequest); | |
cc192b50 | 74 | |
c21ad0f5 | 75 | /* a CONNECT url with CONNECT data */ |
76 | url = xstrdup("foo:45"); | |
c2a7cefd | 77 | aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_CONNECT); |
c21ad0f5 | 78 | expected_port = 45; |
5c51bffb | 79 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 80 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_CONNECT); |
5c51bffb | 81 | CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host())); |
30abd221 | 82 | CPPUNIT_ASSERT_EQUAL(String(""), aRequest->urlpath); |
4e3f4dc7 | 83 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_NONE, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
30abd221 | 84 | CPPUNIT_ASSERT_EQUAL(String("foo:45"), String(url)); |
c21ad0f5 | 85 | xfree(url); |
86 | } | |
87 | ||
88 | /* | |
89 | * Test creating an HttpRequest object from a Url alone. | |
90 | */ | |
91 | void | |
92 | testHttpRequest::testCreateFromUrl() | |
93 | { | |
94 | /* vanilla url */ | |
f45dd259 | 95 | unsigned short expected_port; |
c21ad0f5 | 96 | char * url = xstrdup("http://foo:90/bar"); |
97 | HttpRequest *aRequest = HttpRequest::CreateFromUrl(url); | |
98 | expected_port = 90; | |
5c51bffb | 99 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 100 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); |
5c51bffb | 101 | CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host())); |
30abd221 | 102 | CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest->urlpath); |
4e3f4dc7 | 103 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
30abd221 | 104 | CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url)); |
c21ad0f5 | 105 | xfree(url); |
106 | } | |
cc192b50 | 107 | |
108 | /* | |
109 | * Test BUG: URL '2000:800:45' opens host 2000 port 800 !! | |
110 | */ | |
111 | void | |
112 | testHttpRequest::testIPv6HostColonBug() | |
113 | { | |
f45dd259 | 114 | unsigned short expected_port; |
cc192b50 | 115 | char * url = NULL; |
116 | HttpRequest *aRequest = NULL; | |
117 | ||
118 | /* valid IPv6 address without port */ | |
119 | url = xstrdup("http://[2000:800::45]/foo"); | |
c2a7cefd | 120 | aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_GET); |
cc192b50 | 121 | expected_port = 80; |
5c51bffb | 122 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 123 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); |
5c51bffb | 124 | CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host())); |
cc192b50 | 125 | CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest->urlpath); |
4e3f4dc7 | 126 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
cc192b50 | 127 | CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]/foo"), String(url)); |
128 | xfree(url); | |
129 | ||
130 | /* valid IPv6 address with port */ | |
131 | url = xstrdup("http://[2000:800::45]:90/foo"); | |
c2a7cefd | 132 | aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_GET); |
cc192b50 | 133 | expected_port = 90; |
5c51bffb | 134 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 135 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); |
5c51bffb | 136 | CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host())); |
cc192b50 | 137 | CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest->urlpath); |
4e3f4dc7 | 138 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
cc192b50 | 139 | CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]:90/foo"), String(url)); |
140 | xfree(url); | |
141 | ||
142 | /* IPv6 address as invalid (bug trigger) */ | |
143 | url = xstrdup("http://2000:800::45/foo"); | |
c2a7cefd | 144 | aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_GET); |
cc192b50 | 145 | expected_port = 80; |
5c51bffb | 146 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 147 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); |
5c51bffb | 148 | CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host())); |
cc192b50 | 149 | CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest->urlpath); |
4e3f4dc7 | 150 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
cc192b50 | 151 | CPPUNIT_ASSERT_EQUAL(String("http://2000:800::45/foo"), String(url)); |
152 | xfree(url); | |
153 | } | |
0f9db2d6 AJ |
154 | |
155 | void | |
156 | testHttpRequest::testSanityCheckStartLine() | |
157 | { | |
158 | MemBuf input; | |
159 | PrivateHttpRequest engine; | |
955394ce | 160 | Http::StatusCode error = Http::scNone; |
0f9db2d6 AJ |
161 | size_t hdr_len; |
162 | input.init(); | |
163 | ||
164 | // a valid request line | |
165 | input.append("GET / HTTP/1.1\n\n", 16); | |
166 | hdr_len = headersEnd(input.content(), input.contentSize()); | |
84ae6223 | 167 | CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) ); |
955394ce | 168 | CPPUNIT_ASSERT_EQUAL(error, Http::scNone); |
0f9db2d6 | 169 | input.reset(); |
955394ce | 170 | error = Http::scNone; |
0f9db2d6 AJ |
171 | |
172 | input.append("GET / HTTP/1.1\n\n", 18); | |
173 | hdr_len = headersEnd(input.content(), input.contentSize()); | |
84ae6223 | 174 | CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) ); |
955394ce | 175 | CPPUNIT_ASSERT_EQUAL(error, Http::scNone); |
0f9db2d6 | 176 | input.reset(); |
955394ce | 177 | error = Http::scNone; |
0f9db2d6 AJ |
178 | |
179 | // strange but valid methods | |
180 | input.append(". / HTTP/1.1\n\n", 14); | |
181 | hdr_len = headersEnd(input.content(), input.contentSize()); | |
84ae6223 | 182 | CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) ); |
955394ce | 183 | CPPUNIT_ASSERT_EQUAL(error, Http::scNone); |
0f9db2d6 | 184 | input.reset(); |
955394ce | 185 | error = Http::scNone; |
0f9db2d6 AJ |
186 | |
187 | input.append("OPTIONS * HTTP/1.1\n\n", 20); | |
188 | hdr_len = headersEnd(input.content(), input.contentSize()); | |
84ae6223 | 189 | CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) ); |
955394ce | 190 | CPPUNIT_ASSERT_EQUAL(error, Http::scNone); |
0f9db2d6 | 191 | input.reset(); |
955394ce | 192 | error = Http::scNone; |
0f9db2d6 AJ |
193 | |
194 | // TODO no method | |
195 | ||
196 | // TODO binary code in method | |
197 | ||
198 | // TODO no URL | |
199 | ||
200 | // TODO no status (okay) | |
201 | ||
202 | // TODO non-HTTP protocol | |
203 | ||
204 | input.append(" \n\n", 8); | |
205 | hdr_len = headersEnd(input.content(), input.contentSize()); | |
84ae6223 | 206 | CPPUNIT_ASSERT(!engine.doSanityCheckStartLine(input.content(), hdr_len, &error) ); |
955394ce | 207 | CPPUNIT_ASSERT_EQUAL(error, Http::scInvalidHeader); |
0f9db2d6 | 208 | input.reset(); |
955394ce | 209 | error = Http::scNone; |
0f9db2d6 | 210 | } |
f53969cc | 211 |