testHttpRequest.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 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
21
24{
25public:
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
32void
34{
35 Mem::Init();
38}
39
40/*
41 * Test creating an HttpRequest object from a Url and method
42 */
43void
45{
46 /* vanilla url, implicit method */
47 SBuf url("http://foo:90/bar");
48 const auto mx = MasterXaction::MakePortless<XactionInitiator::initHtcp>();
49 HttpRequest *aRequest = HttpRequest::FromUrl(url, mx);
50 AnyP::KnownPort expected_port = 90;
51 CPPUNIT_ASSERT(aRequest != nullptr);
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
58 /* vanilla url */
59 url = "http://foo:90/bar";
60 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
61 expected_port = 90;
62 CPPUNIT_ASSERT(aRequest != nullptr);
63 CPPUNIT_ASSERT_EQUAL(expected_port, *aRequest->url.port());
64 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
65 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host()));
66 CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest->url.path());
67 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
68
69 /* vanilla url, different method */
70 url = "http://foo/bar";
71 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_PUT);
72 expected_port = 80;
73 CPPUNIT_ASSERT(aRequest != nullptr);
74 CPPUNIT_ASSERT_EQUAL(expected_port, *aRequest->url.port());
75 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_PUT);
76 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host()));
77 CPPUNIT_ASSERT_EQUAL(SBuf("/bar"), aRequest->url.path());
78 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
79
80 /* a connect url with non-CONNECT data */
81 HttpRequest *nullRequest = nullptr;
82 url = ":foo/bar";
83 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_CONNECT);
84 CPPUNIT_ASSERT_EQUAL(nullRequest, aRequest);
85
86 /* a CONNECT url with CONNECT data */
87 url = "foo:45";
88 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_CONNECT);
89 expected_port = 45;
90 CPPUNIT_ASSERT(aRequest != nullptr);
91 CPPUNIT_ASSERT_EQUAL(expected_port, *aRequest->url.port());
92 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_CONNECT);
93 CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->url.host()));
94 CPPUNIT_ASSERT_EQUAL(SBuf(), aRequest->url.path());
95 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_NONE, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
96
97 // XXX: check METHOD_NONE input handling
98}
99
100/*
101 * Test BUG: URL '2000:800:45' opens host 2000 port 800 !!
102 */
103void
105{
106 HttpRequest *aRequest = nullptr;
107
108 /* valid IPv6 address without port */
109 SBuf url("http://[2000:800::45]/foo");
110 const auto mx = MasterXaction::MakePortless<XactionInitiator::initHtcp>();
111 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
112 AnyP::KnownPort expected_port = 80;
113 CPPUNIT_ASSERT_EQUAL(expected_port, *aRequest->url.port());
114 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
115 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host()));
116 CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest->url.path());
117 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
118
119 /* valid IPv6 address with port */
120 url = "http://[2000:800::45]:90/foo";
121 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
122 expected_port = 90;
123 CPPUNIT_ASSERT_EQUAL(expected_port, *aRequest->url.port());
124 CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET);
125 CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->url.host()));
126 CPPUNIT_ASSERT_EQUAL(SBuf("/foo"), aRequest->url.path());
127 CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, static_cast<AnyP::ProtocolType>(aRequest->url.getScheme()));
128
129 /* IPv6 address as invalid (bug trigger) */
130 url = "http://2000:800::45/foo";
131 aRequest = HttpRequest::FromUrl(url, mx, Http::METHOD_GET);
132 expected_port = 80;
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}
139
140void
142{
143 MemBuf input;
144 const auto mx = MasterXaction::MakePortless<XactionInitiator::initHtcp>();
145 PrivateHttpRequest engine(mx);
147 size_t hdr_len;
148 input.init();
149
150 // a valid request line
151 input.append("GET / HTTP/1.1\n\n", 16);
152 hdr_len = headersEnd(input.content(), input.contentSize());
153 CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
154 CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
155 input.reset();
157
158 input.append("GET / HTTP/1.1\n\n", 18);
159 hdr_len = headersEnd(input.content(), input.contentSize());
160 CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
161 CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
162 input.reset();
164
165 // strange but valid methods
166 input.append(". / HTTP/1.1\n\n", 14);
167 hdr_len = headersEnd(input.content(), input.contentSize());
168 CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
169 CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
170 input.reset();
172
173 input.append("OPTIONS * HTTP/1.1\n\n", 20);
174 hdr_len = headersEnd(input.content(), input.contentSize());
175 CPPUNIT_ASSERT(engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
176 CPPUNIT_ASSERT_EQUAL(error, Http::scNone);
177 input.reset();
179
180// TODO no method
181
182// TODO binary code in method
183
184// TODO no URL
185
186// TODO no status (okay)
187
188// TODO non-HTTP protocol
189
190 input.append(" \n\n", 8);
191 hdr_len = headersEnd(input.content(), input.contentSize());
192 CPPUNIT_ASSERT(!engine.doSanityCheckStartLine(input.content(), hdr_len, &error) );
193 CPPUNIT_ASSERT_EQUAL(error, Http::scInvalidHeader);
194 input.reset();
196}
197
void httpHeaderInitModule(void)
Definition: HttpHeader.cc:121
void error(char *format,...)
static void Init()
initializes down-cased protocol scheme names array
Definition: UriScheme.cc:38
AnyP::UriScheme const & getScheme() const
Definition: Uri.h:67
void path(const char *p)
Definition: Uri.h:101
void port(const Port p)
reset authority port subcomponent
Definition: Uri.h:95
void host(const char *src)
Definition: Uri.cc:99
HttpRequestMethod method
Definition: HttpRequest.h:114
bool sanityCheckStartLine(const char *buf, const size_t hdr_len, Http::StatusCode *error) override
Definition: HttpRequest.cc:268
static HttpRequest * FromUrl(const SBuf &url, const MasterXaction::Pointer &, const HttpRequestMethod &method=Http::METHOD_GET)
Definition: HttpRequest.cc:517
AnyP::Uri url
the request URI
Definition: HttpRequest.h:115
Definition: MemBuf.h:24
void append(const char *c, int sz) override
Definition: MemBuf.cc:209
void init(mb_size_t szInit, mb_size_t szMax)
Definition: MemBuf.cc:93
char * content()
start of the added data
Definition: MemBuf.h:41
mb_size_t contentSize() const
available data size
Definition: MemBuf.h:47
void reset()
Definition: MemBuf.cc:129
bool doSanityCheckStartLine(const char *b, const size_t h, Http::StatusCode *e)
PrivateHttpRequest(const MasterXaction::Pointer &mx)
Definition: SBuf.h:94
void setUp() override
void testSanityCheckStartLine()
size_t headersEnd(const char *mime, size_t l, bool &containsObsFold)
Definition: mime_header.cc:17
uint16_t KnownPort
validated/supported port number; these values are never zero
Definition: UriScheme.h:23
ProtocolType
Definition: ProtocolType.h:23
@ PROTO_NONE
Definition: ProtocolType.h:24
@ PROTO_HTTP
Definition: ProtocolType.h:25
StatusCode
Definition: StatusCode.h:20
@ scInvalidHeader
Definition: StatusCode.h:86
@ scNone
Definition: StatusCode.h:21
@ METHOD_PUT
Definition: MethodType.h:27
@ METHOD_CONNECT
Definition: MethodType.h:29
@ METHOD_GET
Definition: MethodType.h:25
void Init()
Definition: old_api.cc:425
CPPUNIT_TEST_SUITE_REGISTRATION(TestHttpRequest)

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors