<div dir="ltr">Thank you very much, that really helped!</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Jan 18, 2021 at 6:48 PM Alex Rousskov <<a href="mailto:rousskov@measurement-factory.com">rousskov@measurement-factory.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On 1/18/21 6:45 AM, Moti Berger wrote:<br>
<br>
> If the ICAP server sets 'Preview: 0' in the OPTIONS it means that when<br>
> the ICAP client sends a request, it should not contain the body.<br>
<br>
The above summary may mislead many readers. I would describe the<br>
protocol operation differently:<br>
<br>
* Preview in an OPTIONS response indicates that the server supports<br>
Preview in general and specifies the maximum Preview size the client<br>
should use (e.g., Preview:0 limits Preview to HTTP headers).<br>
<br>
* The Preview mode for a specific REQMOD or RESPMOD transaction is<br>
signaled in the corresponding REQMOD or RESPMOD request (not a previous<br>
OPTIONS response) by adding a Preview:N ICAP request header (Preview:0<br>
specifies a headers-only Preview for the current transaction).<br>
<br>
* The REQMOD or RESPMOD transaction with a Preview:0 request header is<br>
split into two phases. During the first phase, the client must not send<br>
the virgin body. During the second phase, if any, the client must send<br>
the virgin body. Both phases comprise a single ICAP transaction, with a<br>
single ICAP request and a single ICAP response. Thus, one cannot say<br>
that this transaction (as a whole) "should not contain a body".<br>
<br>
<br>
> This is the REQMOD request:<br>
> <br>
> F..n...DREQMOD icap://censor-req.proxy:14590/request ICAP/1.0<br>
> Host: censor-req.proxy:14590<br>
> Date: Mon, 18 Jan 2021 11:34:54 GMT<br>
> Encapsulated: req-hdr=0, req-body=222<br>
> Preview: 0<br>
> Allow: 204, trailers<br>
> X-custom-header: data<br>
> <br>
> POST <a href="http://www.dst-server.com:22222/v1/test" rel="noreferrer" target="_blank">http://www.dst-server.com:22222/v1/test</a> HTTP/1.1<br>
> User-Agent: python-requests/2.25.1<br>
> Accept-Encoding: gzip, deflate<br>
> Accept: */*<br>
> Content-Length: 10<br>
> Content-Type: application/json<br>
> Host: <a href="http://www.dst-server.com:22222" rel="noreferrer" target="_blank">www.dst-server.com:22222</a> <<a href="http://www.dst-server.com:22222" rel="noreferrer" target="_blank">http://www.dst-server.com:22222</a>><br>
<br>
> The ICAP 'Encapsulated' header has a req-body even though no 'body'<br>
> should be in this request.<br>
<br>
Not exactly. The request may not be over at this point. Please see my<br>
third bullet above for details.<br>
<br>
<br>
> The ICAP server has no way to encapsulate the HTTP request body if it<br>
> didn't get it.<br>
<br>
To get the request body in Preview:0 mode, the ICAP server must respond<br>
with ICAP 100 (Continue).<br>
<br>
<br>
> I want to avoid sending the body because the adaptation is body agnostic.<br>
<br>
Yes, I know, but you have to work within the ICAP protocol boundaries.<br>
ICAP simply does not optimize your use case! After you have the basics<br>
working well, you can invest in implementing a use-original-body ICAP<br>
extension[1] that, in _some_ cases, can prevent the body exchange while<br>
adapting HTTP headers.<br>
<br>
Alternatively, you can use an existing (extendible) ICAP server to do<br>
the legwork for you [2]. Many individuals and companies have learned the<br>
hard way that implementing an ICAP service correctly from scratch is<br>
very difficult and often prohibitively expensive.<br>
<br>
[1]<br>
<a href="http://www.icap-forum.org/documents/specification/draft-icap-ext-partial-content-07.txt" rel="noreferrer" target="_blank">http://www.icap-forum.org/documents/specification/draft-icap-ext-partial-content-07.txt</a><br>
<br>
[2] <a href="https://wiki.squid-cache.org/Features/ICAP#ICAP_Servers" rel="noreferrer" target="_blank">https://wiki.squid-cache.org/Features/ICAP#ICAP_Servers</a><br>
<br>
<br>
HTH,<br>
<br>
Alex.<br>
<br>
<br>
<br>
> On Sun, Jan 17, 2021 at 11:34 PM Alex Rousskov wrote:<br>
> <br>
> On 1/17/21 3:08 PM, Moti Berger wrote:<br>
> > What should the ICAP response look like?<br>
> <br>
> The vast majority off ICAP responses containing an HTTP POST message<br>
> will look like ICAP header + HTTP header + HTTP body. Please see RFC<br>
> 3507 and its errata for examples of and discussion about those three<br>
> components. It should help avoid guessing and developing by examples<br>
> (which usually leads to bugs, especially where ICAP is involved).<br>
> <br>
> <br>
> > What I do is to reply like this:<br>
> ><br>
> > (dI./M..ICAP/1.0 200 OK<br>
> > ISTag: "SjIzlRA4te41axxcDOoiSl6rBRg4ZK"<br>
> > Date: Sun, 17 Jan 2021 19:34:12 GMT<br>
> > Server: BaseICAP/1.0 Python/3.6.12<br>
> > Encapsulated: req-hdr=0, req-body=360<br>
> ><br>
> > POST <a href="http://www.dst-server.com:22222/v1/test" rel="noreferrer" target="_blank">http://www.dst-server.com:22222/v1/test</a> HTTP/1.1<br>
> > x-new-header: {"key": "value"}<br>
> > user-agent: python-requests/2.25.1<br>
> > accept-encoding: gzip, deflate<br>
> > accept: */*<br>
> > content-length: 16<br>
> > content-type: application/json<br>
> > host: <a href="http://www.dst-server.com:22222" rel="noreferrer" target="_blank">www.dst-server.com:22222</a><br>
> <<a href="http://www.dst-server.com:22222" rel="noreferrer" target="_blank">http://www.dst-server.com:22222</a>> <<a href="http://www.dst-server.com:22222" rel="noreferrer" target="_blank">http://www.dst-server.com:22222</a>><br>
> <br>
> <br>
> FYI: The above incomplete ICAP response promises an HTTP request body,<br>
> both on the ICAP level (req-body) and on the HTTP level (content-length:<br>
> 16).<br>
> <br>
> <br>
> > As I said, I use 'Preview: 0' since I don't mind the body. The<br>
> question<br>
> > is whether declaring the body starts at X (req-body=X) is OK even<br>
> though<br>
> > I don't have a body to send?<br>
> <br>
> It is not OK not to send the body. Encapsulated:req-body does more than<br>
> declaring where the encapsulated headers end. It also promises an<br>
> embedded HTTP body after those headers. You must encapsulate the body if<br>
> the HTTP message should have one. You cannot adapt the header of an HTTP<br>
> message with a body without also sending the HTTP body (virgin or<br>
> adapted).<br>
> <br>
> Preview is pretty much irrelevant in this context -- the ICAP protocol<br>
> does not care how the ICAP service gets the HTTP body to include in the<br>
> ICAP response.<br>
> <br>
> There are unofficial ICAP extensions that make it possible to tell the<br>
> ICAP client to reuse the body it has buffered while adapting the header,<br>
> but you should get the baseline case working before bothering with those<br>
> extensions -- they are optimizations that are not applicable to some<br>
> transactions.<br>
> <br>
> <br>
> > I think having req-null=X is bad since it<br>
> > probably tells squid that I decided the adapted request should have no<br>
> > body, but that's only a guess.<br>
> <br>
> If you meant to say "null-body", then you guessed correctly -- null-body<br>
> means the adapted HTTP message has no body. That is not what you want to<br>
> say when adapting most HTTP POST messages.<br>
> <br>
> <br>
> HTH,<br>
> <br>
> Alex.<br>
> <br>
<br>
</blockquote></div>