]> git.ipfire.org Git - thirdparty/squid.git/blob - src/tests/testHttpRequest.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / tests / testHttpRequest.cc
1 /*
2 * Copyright (C) 1996-2019 The Squid Software Foundation and contributors
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
9 #include "squid.h"
10
11 #include <cppunit/TestAssert.h>
12
13 #include "HttpHeader.h"
14 #include "HttpRequest.h"
15 #include "MasterXaction.h"
16 #include "mime_header.h"
17 #include "testHttpRequest.h"
18 #include "unitTestMain.h"
19
20 CPPUNIT_TEST_SUITE_REGISTRATION( testHttpRequest );
21
22 /** wrapper for testing HttpRequest object private and protected functions */
23 class PrivateHttpRequest : public HttpRequest
24 {
25 public:
26 PrivateHttpRequest(const MasterXaction::Pointer &mx) : HttpRequest(mx) {}
27 bool doSanityCheckStartLine(const char *b, const size_t h, Http::StatusCode *e) { return sanityCheckStartLine(b,h,e); };
28 };
29
30 /* init memory pools */
31
32 void
33 testHttpRequest::setUp()
34 {
35 Mem::Init();
36 AnyP::UriScheme::Init();
37 httpHeaderInitModule();
38 }
39
40 /*
41 * Test creating an HttpRequest object from a Url and method
42 */
43 void
44 testHttpRequest::testCreateFromUrl()
45 {
46 /* vanilla url, implict method */
47 unsigned short expected_port;
48 char * url = xstrdup("http://foo:90/bar");
49 const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
50 HttpRequest *aRequest = HttpRequest::FromUrl(url, mx);
51 expected_port = 90;
52 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
53 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
54 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host()));
55 CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest->url.path());
56 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
57 CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url));
58 xfree(url);
59
60 /* vanilla url */
61 url = xstrdup("http://foo:90/bar");
62 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
63 expected_port = 90;
64 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
65 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
66 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host()));
67 CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest->url.path());
68 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
69 CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url));
70 xfree(url);
71
72 /* vanilla url, different method */
73 url = xstrdup("http://foo/bar");
74 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_PUT);
75 expected_port = 80;
76 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
77 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_PUT);
78 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host()));
79 CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest->url.path());
80 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
81 CPPUNIT_ASSERT_EQUAL(String("http://foo/bar"), String(url));
82 xfree(url);
83
84 /* a connect url with non-CONNECT data */
85 HttpRequest *nullRequest = nullptr;
86 url = xstrdup(":foo/bar");
87 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_CONNECT);
88 xfree(url);
89 CPPUNIT_ASSERT_EQUAL(nullRequest, aRequest);
90
91 /* a CONNECT url with CONNECT data */
92 url = xstrdup("foo:45");
93 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_CONNECT);
94 expected_port = 45;
95 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
96 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_CONNECT);
97 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host()));
98 CPPUNIT_ASSERT_EQUAL(SBuf(), aRequest->url.path());
99 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_NONE, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
100 CPPUNIT_ASSERT_EQUAL(String("foo:45"), String(url));
101 xfree(url);
102
103 // XXX: check METHOD_NONE input handling
104 }
105
106 /*
107 * Test BUG: URL '2000:800:45' opens host 2000 port 800 !!
108 */
109 void
110 testHttpRequest::testIPv6HostColonBug()
111 {
112 unsigned short expected_port;
113 char * url = NULL;
114 HttpRequest *aRequest = NULL;
115
116 /* valid IPv6 address without port */
117 url = xstrdup("http://[2000:800::45]/foo");
118 const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
119 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
120 expected_port = 80;
121 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
122 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
123 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host()));
124 CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest->url.path());
125 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
126 CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]/foo"), String(url));
127 xfree(url);
128
129 /* valid IPv6 address with port */
130 url = xstrdup("http://[2000:800::45]:90/foo");
131 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
132 expected_port = 90;
133 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
134 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
135 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host()));
136 CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest->url.path());
137 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
138 CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]:90/foo"), String(url));
139 xfree(url);
140
141 /* IPv6 address as invalid (bug trigger) */
142 url = xstrdup("http://2000:800::45/foo");
143 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
144 expected_port = 80;
145 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
146 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
147 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host()));
148 CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest->url.path());
149 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
150 CPPUNIT_ASSERT_EQUAL(String("http://2000:800::45/foo"), String(url));
151 xfree(url);
152 }
153
154 void
155 testHttpRequest::testSanityCheckStartLine()
156 {
157 MemBuf input;
158 const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
159 PrivateHttpRequest engine(mx);
160 Http::StatusCode error = Http::scNone;
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());
167 CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
168 CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
169 input.reset();
170 error = Http::scNone;
171
172 input.append("GET / HTTP/1.1\n\n", 18);
173 hdr_len = headersEnd(input.content(), input.contentSize());
174 CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
175 CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
176 input.reset();
177 error = Http::scNone;
178
179 // strange but valid methods
180 input.append(". / HTTP/1.1\n\n", 14);
181 hdr_len = headersEnd(input.content(), input.contentSize());
182 CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
183 CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
184 input.reset();
185 error = Http::scNone;
186
187 input.append("OPTIONS * HTTP/1.1\n\n", 20);
188 hdr_len = headersEnd(input.content(), input.contentSize());
189 CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
190 CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
191 input.reset();
192 error = Http::scNone;
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());
206 CPPUNIT_ASSERT(!engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
207 CPPUNIT_ASSERT_EQUAL(error, Http::scInvalidHeader);
208 input.reset();
209 error = Http::scNone;
210 }
211