1//
2// HTTPRequest.cpp
3//
4// Library: Net
5// Package: HTTP
6// Module: HTTPRequest
7//
8// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Net/HTTPRequest.h"
16#include "Poco/Net/NetException.h"
17#include "Poco/Net/NameValueCollection.h"
18#include "Poco/NumberFormatter.h"
19#include "Poco/Ascii.h"
20#include "Poco/String.h"
21
22
23using Poco::NumberFormatter;
24
25
26namespace Poco {
27namespace Net {
28
29
30const std::string HTTPRequest::HTTP_GET = "GET";
31const std::string HTTPRequest::HTTP_HEAD = "HEAD";
32const std::string HTTPRequest::HTTP_PUT = "PUT";
33const std::string HTTPRequest::HTTP_POST = "POST";
34const std::string HTTPRequest::HTTP_OPTIONS = "OPTIONS";
35const std::string HTTPRequest::HTTP_DELETE = "DELETE";
36const std::string HTTPRequest::HTTP_TRACE = "TRACE";
37const std::string HTTPRequest::HTTP_CONNECT = "CONNECT";
38const std::string HTTPRequest::HTTP_PATCH = "PATCH";
39const std::string HTTPRequest::HOST = "Host";
40const std::string HTTPRequest::COOKIE = "Cookie";
41const std::string HTTPRequest::AUTHORIZATION = "Authorization";
42const std::string HTTPRequest::PROXY_AUTHORIZATION = "Proxy-Authorization";
43const std::string HTTPRequest::UPGRADE = "Upgrade";
44const std::string HTTPRequest::EXPECT = "Expect";
45
46
47HTTPRequest::HTTPRequest():
48 _method(HTTP_GET),
49 _uri("/")
50{
51}
52
53
54HTTPRequest::HTTPRequest(const std::string& version):
55 HTTPMessage(version),
56 _method(HTTP_GET),
57 _uri("/")
58{
59}
60
61
62HTTPRequest::HTTPRequest(const std::string& method, const std::string& uri):
63 _method(method),
64 _uri(uri)
65{
66}
67
68
69HTTPRequest::HTTPRequest(const std::string& method, const std::string& uri, const std::string& version):
70 HTTPMessage(version),
71 _method(method),
72 _uri(uri)
73{
74}
75
76
77HTTPRequest::~HTTPRequest()
78{
79}
80
81
82void HTTPRequest::setMethod(const std::string& method)
83{
84 _method = method;
85}
86
87
88void HTTPRequest::setURI(const std::string& uri)
89{
90 _uri = uri;
91}
92
93
94void HTTPRequest::setHost(const std::string& host)
95{
96 set(HOST, host);
97}
98
99
100void HTTPRequest::setHost(const std::string& host, Poco::UInt16 port)
101{
102 std::string value;
103 if (host.find(':') != std::string::npos)
104 {
105 // IPv6 address
106 value.append("[");
107 value.append(host);
108 value.append("]");
109 }
110 else
111 {
112 value.append(host);
113 }
114
115 if (port != 80 && port != 443)
116 {
117 value.append(":");
118 NumberFormatter::append(value, port);
119 }
120 setHost(value);
121}
122
123
124const std::string& HTTPRequest::getHost() const
125{
126 return get(HOST);
127}
128
129
130void HTTPRequest::setCookies(const NameValueCollection& cookies)
131{
132 std::string cookie;
133 cookie.reserve(64);
134 for (NameValueCollection::ConstIterator it = cookies.begin(); it != cookies.end(); ++it)
135 {
136 if (it != cookies.begin())
137 cookie.append("; ");
138 cookie.append(it->first);
139 cookie.append("=");
140 cookie.append(it->second);
141 }
142 add(COOKIE, cookie);
143}
144
145
146void HTTPRequest::getCookies(NameValueCollection& cookies) const
147{
148 NameValueCollection::ConstIterator it = find(COOKIE);
149 while (it != end() && Poco::icompare(it->first, COOKIE) == 0)
150 {
151 splitParameters(it->second.begin(), it->second.end(), cookies);
152 ++it;
153 }
154}
155
156
157bool HTTPRequest::hasCredentials() const
158{
159 return has(AUTHORIZATION);
160}
161
162
163void HTTPRequest::getCredentials(std::string& scheme, std::string& authInfo) const
164{
165 getCredentials(AUTHORIZATION, scheme, authInfo);
166}
167
168
169void HTTPRequest::setCredentials(const std::string& scheme, const std::string& authInfo)
170{
171 setCredentials(AUTHORIZATION, scheme, authInfo);
172}
173
174
175bool HTTPRequest::hasProxyCredentials() const
176{
177 return has(PROXY_AUTHORIZATION);
178}
179
180
181void HTTPRequest::getProxyCredentials(std::string& scheme, std::string& authInfo) const
182{
183 getCredentials(PROXY_AUTHORIZATION, scheme, authInfo);
184}
185
186
187void HTTPRequest::setProxyCredentials(const std::string& scheme, const std::string& authInfo)
188{
189 setCredentials(PROXY_AUTHORIZATION, scheme, authInfo);
190}
191
192
193void HTTPRequest::write(std::ostream& ostr) const
194{
195 ostr << _method << " " << _uri << " " << getVersion() << "\r\n";
196 HTTPMessage::write(ostr);
197 ostr << "\r\n";
198}
199
200
201void HTTPRequest::read(std::istream& istr)
202{
203 static const int eof = std::char_traits<char>::eof();
204
205 std::string method;
206 std::string uri;
207 std::string version;
208 method.reserve(16);
209 uri.reserve(64);
210 version.reserve(16);
211 int ch = istr.get();
212 if (istr.bad()) throw NetException("Error reading HTTP request header");
213 if (ch == eof) throw NoMessageException();
214 while (Poco::Ascii::isSpace(ch)) ch = istr.get();
215 if (ch == eof) throw MessageException("No HTTP request header");
216 while (!Poco::Ascii::isSpace(ch) && ch != eof && method.length() < MAX_METHOD_LENGTH) { method += (char) ch; ch = istr.get(); }
217 if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP request method invalid or too long");
218 while (Poco::Ascii::isSpace(ch)) ch = istr.get();
219 while (!Poco::Ascii::isSpace(ch) && ch != eof && uri.length() < MAX_URI_LENGTH) { uri += (char) ch; ch = istr.get(); }
220 if (!Poco::Ascii::isSpace(ch)) throw MessageException("HTTP request URI invalid or too long");
221 while (Poco::Ascii::isSpace(ch)) ch = istr.get();
222 while (!Poco::Ascii::isSpace(ch) && ch != eof && version.length() < MAX_VERSION_LENGTH) { version += (char) ch; ch = istr.get(); }
223 if (!Poco::Ascii::isSpace(ch)) throw MessageException("Invalid HTTP version string");
224 while (ch != '\n' && ch != eof) { ch = istr.get(); }
225 HTTPMessage::read(istr);
226 ch = istr.get();
227 while (ch != '\n' && ch != eof) { ch = istr.get(); }
228 setMethod(method);
229 setURI(uri);
230 setVersion(version);
231}
232
233
234void HTTPRequest::getCredentials(const std::string& header, std::string& scheme, std::string& authInfo) const
235{
236 scheme.clear();
237 authInfo.clear();
238 if (has(header))
239 {
240 const std::string& auth = get(header);
241 std::string::const_iterator it = auth.begin();
242 std::string::const_iterator end = auth.end();
243 while (it != end && Poco::Ascii::isSpace(*it)) ++it;
244 while (it != end && !Poco::Ascii::isSpace(*it)) scheme += *it++;
245 while (it != end && Poco::Ascii::isSpace(*it)) ++it;
246 while (it != end) authInfo += *it++;
247 }
248 else throw NotAuthenticatedException();
249}
250
251
252void HTTPRequest::setCredentials(const std::string& header, const std::string& scheme, const std::string& authInfo)
253{
254 std::string auth(scheme);
255 auth.append(" ");
256 auth.append(authInfo);
257 set(header, auth);
258}
259
260
261bool HTTPRequest::getExpectContinue() const
262{
263 const std::string& expect = get(EXPECT, EMPTY);
264 return !expect.empty() && icompare(expect, "100-continue") == 0;
265}
266
267
268void HTTPRequest::setExpectContinue(bool expectContinue)
269{
270 if (expectContinue)
271 set(EXPECT, "100-continue");
272 else
273 erase(EXPECT);
274}
275
276
277} } // namespace Poco::Net
278