6
#include "HttpRequest.h"
9
#include "TextException.h"
10
#include <libecap/common/names.h>
11
#include <libecap/common/area.h>
12
#include <libecap/common/version.h>
13
#include "adaptation/ecap/MessageRep.h"
14
#include "adaptation/ecap/XactionRep.h"
15
#include "adaptation/ecap/Host.h" /* for protocol constants */
19
Adaptation::Ecap::HeaderRep::HeaderRep(HttpMsg &aMessage): theHeader(aMessage.header),
25
Adaptation::Ecap::HeaderRep::hasAny(const Name &name) const
27
const http_hdr_type squidId = TranslateHeaderId(name);
28
// XXX: optimize to remove getByName: we do not need the value here
29
return squidId == HDR_OTHER ?
30
theHeader.getByName(name.image().c_str()).size() > 0:
31
(bool)theHeader.has(squidId);
34
Adaptation::Ecap::HeaderRep::Value
35
Adaptation::Ecap::HeaderRep::value(const Name &name) const
37
const http_hdr_type squidId = TranslateHeaderId(name);
38
const String value = squidId == HDR_OTHER ?
39
theHeader.getByName(name.image().c_str()) :
40
theHeader.getStrOrList(squidId);
41
return Value::FromTempString(value.termedBuf());
45
Adaptation::Ecap::HeaderRep::add(const Name &name, const Value &value)
47
const http_hdr_type squidId = TranslateHeaderId(name); // HDR_OTHER OK
48
HttpHeaderEntry *e = new HttpHeaderEntry(squidId, name.image().c_str(),
49
value.toString().c_str());
50
theHeader.addEntry(e);
54
Adaptation::Ecap::HeaderRep::removeAny(const Name &name)
56
const http_hdr_type squidId = TranslateHeaderId(name);
57
if (squidId == HDR_OTHER)
58
theHeader.delByName(name.image().c_str());
60
theHeader.delById(squidId);
64
Adaptation::Ecap::HeaderRep::image() const
70
packerToMemInit(&p, &mb);
71
theMessage.packInto(&p, true);
73
return Area::FromTempBuffer(mb.content(), mb.contentSize());
78
Adaptation::Ecap::HeaderRep::parse(const Area &buf)
82
mb.append(buf.start, buf.size);
84
Must(theMessage.parse(&mb, true, &error));
88
Adaptation::Ecap::HeaderRep::TranslateHeaderId(const Name &name)
90
if (name.assignedHostId())
91
return static_cast<http_hdr_type>(name.hostId());
98
Adaptation::Ecap::FirstLineRep::FirstLineRep(HttpMsg &aMessage): theMessage(aMessage)
103
Adaptation::Ecap::FirstLineRep::version() const
105
return libecap::Version(theMessage.http_ver.major,
106
theMessage.http_ver.minor);
110
Adaptation::Ecap::FirstLineRep::version(const libecap::Version &aVersion)
112
theMessage.http_ver.major = aVersion.majr;
113
theMessage.http_ver.minor = aVersion.minr;
117
Adaptation::Ecap::FirstLineRep::protocol() const
120
switch (theMessage.protocol) {
122
return libecap::protocolHttp;
124
return libecap::protocolHttps;
126
return libecap::protocolFtp;
128
return libecap::protocolGopher;
130
return libecap::protocolWais;
132
return libecap::protocolWhois;
134
return libecap::protocolUrn;
142
return protocolCacheObj;
144
return protocolInternal;
149
break; // should not happen
150
// no default to catch PROTO_ additions
152
Must(false); // not reached
157
Adaptation::Ecap::FirstLineRep::protocol(const Name &p)
159
// TODO: what happens if we fail to translate some protocol?
160
theMessage.protocol = TranslateProtocolId(p);
164
Adaptation::Ecap::FirstLineRep::TranslateProtocolId(const Name &name)
166
if (name.assignedHostId())
167
return static_cast<protocol_t>(name.hostId());
168
return PROTO_NONE; // no PROTO_OTHER
172
/* RequestHeaderRep */
174
Adaptation::Ecap::RequestLineRep::RequestLineRep(HttpRequest &aMessage):
175
FirstLineRep(aMessage), theMessage(aMessage)
180
Adaptation::Ecap::RequestLineRep::uri(const Area &aUri)
182
// TODO: if method is not set, urlPath will assume it is not connect;
183
// Can we change urlParse API to remove the method parameter?
184
// TODO: optimize: urlPath should take constant URL buffer
185
char *buf = xstrdup(aUri.toString().c_str());
186
const bool ok = urlParse(theMessage.method, buf, &theMessage);
191
Adaptation::Ecap::RequestLineRep::Area
192
Adaptation::Ecap::RequestLineRep::uri() const
194
return Area::FromTempBuffer(theMessage.urlpath.rawBuf(),
195
theMessage.urlpath.size());
199
Adaptation::Ecap::RequestLineRep::method(const Name &aMethod)
201
if (aMethod.assignedHostId()) {
202
const int id = aMethod.hostId();
203
Must(METHOD_NONE < id && id < METHOD_ENUM_END);
204
Must(id != METHOD_OTHER);
205
theMessage.method = HttpRequestMethod(static_cast<_method_t>(id));
207
const std::string &image = aMethod.image();
208
theMessage.method = HttpRequestMethod(image.data(),
209
image.data() + image.size());
213
Adaptation::Ecap::RequestLineRep::Name
214
Adaptation::Ecap::RequestLineRep::method() const
216
switch (theMessage.method.id()) {
218
return libecap::methodGet;
220
return libecap::methodPost;
222
return libecap::methodPut;
224
return libecap::methodHead;
226
return libecap::methodConnect;
228
return libecap::methodDelete;
230
return libecap::methodTrace;
232
return Name(theMessage.method.image());
237
Adaptation::Ecap::RequestLineRep::version() const
239
return FirstLineRep::version();
243
Adaptation::Ecap::RequestLineRep::version(const libecap::Version &aVersion)
245
FirstLineRep::version(aVersion);
249
Adaptation::Ecap::RequestLineRep::protocol() const
251
return FirstLineRep::protocol();
255
Adaptation::Ecap::RequestLineRep::protocol(const Name &p)
257
FirstLineRep::protocol(p);
263
Adaptation::Ecap::StatusLineRep::StatusLineRep(HttpReply &aMessage):
264
FirstLineRep(aMessage), theMessage(aMessage)
269
Adaptation::Ecap::StatusLineRep::statusCode(int code)
271
// TODO: why is .status a enum? Do we not support unknown statuses?
272
theMessage.sline.status = static_cast<http_status>(code);
276
Adaptation::Ecap::StatusLineRep::statusCode() const
278
// TODO: see statusCode(code) TODO above
279
return static_cast<int>(theMessage.sline.status);
283
Adaptation::Ecap::StatusLineRep::reasonPhrase(const Area &)
285
// Squid does not support custom reason phrases
286
theMessage.sline.reason = NULL;
289
Adaptation::Ecap::StatusLineRep::Area
290
Adaptation::Ecap::StatusLineRep::reasonPhrase() const
292
return theMessage.sline.reason ?
293
Area::FromTempString(std::string(theMessage.sline.reason)) : Area();
297
Adaptation::Ecap::StatusLineRep::version() const
299
return FirstLineRep::version();
303
Adaptation::Ecap::StatusLineRep::version(const libecap::Version &aVersion)
305
FirstLineRep::version(aVersion);
309
Adaptation::Ecap::StatusLineRep::protocol() const
311
return FirstLineRep::protocol();
315
Adaptation::Ecap::StatusLineRep::protocol(const Name &p)
317
FirstLineRep::protocol(p);
322
Adaptation::Ecap::BodyRep::BodyRep(const BodyPipe::Pointer &aBody): theBody(aBody)
327
Adaptation::Ecap::BodyRep::tie(const BodyPipe::Pointer &aBody)
334
Adaptation::Ecap::BodyRep::BodySize
335
Adaptation::Ecap::BodyRep::bodySize() const
337
return !theBody ? BodySize() : BodySize(theBody->bodySize());
343
Adaptation::Ecap::MessageRep::MessageRep(HttpMsg *rawHeader):
344
theMessage(rawHeader), theFirstLineRep(NULL),
345
theHeaderRep(NULL), theBodyRep(NULL)
347
Must(theMessage.header); // we do not want to represent a missing message
349
if (HttpRequest *req = dynamic_cast<HttpRequest*>(theMessage.header))
350
theFirstLineRep = new RequestLineRep(*req);
352
if (HttpReply *rep = dynamic_cast<HttpReply*>(theMessage.header))
353
theFirstLineRep = new StatusLineRep(*rep);
355
Must(false); // unknown message header type
357
theHeaderRep = new HeaderRep(*theMessage.header);
359
if (theMessage.body_pipe != NULL)
360
theBodyRep = new BodyRep(theMessage.body_pipe);
363
Adaptation::Ecap::MessageRep::~MessageRep()
367
delete theFirstLineRep;
370
libecap::shared_ptr<libecap::Message>
371
Adaptation::Ecap::MessageRep::clone() const
373
HttpMsg *hdr = theMessage.header->clone();
374
hdr->body_pipe = NULL; // if any; TODO: remove pipe cloning from ::clone?
375
libecap::shared_ptr<libecap::Message> res(new MessageRep(hdr));
377
// restore indication of a body if needed, but not the pipe
378
if (theMessage.header->body_pipe != NULL)
385
Adaptation::Ecap::MessageRep::firstLine()
387
return *theFirstLineRep;
390
const libecap::FirstLine &
391
Adaptation::Ecap::MessageRep::firstLine() const
393
return *theFirstLineRep;
397
Adaptation::Ecap::MessageRep::header()
399
return *theHeaderRep;
402
const libecap::Header &
403
Adaptation::Ecap::MessageRep::header() const
405
return *theHeaderRep;
409
Adaptation::Ecap::MessageRep::body()
415
Adaptation::Ecap::MessageRep::addBody()
418
Must(!theMessage.body_pipe); // set in tieBody()
419
theBodyRep = new BodyRep(NULL);
423
Adaptation::Ecap::MessageRep::tieBody(Adaptation::Ecap::XactionRep *x)
425
Must(theBodyRep != NULL); // addBody must be called first
426
Must(!theMessage.header->body_pipe);
427
Must(!theMessage.body_pipe);
428
theMessage.header->body_pipe = new BodyPipe(x);
429
theMessage.body_pipe = theMessage.header->body_pipe;
430
theBodyRep->tie(theMessage.body_pipe);
433
const libecap::Body *Adaptation::Ecap::MessageRep::body() const