]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/ICAP/ICAPOptions.cc
4 #include "ICAPOptions.h"
5 #include "TextException.h"
6 #include "ICAPConfig.h"
9 extern ICAPConfig TheICAPConfig
;
11 ICAPOptions::ICAPOptions(): error("unconfigured"),
12 max_connections(-1), allow204(false),
13 preview(-1), theTTL(-1)
15 theTransfers
.preview
.name
= "Transfer-Preview";
16 theTransfers
.preview
.kind
= xferPreview
;
17 theTransfers
.ignore
.name
= "Transfer-Ignore";
18 theTransfers
.ignore
.kind
= xferIgnore
;
19 theTransfers
.complete
.name
= "Transfer-Complete";
20 theTransfers
.complete
.kind
= xferComplete
;
22 // Section 4.10.2 of RFC 3507 says that default is no Preview
23 // TODO: provide a squid.conf option to overwrite the default
24 theTransfers
.byDefault
= &theTransfers
.complete
;
27 ICAPOptions::~ICAPOptions()
31 // future optimization note: this method is called by ICAP ACL code at least
32 // twice for each HTTP message to see if the message should be ignored. For any
33 // non-ignored HTTP message, ICAP calls to check whether a preview is needed.
34 ICAPOptions::TransferKind
ICAPOptions::transferKind(const String
&urlPath
) const
36 if (theTransfers
.preview
.matches(urlPath
))
39 if (theTransfers
.complete
.matches(urlPath
))
42 if (theTransfers
.ignore
.matches(urlPath
))
45 debugs(93,7, "ICAPOptions url " << urlPath
<< " matches no extensions; " <<
46 "using default: " << theTransfers
.byDefault
->name
);
47 return theTransfers
.byDefault
->kind
;
50 bool ICAPOptions::valid() const
55 bool ICAPOptions::fresh() const
57 return squid_curtime
<= expire();
60 int ICAPOptions::ttl() const
63 return theTTL
>= 0 ? theTTL
: TheICAPConfig
.default_options_ttl
;
66 time_t ICAPOptions::expire() const
69 return theTimestamp
+ ttl();
72 void ICAPOptions::configure(const HttpReply
*reply
)
74 error
= NULL
; // reset initial "unconfigured" value (or an old error?)
76 const HttpHeader
*h
= &reply
->header
;
78 if (reply
->sline
.status
!= 200)
79 error
= "unsupported status code of OPTIONS response";
82 if (h
->hasByNameListMember("Methods", "REQMOD", ','))
83 cfgMethod(ICAP::methodReqmod
);
85 if (h
->hasByNameListMember("Methods", "RESPMOD", ','))
86 cfgMethod(ICAP::methodRespmod
);
88 service
= h
->getByName("Service");
90 serviceId
= h
->getByName("ServiceId");
92 istag
= h
->getByName("ISTag");
94 if (h
->getByName("Opt-body-type").size())
95 error
= "ICAP service returns unsupported OPTIONS body";
97 cfgIntHeader(h
, "Max-Connections", max_connections
);
99 cfgIntHeader(h
, "Options-TTL", theTTL
);
101 theTimestamp
= h
->getTime(HDR_DATE
);
103 if (theTimestamp
< 0)
104 theTimestamp
= squid_curtime
;
106 if (h
->hasListMember(HDR_ALLOW
, "204", ','))
109 cfgIntHeader(h
, "Preview", preview
);
111 cfgTransferList(h
, theTransfers
.preview
);
112 cfgTransferList(h
, theTransfers
.ignore
);
113 cfgTransferList(h
, theTransfers
.complete
);
116 void ICAPOptions::cfgMethod(ICAP::Method m
)
118 Must(m
!= ICAP::methodNone
);
122 // TODO: HttpHeader should provide a general method for this type of conversion
123 void ICAPOptions::cfgIntHeader(const HttpHeader
*h
, const char *fname
, int &value
)
125 const String s
= h
->getByName(fname
);
127 if (s
.size() && xisdigit(*s
.termedBuf()))
128 value
= atoi(s
.termedBuf());
132 debugs(93,5, "ICAPOptions::cfgIntHeader " << fname
<< ": " << value
);
135 void ICAPOptions::cfgTransferList(const HttpHeader
*h
, TransferList
&list
)
137 const String buf
= h
->getByName(list
.name
);
138 bool foundStar
= false;
139 list
.parse(buf
, foundStar
);
142 theTransfers
.byDefault
= &list
;
143 debugs(93,5, "ICAPOptions::cfgTransferList: " <<
144 "set default transfer to " << list
.name
);
147 list
.report(5, "ICAPOptions::cfgTransferList: ");
151 /* ICAPOptions::TransferList */
153 ICAPOptions::TransferList::TransferList(): extensions(NULL
), name(NULL
),
158 ICAPOptions::TransferList::~TransferList()
160 wordlistDestroy(&extensions
);
163 void ICAPOptions::TransferList::add(const char *extension
)
165 wordlistAdd(&extensions
, extension
);
168 bool ICAPOptions::TransferList::matches(const String
&urlPath
) const
170 const int urlLen
= urlPath
.size();
171 for (wordlist
*e
= extensions
; e
; e
= e
->next
) {
172 // optimize: store extension lengths
173 const int eLen
= strlen(e
->key
);
175 // assume URL contains at least '/' before the extension
177 const int eOff
= urlLen
- eLen
;
178 // RFC 3507 examples imply that extensions come without leading '.'
179 if (urlPath
[eOff
-1] == '.' &&
180 strcmp(urlPath
.termedBuf() + eOff
, e
->key
) == 0) {
181 debugs(93,7, "ICAPOptions url " << urlPath
<< " matches " <<
182 name
<< " extension " << e
->key
);
187 debugs(93,8, "ICAPOptions url " << urlPath
<< " matches no " << name
<< " extensions");
191 void ICAPOptions::TransferList::parse(const String
&buf
, bool &foundStar
)
196 const char *pos
= NULL
;
198 while (strListGetItem(&buf
, ',', &item
, &ilen
, &pos
)) {
199 if (ilen
== 1 && *item
== '*')
202 add(xstrndup(item
, ilen
+1));
206 void ICAPOptions::TransferList::report(int level
, const char *prefix
) const
209 for (wordlist
*e
= extensions
; e
; e
= e
->next
)
210 debugs(93,level
, prefix
<< name
<< ": " << e
->key
);
212 debugs(93,level
, prefix
<< "no " << name
<< " extensions");