1 #define SQUID_UNIT_TEST 1
4 #include <cppunit/TestAssert.h>
6 #include "HttpHeader.h"
7 #include "HttpRequest.h"
9 #include "mime_header.h"
10 #include "testHttpRequest.h"
12 CPPUNIT_TEST_SUITE_REGISTRATION( testHttpRequest
);
14 /** wrapper for testing HttpRequest object private and protected functions */
15 class PrivateHttpRequest
: public HttpRequest
18 bool doSanityCheckStartLine(MemBuf
*b
, const size_t h
, Http::StatusCode
*e
) { return sanityCheckStartLine(b
,h
,e
); };
21 /* init memory pools */
24 testHttpRequest::setUp()
27 httpHeaderInitModule();
31 * Test creating an HttpRequest object from a Url and method
34 testHttpRequest::testCreateFromUrlAndMethod()
37 unsigned short expected_port
;
38 char * url
= xstrdup("http://foo:90/bar");
39 HttpRequest
*aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_GET
);
41 HttpRequest
*nullRequest
= NULL
;
42 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
43 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
44 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest
->GetHost()));
45 CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest
->urlpath
);
46 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
47 CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url
));
50 /* vanilla url, different method */
51 url
= xstrdup("http://foo/bar");
52 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_PUT
);
54 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
55 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_PUT
);
56 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest
->GetHost()));
57 CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest
->urlpath
);
58 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
59 CPPUNIT_ASSERT_EQUAL(String("http://foo/bar"), String(url
));
62 /* a connect url with non-CONNECT data */
63 url
= xstrdup(":foo/bar");
64 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_CONNECT
);
66 CPPUNIT_ASSERT_EQUAL(nullRequest
, aRequest
);
68 /* a CONNECT url with CONNECT data */
69 url
= xstrdup("foo:45");
70 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_CONNECT
);
72 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
73 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_CONNECT
);
74 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest
->GetHost()));
75 CPPUNIT_ASSERT_EQUAL(String(""), aRequest
->urlpath
);
76 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_NONE
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
77 CPPUNIT_ASSERT_EQUAL(String("foo:45"), String(url
));
82 * Test creating an HttpRequest object from a Url alone.
85 testHttpRequest::testCreateFromUrl()
88 unsigned short expected_port
;
89 char * url
= xstrdup("http://foo:90/bar");
90 HttpRequest
*aRequest
= HttpRequest::CreateFromUrl(url
);
92 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
93 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
94 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest
->GetHost()));
95 CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest
->urlpath
);
96 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
97 CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url
));
102 * Test BUG: URL '2000:800:45' opens host 2000 port 800 !!
105 testHttpRequest::testIPv6HostColonBug()
107 unsigned short expected_port
;
109 HttpRequest
*aRequest
= NULL
;
111 /* valid IPv6 address without port */
112 url
= xstrdup("http://[2000:800::45]/foo");
113 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_GET
);
115 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
116 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
117 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest
->GetHost()));
118 CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest
->urlpath
);
119 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
120 CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]/foo"), String(url
));
123 /* valid IPv6 address with port */
124 url
= xstrdup("http://[2000:800::45]:90/foo");
125 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_GET
);
127 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
128 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
129 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest
->GetHost()));
130 CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest
->urlpath
);
131 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
132 CPPUNIT_ASSERT_EQUAL(String("http://[2000:800::45]:90/foo"), String(url
));
135 /* IPv6 address as invalid (bug trigger) */
136 url
= xstrdup("http://2000:800::45/foo");
137 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_GET
);
139 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
140 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
141 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest
->GetHost()));
142 CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest
->urlpath
);
143 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
144 CPPUNIT_ASSERT_EQUAL(String("http://2000:800::45/foo"), String(url
));
149 testHttpRequest::testSanityCheckStartLine()
152 PrivateHttpRequest engine
;
153 Http::StatusCode error
= Http::scNone
;
157 // a valid request line
158 input
.append("GET / HTTP/1.1\n\n", 16);
159 hdr_len
= headersEnd(input
.content(), input
.contentSize());
160 CPPUNIT_ASSERT(engine
.doSanityCheckStartLine(&input
, hdr_len
, &error
) );
161 CPPUNIT_ASSERT_EQUAL(error
, Http::scNone
);
163 error
= Http::scNone
;
165 input
.append("GET / HTTP/1.1\n\n", 18);
166 hdr_len
= headersEnd(input
.content(), input
.contentSize());
167 CPPUNIT_ASSERT(engine
.doSanityCheckStartLine(&input
, hdr_len
, &error
) );
168 CPPUNIT_ASSERT_EQUAL(error
, Http::scNone
);
170 error
= Http::scNone
;
172 // strange but valid methods
173 input
.append(". / HTTP/1.1\n\n", 14);
174 hdr_len
= headersEnd(input
.content(), input
.contentSize());
175 CPPUNIT_ASSERT(engine
.doSanityCheckStartLine(&input
, hdr_len
, &error
) );
176 CPPUNIT_ASSERT_EQUAL(error
, Http::scNone
);
178 error
= Http::scNone
;
180 input
.append("OPTIONS * HTTP/1.1\n\n", 20);
181 hdr_len
= headersEnd(input
.content(), input
.contentSize());
182 CPPUNIT_ASSERT(engine
.doSanityCheckStartLine(&input
, hdr_len
, &error
) );
183 CPPUNIT_ASSERT_EQUAL(error
, Http::scNone
);
185 error
= Http::scNone
;
189 // TODO binary code in method
193 // TODO no status (okay)
195 // TODO non-HTTP protocol
197 input
.append(" \n\n", 8);
198 hdr_len
= headersEnd(input
.content(), input
.contentSize());
199 CPPUNIT_ASSERT(!engine
.doSanityCheckStartLine(&input
, hdr_len
, &error
) );
200 CPPUNIT_ASSERT_EQUAL(error
, Http::scInvalidHeader
);
202 error
= Http::scNone
;