]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/adaptation/icap/Options.cc
e08120adce6b643bad20e0f278d52605f100a7d5
2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
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.
10 #include "adaptation/icap/Config.h"
11 #include "adaptation/icap/Options.h"
12 #include "base/TextException.h"
13 #include "HttpReply.h"
14 #include "SquidTime.h"
18 Adaptation::Icap::Options::Options() :
19 error("unconfigured"),
27 theTransfers
.preview
.name
= "Transfer-Preview";
28 theTransfers
.preview
.kind
= xferPreview
;
29 theTransfers
.ignore
.name
= "Transfer-Ignore";
30 theTransfers
.ignore
.kind
= xferIgnore
;
31 theTransfers
.complete
.name
= "Transfer-Complete";
32 theTransfers
.complete
.kind
= xferComplete
;
34 // Section 4.10.2 of RFC 3507 says that default is no Preview
35 // TODO: provide a squid.conf option to overwrite the default
36 theTransfers
.byDefault
= &theTransfers
.complete
;
39 Adaptation::Icap::Options::~Options()
43 // future optimization note: this method is called by ICAP ACL code at least
44 // twice for each HTTP message to see if the message should be ignored. For any
45 // non-ignored HTTP message, ICAP calls to check whether a preview is needed.
46 Adaptation::Icap::Options::TransferKind
47 Adaptation::Icap::Options::transferKind(const SBuf
&urlPath
) const
49 if (theTransfers
.preview
.matches(urlPath
))
52 if (theTransfers
.complete
.matches(urlPath
))
55 if (theTransfers
.ignore
.matches(urlPath
))
58 debugs(93,7, "url " << urlPath
<< " matches no extensions; " <<
59 "using default: " << theTransfers
.byDefault
->name
);
60 return theTransfers
.byDefault
->kind
;
63 bool Adaptation::Icap::Options::valid() const
68 bool Adaptation::Icap::Options::fresh() const
70 return squid_curtime
<= expire();
73 int Adaptation::Icap::Options::ttl() const
76 return theTTL
>= 0 ? theTTL
: TheConfig
.default_options_ttl
;
79 time_t Adaptation::Icap::Options::expire() const
82 return theTimestamp
+ ttl();
85 void Adaptation::Icap::Options::configure(const HttpReply
*reply
)
87 error
= NULL
; // reset initial "unconfigured" value (or an old error?)
89 const HttpHeader
*h
= &reply
->header
;
91 if (reply
->sline
.status() != Http::scOkay
)
92 error
= "unsupported status code of OPTIONS response";
95 if (h
->hasByNameListMember("Methods", "REQMOD", ','))
96 cfgMethod(ICAP::methodReqmod
);
98 if (h
->hasByNameListMember("Methods", "RESPMOD", ','))
99 cfgMethod(ICAP::methodRespmod
);
101 service
= h
->getByName("Service");
103 serviceId
= h
->getByName("ServiceId");
105 istag
= h
->getByName("ISTag");
107 if (h
->getByName("Opt-body-type").size()) {
108 // TODO: add a class to rate-limit such warnings using FadingCounter
109 debugs(93,DBG_IMPORTANT
, "WARNING: Ignoring unsupported ICAP " <<
110 "OPTIONS body; type: " << h
->getByName("Opt-body-type"));
111 // Do not set error, assuming the response headers are valid.
114 cfgIntHeader(h
, "Max-Connections", max_connections
);
115 if (max_connections
== 0)
116 debugs(93, DBG_IMPORTANT
, "WARNING: Max-Connections is set to zero! ");
118 cfgIntHeader(h
, "Options-TTL", theTTL
);
120 theTimestamp
= h
->getTime(Http::HdrType::DATE
);
122 if (theTimestamp
< 0)
123 theTimestamp
= squid_curtime
;
125 if (h
->hasListMember(Http::HdrType::ALLOW
, "204", ','))
128 if (h
->hasListMember(Http::HdrType::ALLOW
, "206", ','))
131 cfgIntHeader(h
, "Preview", preview
);
133 cfgTransferList(h
, theTransfers
.preview
);
134 cfgTransferList(h
, theTransfers
.ignore
);
135 cfgTransferList(h
, theTransfers
.complete
);
138 void Adaptation::Icap::Options::cfgMethod(ICAP::Method m
)
140 Must(m
!= ICAP::methodNone
);
141 methods
.push_back(m
);
144 // TODO: HttpHeader should provide a general method for this type of conversion
145 void Adaptation::Icap::Options::cfgIntHeader(const HttpHeader
*h
, const char *fname
, int &value
)
147 const String s
= h
->getByName(fname
);
149 if (s
.size() && xisdigit(*s
.termedBuf()))
150 value
= atoi(s
.termedBuf());
154 debugs(93,5, HERE
<< "int header: " << fname
<< ": " << value
);
157 void Adaptation::Icap::Options::cfgTransferList(const HttpHeader
*h
, TransferList
&list
)
159 const String buf
= h
->getByName(list
.name
);
160 bool foundStar
= false;
161 list
.parse(buf
, foundStar
);
164 theTransfers
.byDefault
= &list
;
165 debugs(93,5, HERE
<< "set default transfer to " << list
.name
);
168 list
.report(5, "Adaptation::Icap::Options::cfgTransferList: ");
171 /* Adaptation::Icap::Options::TransferList */
173 Adaptation::Icap::Options::TransferList::TransferList(): extensions(NULL
), name(NULL
),
178 Adaptation::Icap::Options::TransferList::~TransferList()
180 wordlistDestroy(&extensions
);
183 void Adaptation::Icap::Options::TransferList::add(const char *extension
)
185 wordlistAdd(&extensions
, extension
);
188 bool Adaptation::Icap::Options::TransferList::matches(const SBuf
&urlPath
) const
190 const SBuf::size_type urlLen
= urlPath
.length();
191 for (wordlist
*e
= extensions
; e
; e
= e
->next
) {
192 // optimize: store extension lengths
193 const size_t eLen
= strlen(e
->key
);
195 // assume URL contains at least '/' before the extension
197 const size_t eOff
= urlLen
- eLen
;
198 // RFC 3507 examples imply that extensions come without leading '.'
199 if (urlPath
[eOff
-1] == '.' && urlPath
.substr(eOff
).cmp(e
->key
, eLen
) == 0) {
200 debugs(93,7, "url " << urlPath
<< " matches " << name
<< " extension " << e
->key
);
205 debugs(93,8, "url " << urlPath
<< " matches no " << name
<< " extensions");
209 void Adaptation::Icap::Options::TransferList::parse(const String
&buf
, bool &foundStar
)
214 const char *pos
= NULL
;
216 while (strListGetItem(&buf
, ',', &item
, &ilen
, &pos
)) {
217 if (ilen
== 1 && *item
== '*')
220 const char *tmp
= xstrndup(item
, ilen
+1);
227 void Adaptation::Icap::Options::TransferList::report(int level
, const char *prefix
) const
230 for (wordlist
*e
= extensions
; e
; e
= e
->next
)
231 debugs(93,level
, prefix
<< name
<< ": " << e
->key
);
233 debugs(93,level
, prefix
<< "no " << name
<< " extensions");