]> git.ipfire.org Git - thirdparty/squid.git/blame - src/adaptation/ecap/MessageRep.cc
Allow uri=value parameter when specifying adaptation service URIs.
[thirdparty/squid.git] / src / adaptation / ecap / MessageRep.cc
CommitLineData
fdc96a39 1/*
b510f3a1 2 * DEBUG: section 93 eCAP Interface
fdc96a39 3 */
fdc96a39 4#include "squid.h"
cf331c99
AR
5#include "HttpRequest.h"
6#include "HttpReply.h"
7#include "BodyPipe.h"
cf331c99
AR
8#include <libecap/common/names.h>
9#include <libecap/common/area.h>
10#include <libecap/common/version.h>
1f3c65fc
AR
11#include "adaptation/ecap/MessageRep.h"
12#include "adaptation/ecap/XactionRep.h"
13#include "adaptation/ecap/Host.h" /* for protocol constants */
3d93a84d 14#include "base/TextException.h"
fdc96a39 15
cf331c99
AR
16/* HeaderRep */
17
574b508c 18Adaptation::Ecap::HeaderRep::HeaderRep(HttpMsg &aMessage): theHeader(aMessage.header),
26ac0430 19 theMessage(aMessage)
cf331c99
AR
20{
21}
22
cf331c99 23bool
574b508c 24Adaptation::Ecap::HeaderRep::hasAny(const Name &name) const
cf331c99
AR
25{
26 const http_hdr_type squidId = TranslateHeaderId(name);
27 // XXX: optimize to remove getByName: we do not need the value here
28 return squidId == HDR_OTHER ?
26ac0430
AJ
29 theHeader.getByName(name.image().c_str()).size() > 0:
30 (bool)theHeader.has(squidId);
cf331c99
AR
31}
32
574b508c
AR
33Adaptation::Ecap::HeaderRep::Value
34Adaptation::Ecap::HeaderRep::value(const Name &name) const
cf331c99
AR
35{
36 const http_hdr_type squidId = TranslateHeaderId(name);
37 const String value = squidId == HDR_OTHER ?
26ac0430
AJ
38 theHeader.getByName(name.image().c_str()) :
39 theHeader.getStrOrList(squidId);
5e6f9b92 40 return value.defined() ?
001eaf80 41 Value::FromTempString(value.termedBuf()) : Value();
cf331c99
AR
42}
43
44void
574b508c 45Adaptation::Ecap::HeaderRep::add(const Name &name, const Value &value)
cf331c99
AR
46{
47 const http_hdr_type squidId = TranslateHeaderId(name); // HDR_OTHER OK
48 HttpHeaderEntry *e = new HttpHeaderEntry(squidId, name.image().c_str(),
26ac0430 49 value.toString().c_str());
cf331c99
AR
50 theHeader.addEntry(e);
51}
52
53void
574b508c 54Adaptation::Ecap::HeaderRep::removeAny(const Name &name)
cf331c99
AR
55{
56 const http_hdr_type squidId = TranslateHeaderId(name);
57 if (squidId == HDR_OTHER)
58 theHeader.delByName(name.image().c_str());
59 else
60 theHeader.delById(squidId);
61}
62
63libecap::Area
574b508c 64Adaptation::Ecap::HeaderRep::image() const
cf331c99
AR
65{
66 MemBuf mb;
67 mb.init();
68
69 Packer p;
70 packerToMemInit(&p, &mb);
71 theMessage.packInto(&p, true);
72 packerClean(&p);
73 return Area::FromTempBuffer(mb.content(), mb.contentSize());
74}
75
76// throws on failures
77void
574b508c 78Adaptation::Ecap::HeaderRep::parse(const Area &buf)
cf331c99
AR
79{
80 MemBuf mb;
81 mb.init();
82 mb.append(buf.start, buf.size);
83 http_status error;
84 Must(theMessage.parse(&mb, true, &error));
85}
86
77773405 87http_hdr_type
574b508c 88Adaptation::Ecap::HeaderRep::TranslateHeaderId(const Name &name)
77773405
AR
89{
90 if (name.assignedHostId())
91 return static_cast<http_hdr_type>(name.hostId());
92 return HDR_OTHER;
93}
94
95
96/* FirstLineRep */
97
574b508c 98Adaptation::Ecap::FirstLineRep::FirstLineRep(HttpMsg &aMessage): theMessage(aMessage)
77773405
AR
99{
100}
101
cf331c99 102libecap::Version
574b508c 103Adaptation::Ecap::FirstLineRep::version() const
cf331c99
AR
104{
105 return libecap::Version(theMessage.http_ver.major,
26ac0430 106 theMessage.http_ver.minor);
cf331c99
AR
107}
108
109void
574b508c 110Adaptation::Ecap::FirstLineRep::version(const libecap::Version &aVersion)
cf331c99
AR
111{
112 theMessage.http_ver.major = aVersion.majr;
113 theMessage.http_ver.minor = aVersion.minr;
114}
115
116libecap::Name
574b508c 117Adaptation::Ecap::FirstLineRep::protocol() const
cf331c99
AR
118{
119 // TODO: optimize?
120 switch (theMessage.protocol) {
26ac0430
AJ
121 case PROTO_HTTP:
122 return libecap::protocolHttp;
123 case PROTO_HTTPS:
124 return libecap::protocolHttps;
125 case PROTO_FTP:
126 return libecap::protocolFtp;
127 case PROTO_GOPHER:
128 return libecap::protocolGopher;
129 case PROTO_WAIS:
130 return libecap::protocolWais;
131 case PROTO_WHOIS:
132 return libecap::protocolWhois;
133 case PROTO_URN:
134 return libecap::protocolUrn;
135 case PROTO_ICP:
136 return protocolIcp;
cf331c99 137#if USE_HTCP
26ac0430
AJ
138 case PROTO_HTCP:
139 return protocolHtcp;
cf331c99 140#endif
26ac0430
AJ
141 case PROTO_CACHEOBJ:
142 return protocolCacheObj;
143 case PROTO_INTERNAL:
144 return protocolInternal;
48d54e4d
AJ
145 case PROTO_ICY:
146 return Name();
26ac0430
AJ
147 case PROTO_NONE:
148 return Name();
149
150 case PROTO_MAX:
151 break; // should not happen
cf331c99
AR
152 // no default to catch PROTO_ additions
153 }
154 Must(false); // not reached
155 return Name();
156}
157
158void
574b508c 159Adaptation::Ecap::FirstLineRep::protocol(const Name &p)
cf331c99
AR
160{
161 // TODO: what happens if we fail to translate some protocol?
162 theMessage.protocol = TranslateProtocolId(p);
163}
164
77773405 165protocol_t
574b508c 166Adaptation::Ecap::FirstLineRep::TranslateProtocolId(const Name &name)
77773405
AR
167{
168 if (name.assignedHostId())
169 return static_cast<protocol_t>(name.hostId());
170 return PROTO_NONE; // no PROTO_OTHER
171}
172
cf331c99
AR
173
174/* RequestHeaderRep */
175
574b508c 176Adaptation::Ecap::RequestLineRep::RequestLineRep(HttpRequest &aMessage):
26ac0430 177 FirstLineRep(aMessage), theMessage(aMessage)
cf331c99
AR
178{
179}
180
181void
574b508c 182Adaptation::Ecap::RequestLineRep::uri(const Area &aUri)
cf331c99
AR
183{
184 // TODO: if method is not set, urlPath will assume it is not connect;
185 // Can we change urlParse API to remove the method parameter?
186 // TODO: optimize: urlPath should take constant URL buffer
187 char *buf = xstrdup(aUri.toString().c_str());
188 const bool ok = urlParse(theMessage.method, buf, &theMessage);
189 xfree(buf);
190 Must(ok);
191}
192
574b508c
AR
193Adaptation::Ecap::RequestLineRep::Area
194Adaptation::Ecap::RequestLineRep::uri() const
cf331c99 195{
bb790702 196 return Area::FromTempBuffer(theMessage.urlpath.rawBuf(),
26ac0430 197 theMessage.urlpath.size());
cf331c99
AR
198}
199
200void
574b508c 201Adaptation::Ecap::RequestLineRep::method(const Name &aMethod)
cf331c99
AR
202{
203 if (aMethod.assignedHostId()) {
204 const int id = aMethod.hostId();
205 Must(METHOD_NONE < id && id < METHOD_ENUM_END);
206 Must(id != METHOD_OTHER);
207 theMessage.method = HttpRequestMethod(static_cast<_method_t>(id));
208 } else {
209 const std::string &image = aMethod.image();
210 theMessage.method = HttpRequestMethod(image.data(),
26ac0430 211 image.data() + image.size());
cf331c99
AR
212 }
213}
214
574b508c
AR
215Adaptation::Ecap::RequestLineRep::Name
216Adaptation::Ecap::RequestLineRep::method() const
cf331c99
AR
217{
218 switch (theMessage.method.id()) {
26ac0430
AJ
219 case METHOD_GET:
220 return libecap::methodGet;
221 case METHOD_POST:
222 return libecap::methodPost;
223 case METHOD_PUT:
224 return libecap::methodPut;
225 case METHOD_HEAD:
226 return libecap::methodHead;
227 case METHOD_CONNECT:
228 return libecap::methodConnect;
229 case METHOD_DELETE:
230 return libecap::methodDelete;
231 case METHOD_TRACE:
232 return libecap::methodTrace;
233 default:
234 return Name(theMessage.method.image());
cf331c99
AR
235 }
236}
237
77773405 238libecap::Version
574b508c 239Adaptation::Ecap::RequestLineRep::version() const
77773405
AR
240{
241 return FirstLineRep::version();
242}
243
244void
574b508c 245Adaptation::Ecap::RequestLineRep::version(const libecap::Version &aVersion)
77773405
AR
246{
247 FirstLineRep::version(aVersion);
248}
249
250libecap::Name
574b508c 251Adaptation::Ecap::RequestLineRep::protocol() const
77773405
AR
252{
253 return FirstLineRep::protocol();
254}
255
256void
574b508c 257Adaptation::Ecap::RequestLineRep::protocol(const Name &p)
77773405
AR
258{
259 FirstLineRep::protocol(p);
260}
261
cf331c99
AR
262
263/* ReplyHeaderRep */
264
574b508c 265Adaptation::Ecap::StatusLineRep::StatusLineRep(HttpReply &aMessage):
26ac0430 266 FirstLineRep(aMessage), theMessage(aMessage)
cf331c99
AR
267{
268}
269
270void
574b508c 271Adaptation::Ecap::StatusLineRep::statusCode(int code)
cf331c99
AR
272{
273 // TODO: why is .status a enum? Do we not support unknown statuses?
274 theMessage.sline.status = static_cast<http_status>(code);
275}
276
277int
574b508c 278Adaptation::Ecap::StatusLineRep::statusCode() const
cf331c99
AR
279{
280 // TODO: see statusCode(code) TODO above
281 return static_cast<int>(theMessage.sline.status);
282}
283
284void
574b508c 285Adaptation::Ecap::StatusLineRep::reasonPhrase(const Area &)
cf331c99
AR
286{
287 // Squid does not support custom reason phrases
288 theMessage.sline.reason = NULL;
289}
290
574b508c
AR
291Adaptation::Ecap::StatusLineRep::Area
292Adaptation::Ecap::StatusLineRep::reasonPhrase() const
cf331c99
AR
293{
294 return theMessage.sline.reason ?
26ac0430 295 Area::FromTempString(std::string(theMessage.sline.reason)) : Area();
cf331c99
AR
296}
297
77773405 298libecap::Version
574b508c 299Adaptation::Ecap::StatusLineRep::version() const
77773405
AR
300{
301 return FirstLineRep::version();
302}
303
304void
574b508c 305Adaptation::Ecap::StatusLineRep::version(const libecap::Version &aVersion)
77773405
AR
306{
307 FirstLineRep::version(aVersion);
308}
309
310libecap::Name
574b508c 311Adaptation::Ecap::StatusLineRep::protocol() const
77773405
AR
312{
313 return FirstLineRep::protocol();
314}
315
316void
574b508c 317Adaptation::Ecap::StatusLineRep::protocol(const Name &p)
77773405
AR
318{
319 FirstLineRep::protocol(p);
320}
cf331c99
AR
321
322/* BodyRep */
323
574b508c 324Adaptation::Ecap::BodyRep::BodyRep(const BodyPipe::Pointer &aBody): theBody(aBody)
cf331c99
AR
325{
326}
327
77773405 328void
574b508c 329Adaptation::Ecap::BodyRep::tie(const BodyPipe::Pointer &aBody)
77773405
AR
330{
331 Must(!theBody);
332 Must(aBody != NULL);
333 theBody = aBody;
334}
335
574b508c
AR
336Adaptation::Ecap::BodyRep::BodySize
337Adaptation::Ecap::BodyRep::bodySize() const
cf331c99 338{
77773405 339 return !theBody ? BodySize() : BodySize(theBody->bodySize());
cf331c99
AR
340}
341
cf331c99
AR
342
343/* MessageRep */
344
574b508c 345Adaptation::Ecap::MessageRep::MessageRep(HttpMsg *rawHeader):
26ac0430
AJ
346 theMessage(rawHeader), theFirstLineRep(NULL),
347 theHeaderRep(NULL), theBodyRep(NULL)
cf331c99
AR
348{
349 Must(theMessage.header); // we do not want to represent a missing message
350
351 if (HttpRequest *req = dynamic_cast<HttpRequest*>(theMessage.header))
77773405 352 theFirstLineRep = new RequestLineRep(*req);
e1381638
AJ
353 else if (HttpReply *rep = dynamic_cast<HttpReply*>(theMessage.header))
354 theFirstLineRep = new StatusLineRep(*rep);
cf331c99 355 else
e1381638 356 Must(false); // unknown message header type
cf331c99 357
77773405
AR
358 theHeaderRep = new HeaderRep(*theMessage.header);
359
cf331c99
AR
360 if (theMessage.body_pipe != NULL)
361 theBodyRep = new BodyRep(theMessage.body_pipe);
362}
363
574b508c 364Adaptation::Ecap::MessageRep::~MessageRep()
cf331c99 365{
77773405 366 delete theBodyRep;
80031342
AR
367 delete theHeaderRep;
368 delete theFirstLineRep;
77773405
AR
369}
370
371libecap::shared_ptr<libecap::Message>
574b508c 372Adaptation::Ecap::MessageRep::clone() const
77773405
AR
373{
374 HttpMsg *hdr = theMessage.header->clone();
375 hdr->body_pipe = NULL; // if any; TODO: remove pipe cloning from ::clone?
376 libecap::shared_ptr<libecap::Message> res(new MessageRep(hdr));
377
378 // restore indication of a body if needed, but not the pipe
379 if (theMessage.header->body_pipe != NULL)
380 res->addBody();
381
382 return res;
383}
384
385libecap::FirstLine &
574b508c 386Adaptation::Ecap::MessageRep::firstLine()
77773405
AR
387{
388 return *theFirstLineRep;
389}
390
391const libecap::FirstLine &
574b508c 392Adaptation::Ecap::MessageRep::firstLine() const
77773405
AR
393{
394 return *theFirstLineRep;
cf331c99
AR
395}
396
397libecap::Header &
574b508c 398Adaptation::Ecap::MessageRep::header()
cf331c99
AR
399{
400 return *theHeaderRep;
401}
402
403const libecap::Header &
574b508c 404Adaptation::Ecap::MessageRep::header() const
cf331c99
AR
405{
406 return *theHeaderRep;
407}
408
409libecap::Body *
574b508c 410Adaptation::Ecap::MessageRep::body()
cf331c99
AR
411{
412 return theBodyRep;
413}
414
415void
574b508c 416Adaptation::Ecap::MessageRep::addBody()
cf331c99 417{
cf331c99 418 Must(!theBodyRep);
77773405
AR
419 Must(!theMessage.body_pipe); // set in tieBody()
420 theBodyRep = new BodyRep(NULL);
421}
422
423void
574b508c 424Adaptation::Ecap::MessageRep::tieBody(Adaptation::Ecap::XactionRep *x)
77773405
AR
425{
426 Must(theBodyRep != NULL); // addBody must be called first
ce367911 427 Must(!theMessage.header->body_pipe);
cf331c99 428 Must(!theMessage.body_pipe);
ce367911
AR
429 theMessage.header->body_pipe = new BodyPipe(x);
430 theMessage.body_pipe = theMessage.header->body_pipe;
77773405 431 theBodyRep->tie(theMessage.body_pipe);
cf331c99
AR
432}
433
574b508c 434const libecap::Body *Adaptation::Ecap::MessageRep::body() const
cf331c99
AR
435{
436 return theBodyRep;
437}