]> git.ipfire.org Git - thirdparty/squid.git/blame - src/tests/testHttpRequest.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / tests / testHttpRequest.cc
CommitLineData
4e0938ef 1/*
f70aedc4 2 * Copyright (C) 1996-2021 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"
5ceaee75 15#include "MasterXaction.h"
bf7af17b 16#include "mime_header.h"
602d9612 17#include "testHttpRequest.h"
7f861c77
AJ
18#include "unitTestMain.h"
19
c21ad0f5 20CPPUNIT_TEST_SUITE_REGISTRATION( testHttpRequest );
21
0f9db2d6
AJ
22/** wrapper for testing HttpRequest object private and protected functions */
23class PrivateHttpRequest : public HttpRequest
24{
25public:
e16571ed 26 PrivateHttpRequest(const MasterXaction::Pointer &mx) : HttpRequest(mx) {}
84ae6223 27 bool doSanityCheckStartLine(const char *b, const size_t h, Http::StatusCode *e) { return sanityCheckStartLine(b,h,e); };
0f9db2d6
AJ
28};
29
c21ad0f5 30/* init memory pools */
31
16555581 32void
33testHttpRequest::setUp()
c21ad0f5 34{
16555581 35 Mem::Init();
50a43a49 36 AnyP::UriScheme::Init();
0f9db2d6 37 httpHeaderInitModule();
16555581 38}
c21ad0f5 39
40/*
41 * Test creating an HttpRequest object from a Url and method
42 */
43void
d6067ac1 44testHttpRequest::testCreateFromUrl()
c21ad0f5 45{
2f8abb64 46 /* vanilla url, implicit method */
f45dd259 47 unsigned short expected_port;
6c880a16 48 SBuf url("http://foo:90/bar");
5ceaee75
CT
49 const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
50 HttpRequest *aRequest = HttpRequest::FromUrl(url, mx);
d6067ac1 51 expected_port = 90;
6c880a16 52 CPPUNIT_ASSERT(aRequest != nullptr);
d6067ac1
AJ
53 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
54 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
55 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host()));
56 CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest->url.path());
57 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
d6067ac1
AJ
58
59 /* vanilla url */
6c880a16 60 url = "http://foo:90/bar";
5ceaee75 61 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
c21ad0f5 62 expected_port = 90;
6c880a16 63 CPPUNIT_ASSERT(aRequest != nullptr);
5c51bffb 64 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
c2a7cefd 65 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
5c51bffb 66 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host()));
51b5dcf5 67 CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest->url.path());
4e3f4dc7 68 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
cc192b50 69
c21ad0f5 70 /* vanilla url, different method */
6c880a16 71 url = "http://foo/bar";
5ceaee75 72 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_PUT);
c21ad0f5 73 expected_port = 80;
6c880a16 74 CPPUNIT_ASSERT(aRequest != nullptr);
5c51bffb 75 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
c2a7cefd 76 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_PUT);
5c51bffb 77 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host()));
51b5dcf5 78 CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest->url.path());
4e3f4dc7 79 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
cc192b50 80
c21ad0f5 81 /* a connect url with non-CONNECT data */
d6067ac1 82 HttpRequest *nullRequest = nullptr;
6c880a16 83 url = ":foo/bar";
5ceaee75 84 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_CONNECT);
c21ad0f5 85 CPPUNIT_ASSERT_EQUAL(nullRequest, aRequest);
cc192b50 86
c21ad0f5 87 /* a CONNECT url with CONNECT data */
6c880a16 88 url = "foo:45";
5ceaee75 89 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_CONNECT);
c21ad0f5 90 expected_port = 45;
6c880a16 91 CPPUNIT_ASSERT(aRequest != nullptr);
5c51bffb 92 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
c2a7cefd 93 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_CONNECT);
5c51bffb 94 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host()));
51b5dcf5 95 CPPUNIT_ASSERT_EQUAL(SBuf(), aRequest->url.path());
4e3f4dc7 96 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_NONE, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
c21ad0f5 97
d6067ac1 98 // XXX: check METHOD_NONE input handling
c21ad0f5 99}
cc192b50 100
101/*
102 * Test BUG: URL '2000:800:45' opens host 2000 port 800 !!
103 */
104void
105testHttpRequest::testIPv6HostColonBug()
106{
f45dd259 107 unsigned short expected_port;
cc192b50 108 HttpRequest *aRequest = NULL;
109
110 /* valid IPv6 address without port */
6c880a16 111 SBuf url("http://[2000:800::45]/foo");
5ceaee75
CT
112 const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
113 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
cc192b50 114 expected_port = 80;
5c51bffb 115 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
c2a7cefd 116 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
5c51bffb 117 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host()));
51b5dcf5 118 CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest->url.path());
4e3f4dc7 119 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
cc192b50 120
121 /* valid IPv6 address with port */
6c880a16 122 url = "http://[2000:800::45]:90/foo";
5ceaee75 123 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
cc192b50 124 expected_port = 90;
5c51bffb 125 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
c2a7cefd 126 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
5c51bffb 127 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host()));
51b5dcf5 128 CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest->url.path());
4e3f4dc7 129 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
cc192b50 130
131 /* IPv6 address as invalid (bug trigger) */
6c880a16 132 url = "http://2000:800::45/foo";
5ceaee75 133 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
cc192b50 134 expected_port = 80;
5c51bffb 135 CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->url.port());
c2a7cefd 136 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
5c51bffb 137 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host()));
51b5dcf5 138 CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest->url.path());
4e3f4dc7 139 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
cc192b50 140}
0f9db2d6
AJ
141
142void
143testHttpRequest::testSanityCheckStartLine()
144{
145 MemBuf input;
5ceaee75
CT
146 const MasterXaction::Pointer mx = new MasterXaction(XactionInitiator::initClient);
147 PrivateHttpRequest engine(mx);
955394ce 148 Http::StatusCode error = Http::scNone;
0f9db2d6
AJ
149 size_t hdr_len;
150 input.init();
151
152 // a valid request line
153 input.append("GET / HTTP/1.1\n\n", 16);
154 hdr_len = headersEnd(input.content(), input.contentSize());
84ae6223 155 CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
955394ce 156 CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
0f9db2d6 157 input.reset();
955394ce 158 error = Http::scNone;
0f9db2d6
AJ
159
160 input.append("GET / HTTP/1.1\n\n", 18);
161 hdr_len = headersEnd(input.content(), input.contentSize());
84ae6223 162 CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
955394ce 163 CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
0f9db2d6 164 input.reset();
955394ce 165 error = Http::scNone;
0f9db2d6
AJ
166
167 // strange but valid methods
168 input.append(". / HTTP/1.1\n\n", 14);
169 hdr_len = headersEnd(input.content(), input.contentSize());
84ae6223 170 CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
955394ce 171 CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
0f9db2d6 172 input.reset();
955394ce 173 error = Http::scNone;
0f9db2d6
AJ
174
175 input.append("OPTIONS * HTTP/1.1\n\n", 20);
176 hdr_len = headersEnd(input.content(), input.contentSize());
84ae6223 177 CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
955394ce 178 CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
0f9db2d6 179 input.reset();
955394ce 180 error = Http::scNone;
0f9db2d6
AJ
181
182// TODO no method
183
184// TODO binary code in method
185
186// TODO no URL
187
188// TODO no status (okay)
189
190// TODO non-HTTP protocol
191
192 input.append(" \n\n", 8);
193 hdr_len = headersEnd(input.content(), input.contentSize());
84ae6223 194 CPPUNIT_ASSERT(!engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
955394ce 195 CPPUNIT_ASSERT_EQUAL(error, Http::scInvalidHeader);
0f9db2d6 196 input.reset();
955394ce 197 error = Http::scNone;
0f9db2d6 198}
f53969cc 199