2 * Copyright (C) 1996-2015 The Squid Software Foundation and contributors
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.
11 #include <cppunit/TestAssert.h>
13 #include "HttpHeader.h"
14 #include "HttpRequest.h"
15 #include "mime_header.h"
16 #include "testHttpRequest.h"
17 #include "unitTestMain.h"
19 CPPUNIT_TEST_SUITE_REGISTRATION( testHttpRequest
);
21 /** wrapper for testing HttpRequest object private and protected functions */
22 class PrivateHttpRequest
: public HttpRequest
25 bool doSanityCheckStartLine(const char *b
, const size_t h
, Http::StatusCode
*e
) { return sanityCheckStartLine(b
,h
,e
); };
28 /* init memory pools */
31 testHttpRequest::setUp()
34 httpHeaderInitModule();
38 * Test creating an HttpRequest object from a Url and method
41 testHttpRequest::testCreateFromUrlAndMethod()
44 unsigned short expected_port
;
45 char * url
= xstrdup("http://foo:90/bar");
46 HttpRequest
*aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_GET
);
48 HttpRequest
*nullRequest
= NULL
;
49 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->url
.port());
50 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
51 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest
->url
.host()));
52 CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest
->url
.path());
53 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
54 CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url
));
57 /* vanilla url, different method */
58 url
= xstrdup("http://foo/bar");
59 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_PUT
);
61 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->url
.port());
62 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_PUT
);
63 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest
->url
.host()));
64 CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest
->url
.path());
65 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
66 CPPUNIT_ASSERT_EQUAL(String("http://foo/bar"), String(url
));
69 /* a connect url with non-CONNECT data */
70 url
= xstrdup(":foo/bar");
71 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_CONNECT
);
73 CPPUNIT_ASSERT_EQUAL(nullRequest
, aRequest
);
75 /* a CONNECT url with CONNECT data */
76 url
= xstrdup("foo:45");
77 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_CONNECT
);
79 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->url
.port());
80 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_CONNECT
);
81 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest
->url
.host()));
82 CPPUNIT_ASSERT_EQUAL(SBuf(), aRequest
->url
.path());
83 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_NONE
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
84 CPPUNIT_ASSERT_EQUAL(String("foo:45"), String(url
));
89 * Test creating an HttpRequest object from a Url alone.
92 testHttpRequest::testCreateFromUrl()
95 unsigned short expected_port
;
96 char * url
= xstrdup("http://foo:90/bar");
97 HttpRequest
*aRequest
= HttpRequest::CreateFromUrl(url
);
99 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->url
.port());
100 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
101 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest
->url
.host()));
102 CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest
->url
.path());
103 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
104 CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url
));
109 * Test BUG: URL '2000:800:45' opens host 2000 port 800 !!
112 testHttpRequest::testIPv6HostColonBug()
114 unsigned short expected_port
;
116 HttpRequest
*aRequest
= NULL
;
118 /* valid IPv6 address without port */
119 url
= xstrdup("http://[2000:800::45]/foo");
120 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_GET
);
122 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->url
.port());
123 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
124 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest
->url
.host()));
125 CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest
->url
.path());
126 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
127 CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]/foo"), String(url
));
130 /* valid IPv6 address with port */
131 url
= xstrdup("http://[2000:800::45]:90/foo");
132 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_GET
);
134 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->url
.port());
135 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
136 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest
->url
.host()));
137 CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest
->url
.path());
138 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
139 CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]:90/foo"), String(url
));
142 /* IPv6 address as invalid (bug trigger) */
143 url
= xstrdup("http://2000:800::45/foo");
144 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_GET
);
146 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->url
.port());
147 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
148 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest
->url
.host()));
149 CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest
->url
.path());
150 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
151 CPPUNIT_ASSERT_EQUAL(String("http://2000:800::45/foo"), String(url
));
156 testHttpRequest::testSanityCheckStartLine()
159 PrivateHttpRequest engine
;
160 Http::StatusCode error
= Http::scNone
;
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
);
170 error
= Http::scNone
;
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
);
177 error
= Http::scNone
;
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
);
185 error
= Http::scNone
;
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
);
192 error
= Http::scNone
;
196 // TODO binary code in method
200 // TODO no status (okay)
202 // TODO non-HTTP protocol
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
);
209 error
= Http::scNone
;