]>
Commit | Line | Data |
---|---|---|
4e0938ef | 1 | /* |
4ac4a490 | 2 | * Copyright (C) 1996-2017 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 | |
d6067ac1 | 41 | testHttpRequest::testCreateFromUrl() |
c21ad0f5 | 42 | { |
d6067ac1 | 43 | /* vanilla url, implict method */ |
f45dd259 | 44 | unsigned short expected_port; |
c21ad0f5 | 45 | char * url = xstrdup("http://foo:90/bar"); |
d6067ac1 AJ |
46 | HttpRequest *aRequest = HttpRequest::CreateFromUrl(url); |
47 | expected_port = 90; | |
48 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); | |
49 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); | |
50 | CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host())); | |
51 | CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest->url.path()); | |
52 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); | |
53 | CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url)); | |
54 | xfree(url); | |
55 | ||
56 | /* vanilla url */ | |
57 | url = xstrdup("http://foo:90/bar"); | |
58 | aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_GET); | |
c21ad0f5 | 59 | expected_port = 90; |
5c51bffb | 60 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 61 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); |
5c51bffb | 62 | CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host())); |
51b5dcf5 | 63 | CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest->url.path()); |
4e3f4dc7 | 64 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
30abd221 | 65 | CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url)); |
c21ad0f5 | 66 | xfree(url); |
cc192b50 | 67 | |
c21ad0f5 | 68 | /* vanilla url, different method */ |
69 | url = xstrdup("http://foo/bar"); | |
d6067ac1 | 70 | aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_PUT); |
c21ad0f5 | 71 | expected_port = 80; |
5c51bffb | 72 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 73 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_PUT); |
5c51bffb | 74 | CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host())); |
51b5dcf5 | 75 | CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest->url.path()); |
4e3f4dc7 | 76 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
30abd221 | 77 | CPPUNIT_ASSERT_EQUAL(String("http://foo/bar"), String(url)); |
a0b3b22c | 78 | xfree(url); |
cc192b50 | 79 | |
c21ad0f5 | 80 | /* a connect url with non-CONNECT data */ |
d6067ac1 | 81 | HttpRequest *nullRequest = nullptr; |
c21ad0f5 | 82 | url = xstrdup(":foo/bar"); |
d6067ac1 | 83 | aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_CONNECT); |
c21ad0f5 | 84 | xfree(url); |
85 | CPPUNIT_ASSERT_EQUAL(nullRequest, aRequest); | |
cc192b50 | 86 | |
c21ad0f5 | 87 | /* a CONNECT url with CONNECT data */ |
88 | url = xstrdup("foo:45"); | |
d6067ac1 | 89 | aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_CONNECT); |
c21ad0f5 | 90 | expected_port = 45; |
5c51bffb | 91 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 92 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_CONNECT); |
5c51bffb | 93 | CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host())); |
51b5dcf5 | 94 | CPPUNIT_ASSERT_EQUAL(SBuf(), aRequest->url.path()); |
4e3f4dc7 | 95 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_NONE, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
30abd221 | 96 | CPPUNIT_ASSERT_EQUAL(String("foo:45"), String(url)); |
c21ad0f5 | 97 | xfree(url); |
c21ad0f5 | 98 | |
d6067ac1 | 99 | // XXX: check METHOD_NONE input handling |
c21ad0f5 | 100 | } |
cc192b50 | 101 | |
102 | /* | |
103 | * Test BUG: URL '2000:800:45' opens host 2000 port 800 !! | |
104 | */ | |
105 | void | |
106 | testHttpRequest::testIPv6HostColonBug() | |
107 | { | |
f45dd259 | 108 | unsigned short expected_port; |
cc192b50 | 109 | char * url = NULL; |
110 | HttpRequest *aRequest = NULL; | |
111 | ||
112 | /* valid IPv6 address without port */ | |
113 | url = xstrdup("http://[2000:800::45]/foo"); | |
d6067ac1 | 114 | aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_GET); |
cc192b50 | 115 | expected_port = 80; |
5c51bffb | 116 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 117 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); |
5c51bffb | 118 | CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host())); |
51b5dcf5 | 119 | CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest->url.path()); |
4e3f4dc7 | 120 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
cc192b50 | 121 | CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]/foo"), String(url)); |
122 | xfree(url); | |
123 | ||
124 | /* valid IPv6 address with port */ | |
125 | url = xstrdup("http://[2000:800::45]:90/foo"); | |
d6067ac1 | 126 | aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_GET); |
cc192b50 | 127 | expected_port = 90; |
5c51bffb | 128 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 129 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); |
5c51bffb | 130 | CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host())); |
51b5dcf5 | 131 | CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest->url.path()); |
4e3f4dc7 | 132 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
cc192b50 | 133 | CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]:90/foo"), String(url)); |
134 | xfree(url); | |
135 | ||
136 | /* IPv6 address as invalid (bug trigger) */ | |
137 | url = xstrdup("http://2000:800::45/foo"); | |
d6067ac1 | 138 | aRequest = HttpRequest::CreateFromUrl(url, Http::METHOD_GET); |
cc192b50 | 139 | expected_port = 80; |
5c51bffb | 140 | CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port()); |
c2a7cefd | 141 | CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); |
5c51bffb | 142 | CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host())); |
51b5dcf5 | 143 | CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest->url.path()); |
4e3f4dc7 | 144 | CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme())); |
cc192b50 | 145 | CPPUNIT_ASSERT_EQUAL(String("http://2000:800::45/foo"), String(url)); |
146 | xfree(url); | |
147 | } | |
0f9db2d6 AJ |
148 | |
149 | void | |
150 | testHttpRequest::testSanityCheckStartLine() | |
151 | { | |
152 | MemBuf input; | |
153 | PrivateHttpRequest engine; | |
955394ce | 154 | Http::StatusCode error = Http::scNone; |
0f9db2d6 AJ |
155 | size_t hdr_len; |
156 | input.init(); | |
157 | ||
158 | // a valid request line | |
159 | input.append("GET / HTTP/1.1\n\n", 16); | |
160 | hdr_len = headersEnd(input.content(), input.contentSize()); | |
84ae6223 | 161 | CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) ); |
955394ce | 162 | CPPUNIT_ASSERT_EQUAL(error, Http::scNone); |
0f9db2d6 | 163 | input.reset(); |
955394ce | 164 | error = Http::scNone; |
0f9db2d6 AJ |
165 | |
166 | input.append("GET / HTTP/1.1\n\n", 18); | |
167 | hdr_len = headersEnd(input.content(), input.contentSize()); | |
84ae6223 | 168 | CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) ); |
955394ce | 169 | CPPUNIT_ASSERT_EQUAL(error, Http::scNone); |
0f9db2d6 | 170 | input.reset(); |
955394ce | 171 | error = Http::scNone; |
0f9db2d6 AJ |
172 | |
173 | // strange but valid methods | |
174 | input.append(". / HTTP/1.1\n\n", 14); | |
175 | hdr_len = headersEnd(input.content(), input.contentSize()); | |
84ae6223 | 176 | CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) ); |
955394ce | 177 | CPPUNIT_ASSERT_EQUAL(error, Http::scNone); |
0f9db2d6 | 178 | input.reset(); |
955394ce | 179 | error = Http::scNone; |
0f9db2d6 AJ |
180 | |
181 | input.append("OPTIONS * HTTP/1.1\n\n", 20); | |
182 | hdr_len = headersEnd(input.content(), input.contentSize()); | |
84ae6223 | 183 | CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) ); |
955394ce | 184 | CPPUNIT_ASSERT_EQUAL(error, Http::scNone); |
0f9db2d6 | 185 | input.reset(); |
955394ce | 186 | error = Http::scNone; |
0f9db2d6 AJ |
187 | |
188 | // TODO no method | |
189 | ||
190 | // TODO binary code in method | |
191 | ||
192 | // TODO no URL | |
193 | ||
194 | // TODO no status (okay) | |
195 | ||
196 | // TODO non-HTTP protocol | |
197 | ||
198 | input.append(" \n\n", 8); | |
199 | hdr_len = headersEnd(input.content(), input.contentSize()); | |
84ae6223 | 200 | CPPUNIT_ASSERT(!engine.doSanityCheckStartLine(input.content(), hdr_len, &error) ); |
955394ce | 201 | CPPUNIT_ASSERT_EQUAL(error, Http::scInvalidHeader); |
0f9db2d6 | 202 | input.reset(); |
955394ce | 203 | error = Http::scNone; |
0f9db2d6 | 204 | } |
f53969cc | 205 |