2 * Copyright (C) 1996-2014 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"
18 CPPUNIT_TEST_SUITE_REGISTRATION( testHttpRequest
);
20 /** wrapper for testing HttpRequest object private and protected functions */
21 class PrivateHttpRequest
: public HttpRequest
24 bool doSanityCheckStartLine(MemBuf
*b
, const size_t h
, Http::StatusCode
*e
) { return sanityCheckStartLine(b
,h
,e
); };
27 /* init memory pools */
30 testHttpRequest::setUp()
33 httpHeaderInitModule();
37 * Test creating an HttpRequest object from a Url and method
40 testHttpRequest::testCreateFromUrlAndMethod()
43 unsigned short expected_port
;
44 char * url
= xstrdup("http://foo:90/bar");
45 HttpRequest
*aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_GET
);
47 HttpRequest
*nullRequest
= NULL
;
48 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
49 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
50 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest
->GetHost()));
51 CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest
->urlpath
);
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
));
56 /* vanilla url, different method */
57 url
= xstrdup("http://foo/bar");
58 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_PUT
);
60 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
61 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_PUT
);
62 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest
->GetHost()));
63 CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest
->urlpath
);
64 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
65 CPPUNIT_ASSERT_EQUAL(String("http://foo/bar"), String(url
));
68 /* a connect url with non-CONNECT data */
69 url
= xstrdup(":foo/bar");
70 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_CONNECT
);
72 CPPUNIT_ASSERT_EQUAL(nullRequest
, aRequest
);
74 /* a CONNECT url with CONNECT data */
75 url
= xstrdup("foo:45");
76 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_CONNECT
);
78 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
79 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_CONNECT
);
80 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest
->GetHost()));
81 CPPUNIT_ASSERT_EQUAL(String(""), aRequest
->urlpath
);
82 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_NONE
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
83 CPPUNIT_ASSERT_EQUAL(String("foo:45"), String(url
));
88 * Test creating an HttpRequest object from a Url alone.
91 testHttpRequest::testCreateFromUrl()
94 unsigned short expected_port
;
95 char * url
= xstrdup("http://foo:90/bar");
96 HttpRequest
*aRequest
= HttpRequest::CreateFromUrl(url
);
98 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
99 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
100 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest
->GetHost()));
101 CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest
->urlpath
);
102 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP
, static_cast<AnyP::ProtocolType
>(aRequest
->url
.getScheme()));
103 CPPUNIT_ASSERT_EQUAL(String("http://foo:90/bar"), String(url
));
108 * Test BUG: URL '2000:800:45' opens host 2000 port 800 !!
111 testHttpRequest::testIPv6HostColonBug()
113 unsigned short expected_port
;
115 HttpRequest
*aRequest
= NULL
;
117 /* valid IPv6 address without port */
118 url
= xstrdup("http://[2000:800::45]/foo");
119 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_GET
);
121 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
122 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
123 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest
->GetHost()));
124 CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest
->urlpath
);
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
));
129 /* valid IPv6 address with port */
130 url
= xstrdup("http://[2000:800::45]:90/foo");
131 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_GET
);
133 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
134 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
135 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest
->GetHost()));
136 CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest
->urlpath
);
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
));
141 /* IPv6 address as invalid (bug trigger) */
142 url
= xstrdup("http://2000:800::45/foo");
143 aRequest
= HttpRequest::CreateFromUrlAndMethod(url
, Http::METHOD_GET
);
145 CPPUNIT_ASSERT_EQUAL(expected_port
, aRequest
->port
);
146 CPPUNIT_ASSERT(aRequest
->method
== Http::METHOD_GET
);
147 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest
->GetHost()));
148 CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest
->urlpath
);
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
));
155 testHttpRequest::testSanityCheckStartLine()
158 PrivateHttpRequest engine
;
159 Http::StatusCode error
= Http::scNone
;
163 // a valid request line
164 input
.append("GET / HTTP/1.1\n\n", 16);
165 hdr_len
= headersEnd(input
.content(), input
.contentSize());
166 CPPUNIT_ASSERT(engine
.doSanityCheckStartLine(&input
, hdr_len
, &error
) );
167 CPPUNIT_ASSERT_EQUAL(error
, Http::scNone
);
169 error
= Http::scNone
;
171 input
.append("GET / HTTP/1.1\n\n", 18);
172 hdr_len
= headersEnd(input
.content(), input
.contentSize());
173 CPPUNIT_ASSERT(engine
.doSanityCheckStartLine(&input
, hdr_len
, &error
) );
174 CPPUNIT_ASSERT_EQUAL(error
, Http::scNone
);
176 error
= Http::scNone
;
178 // strange but valid methods
179 input
.append(". / HTTP/1.1\n\n", 14);
180 hdr_len
= headersEnd(input
.content(), input
.contentSize());
181 CPPUNIT_ASSERT(engine
.doSanityCheckStartLine(&input
, hdr_len
, &error
) );
182 CPPUNIT_ASSERT_EQUAL(error
, Http::scNone
);
184 error
= Http::scNone
;
186 input
.append("OPTIONS * HTTP/1.1\n\n", 20);
187 hdr_len
= headersEnd(input
.content(), input
.contentSize());
188 CPPUNIT_ASSERT(engine
.doSanityCheckStartLine(&input
, hdr_len
, &error
) );
189 CPPUNIT_ASSERT_EQUAL(error
, Http::scNone
);
191 error
= Http::scNone
;
195 // TODO binary code in method
199 // TODO no status (okay)
201 // TODO non-HTTP protocol
203 input
.append(" \n\n", 8);
204 hdr_len
= headersEnd(input
.content(), input
.contentSize());
205 CPPUNIT_ASSERT(!engine
.doSanityCheckStartLine(&input
, hdr_len
, &error
) );
206 CPPUNIT_ASSERT_EQUAL(error
, Http::scInvalidHeader
);
208 error
= Http::scNone
;