Add acl support to range_offset_limit.
It is being parsed using the same data types as reply_body_max_size,
which means the limit value gets run through parseBytesLine64, and the
acl is optional.
If people are using the old global style of range_offset_limit, they
shouldn't have to do anything to their configs.
getRangeOffsetLimit is now a member of HttpRequest, and it caches it's
value the same way reply_body_max_size does for faster repeat checking.
}
/*
- * Return true if the first range offset is larger than the configured
- * limit.
- * Note that exceeding the limit (returning true) results in only
- * grabbing the needed range elements from the origin.
+ * \retval true Fetch only requested ranges. The first range is larger that configured limit.
+ * \retval false Full download. Not a range request, no limit, or the limit is not yet reached.
*/
bool
-HttpHdrRange::offsetLimitExceeded() const
+HttpHdrRange::offsetLimitExceeded(const int64_t limit) const
{
if (NULL == this)
/* not a range request */
return false;
- if (Config.rangeOffsetLimit == 0)
- /* disabled */
+ if (limit == 0)
+ /* 0 == disabled */
return true;
- if (-1 == Config.rangeOffsetLimit)
- /* forced */
+ if (-1 == limit)
+ /* 'none' == forced */
return false;
if (firstOffset() == -1)
/* tail request */
return true;
- if (Config.rangeOffsetLimit >= firstOffset())
+ if (limit >= firstOffset())
/* below the limit */
return false;
bool willBeComplex() const;
int64_t firstOffset() const;
int64_t lowestOffset(int64_t) const;
- bool offsetLimitExceeded() const;
+ bool offsetLimitExceeded(const int64_t limit) const;
bool contains(HttpHdrRangeSpec& r) const;
Vector<HttpHdrRangeSpec *> specs;
#if ICAP_CLIENT
#include "adaptation/icap/icap_log.h"
#endif
+#include "acl/FilledChecklist.h"
HttpRequest::HttpRequest() : HttpMsg(hoRequest)
{
#if ICAP_CLIENT
icapHistory_ = NULL;
#endif
+ rangeOffsetLimit = -2; //a value of -2 means not checked yet
}
void
dnsWait = dns.wait;
}
}
+
+int64_t
+HttpRequest::getRangeOffsetLimit()
+{
+ /* -2 is the starting value of rangeOffsetLimit.
+ * If it is -2, that means we haven't checked it yet.
+ * Otherwise, return the current value */
+ if(rangeOffsetLimit != -2)
+ return rangeOffsetLimit;
+
+ rangeOffsetLimit = 0; // default value for rangeOffsetLimit
+
+ ACLFilledChecklist ch(NULL, this, NULL);
+ ch.src_addr = client_addr;
+ ch.my_addr = my_addr;
+
+ for (acl_size_t *l = Config.rangeOffsetLimit; l; l = l -> next) {
+ /* if there is no ACL list or if the ACLs listed match use this limit value */
+ if (!l->aclList || ch.matchAclListFast(l->aclList)) {
+ debugs(58, 4, HERE << "rangeOffsetLimit=" << rangeOffsetLimit);
+ rangeOffsetLimit = l->size; // may be -1
+ break;
+ }
+ }
+
+ return rangeOffsetLimit;
+}
cbdataReferenceDone(pinned_connection);
}
+ int64_t getRangeOffsetLimit(); /* the result of this function gets cached in rangeOffsetLimit */
+
private:
const char *packableURI(bool full_uri) const;
+ mutable int64_t rangeOffsetLimit; /* caches the result of getRangeOffsetLimit */
+
protected:
virtual void packFirstLineInto(Packer * p, bool full_uri) const;
usage: neighbor_type_domain neighbor parent|sibling domain domain ...
Modifying the neighbor type for specific domains is now
- possible. You can treat some domains differently than the the
+ possible. You can treat some domains differently than the
default neighbor type specified on the 'cache_peer' line.
Normally it should only be necessary to list domains which
should be treated differently because the default neighbor type
DOC_END
NAME: range_offset_limit
-COMMENT: (bytes)
-TYPE: b_int64_t
+COMMENT: size [acl acl...]
+TYPE: acl_b_size_t
LOC: Config.rangeOffsetLimit
-DEFAULT: 0 KB
+DEFAULT: none
DOC_START
- Sets a upper limit on how far into the the file a Range request
- may be to cause Squid to prefetch the whole file. If beyond this
- limit Squid forwards the Range request as it is and the result
- is NOT cached.
-
+ usage: (size) [units] [[!]aclname]
+
+ Sets an upper limit on how far (number of bytes) into the file
+ a Range request may be to cause Squid to prefetch the whole file.
+ If beyond this limit, Squid forwards the Range request as it is and
+ the result is NOT cached.
+
This is to stop a far ahead range request (lets say start at 17MB)
from making Squid fetch the whole object up to that point before
sending anything to the client.
-
- A value of 0 causes Squid to never fetch more than the
+
+ Multiple range_offset_limit lines may be specified, and they will
+ be searched from top to bottom on each request until a match is found.
+ The first match found will be used. If no line matches a request, the
+ default limit of 0 bytes will be used.
+
+ 'size' is the limit specified as a number of units.
+
+ 'units' specifies whether to use bytes, KB, MB, etc.
+ If no units are specified bytes are assumed.
+
+ A size of 0 causes Squid to never fetch more than the
client requested. (default)
-
- A value of -1 causes Squid to always fetch the object from the
+
+ A size of 'none' causes Squid to always fetch the object from the
beginning so it may cache the result. (2.0 style)
-
- NP: Using -1 here will override any quick_abort settings that may
- otherwise apply to the range request. The range request will
+
+ 'aclname' is the name of a defined ACL.
+
+ NP: Using 'none' as the byte value here will override any quick_abort settings
+ that may otherwise apply to the range request. The range request will
be fully fetched from start to finish regardless of the client
actions. This affects bandwidth usage.
DOC_END
assert(request->range);
/* check if we still want to do ranges */
+ int64_t roffLimit = request->getRangeOffsetLimit();
+
if (!rep)
range_err = "no [parse-able] reply";
else if ((rep->sline.status != HTTP_OK) && (rep->sline.status != HTTP_PARTIAL_CONTENT))
range_err = "canonization failed";
else if (http->request->range->isComplex())
range_err = "too complex range header";
- else if (!logTypeIsATcpHit(http->logType) && http->request->range->offsetLimitExceeded())
+ else if (!logTypeIsATcpHit(http->logType) && http->request->range->offsetLimitExceeded(roffLimit))
range_err = "range outside range_offset_limit";
/* get rid of our range specs on error */
* the server and fetch only the requested content)
*/
+ int64_t roffLimit = orig_request->getRangeOffsetLimit();
+
if (NULL == orig_request->range || !orig_request->flags.cachable
- || orig_request->range->offsetLimitExceeded() || orig_request->flags.connection_auth)
+ || orig_request->range->offsetLimitExceeded(roffLimit) || orig_request->flags.connection_auth)
result = false;
debugs(11, 8, "decideIfWeDoRanges: range specs: " <<
return 0;
}
- if ( Config.rangeOffsetLimit < 0 && mem->request && mem->request->range ) {
+ int64_t roffLimit = mem->request->getRangeOffsetLimit();
+
+ if ( roffLimit < 0 && mem->request && mem->request->range ) {
/* Don't abort if the admin has configured range_ofset -1 to download fully for caching. */
debugs(90, 3, "CheckQuickAbort2: NO admin configured range replies to full-download");
return 0;
} comm_incoming;
int max_open_disk_fds;
int uri_whitespace;
- int64_t rangeOffsetLimit;
+ acl_size_t *rangeOffsetLimit;
#if MULTICAST_MISS_STREAM
struct {