<div dir="ltr">Maybe something like "new (top)blah = ..." and "blah.foo()" would allow us to target different scopes but keep the variable names and VCL syntax more clean. Just thinking out loud.</div><div class="gmail_extra"><br clear="all"><div><div class="gmail_signature"><div dir="ltr">--<br>Reza Naghibi<br>Varnish Software</div></div></div>
<br><div class="gmail_quote">On Thu, Apr 7, 2016 at 10:04 AM, Reza Naghibi <span dir="ltr"><<a href="mailto:reza@varnish-software.com" target="_blank">reza@varnish-software.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">I was thinking about this a bit more last night. I agree that "req.var.blah.foo()" is pretty verbose. We could drop it all and just do "new blah = ..." with "blah.foo()" and let vcc and the user reason about the scope. Maybe a shorthand prefix is best. One issue is if you want to target the top request lifetime (ESI), then without a prefix, there is no way to do that. There is no way to tell is "new blah = ..." should be request or top request scope. With a prefix, vcc would know which scope you want it to be. Im thinking having top request scopes would be useful, but if not, then we could favor dropping the prefix altogether.</div><div class="gmail_extra"><span class=""><br clear="all"><div><div><div dir="ltr">--<br>Reza Naghibi<br>Varnish Software</div></div></div>
<br></span><div><div class="h5"><div class="gmail_quote">On Thu, Apr 7, 2016 at 7:45 AM, Federico Schwindt <span dir="ltr"><<a href="mailto:fgsch@lodoss.net" target="_blank">fgsch@lodoss.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>I definitely like this and I can see a lot of places where it will become handy.</div><div><br></div><div>What I'm not particularly keen is the xxx.var namespace. While I understand the reasoning behind and I'd like to see some kind of variable support in Varnish I'm not sure reusing the *req/*resp space is the way forward. </div><div>If you really want to tie the variables to a particular namespace you could name them as `req_var_xxx`, `bereq_var_xxx`, etc. so this feels a bit superfluous.</div><div><br></div><div>Speaking of variable support, if we were to have these new scopes isn't this exactly giving us that, perhaps with some extra cost? </div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div>On Wed, Apr 6, 2016 at 10:09 PM, Reza Naghibi <span dir="ltr"><<a href="mailto:reza@varnish-software.com" target="_blank">reza@varnish-software.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div><div dir="ltr">Below are some thoughts and a prototype patch for expanding object support. Today, objects are limited to global objects which have a lifetime of the entire VCL. I feel its useful to have objects which can be created during the request and their scope is limited to that request. When the request is done, the objects are finalized.<div><br></div><div>The driver for this is creating a new curl/http vmod (I have several other vmods in mind which would benefit from this). When making curl requests from VCL, you may want to have multiple outstanding (async) requests, so we need to have the ability to encapsulate these requests in isolated, independent, and request scoped objects. Another use case is creating simple type objects, like VCL_STRING, VCL_INT, and VCL_BLOB. We can wrap these types into an object and we now have VCL variables which don't require conversion into headers and we can define them on the fly per request. This will likely open the door for some very interesting VCL functionality :)</div><div><br></div><div>Here is a VCL snippet which compiles and works with the patch and uses my new libvmod_types [0].</div><div><br></div><div>---</div><div><font face="monospace, monospace">import types;</font></div><div><font face="monospace, monospace"><br></font></div><div><div><font face="monospace, monospace">sub vcl_init</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace"> //global objects, these are unchanged from 4.0</font></div><div><font face="monospace, monospace"> new s = types.string("Hello!");</font></div><div><font face="monospace, monospace"> new reqs = types.integer(0);</font></div><div><font face="monospace, monospace">}</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">sub vcl_recv</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace"> //new req scoped objects</font></div><div><font face="monospace, monospace"> new req.var.slocal = types.string("Request scoped string");</font></div><div><font face="monospace, monospace"> new req.var.s2 = types.string("request string two");</font></div><div><font face="monospace, monospace"> new req.var.count = types.integer(1);</font></div><div><font face="monospace, monospace">}</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">sub vcl_backend_fetch</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace"> //new bereq scoped objects</font></div><div><font face="monospace, monospace"> new bereq.var.sbe = types.string("berequest string v1");</font></div><div><font face="monospace, monospace"> set bereq.http.sbe = bereq.var.sbe.value();</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> bereq.var.sbe.set("berequest string v2");</font></div><div><font face="monospace, monospace"> set bereq.http.sbe2 = bereq.var.sbe.value();</font></div><div><font face="monospace, monospace">}</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">sub vcl_deliver</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace"> //referencing a mix of global and req scoped objects</font></div><div><font face="monospace, monospace"> set resp.http.X-s = s.value();</font></div><div><font face="monospace, monospace"> set resp.http.X-s-length = s.length();</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> set resp.http.X-slocal = req.var.slocal.value();</font></div><div><font face="monospace, monospace"> set resp.http.X-slocal-length = req.var.slocal.length();</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> req.var.count.increment(10);</font></div><div><font face="monospace, monospace"> set resp.http.count = req.var.count.value();</font></div><div><font face="monospace, monospace"> set resp.http.reqs = reqs.increment_get(1);</font></div><div><font face="monospace, monospace">}</font></div></div><div>---</div><div><br></div><div>The theoretical curl/http example:</div><div><br></div><div>---</div><div><font face="monospace, monospace">import http;</font></div><div><font face="monospace, monospace"><br></font></div><div><div><font face="monospace, monospace">sub vcl_recv</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace"> //http request #1</font></div><div><font face="monospace, monospace"> new req.var.h1 = http.request();</font></div><div><font face="monospace, monospace"> req.var.h1.set_header("foo", "bar");</font></div><div><font face="monospace, monospace"> req.var.h1.set_url("POST", "<a href="http://host1/blah?ok=true" target="_blank">http://host1/blah?ok=true</a>");</font></div><div><font face="monospace, monospace"> req.var.h1.send();</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> //http request #2 (we dont read it so its async)</font></div><div><font face="monospace, monospace"> new req.var.h2 = http.request();</font></div><div><font face="monospace, monospace"> req.var.h2.set_url("GET", "<a href="http://host2/ping" target="_blank">http://host2/ping</a>");</font></div><div><font face="monospace, monospace"> req.var.h2.send();</font></div><div><font face="monospace, monospace">}</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace">sub vcl_deliver</font></div><div><font face="monospace, monospace">{</font></div><div><font face="monospace, monospace"> //reference and read http request #1 and block for result</font></div><div><font face="monospace, monospace"> set resp.http.X-test-response-code = req.var.h1.get_response_code();</font></div><div><font face="monospace, monospace">}</font></div></div><div>---</div><div><br></div><div>I left the legacy global objects alone in code and syntax. I introduced 2 new variable name scopes: req.var.* and bereq.var.*. This is completely cosmetic as these variables can still be request scoped without the (be)req.var prefix. However, the reason for adding it is to give the user some kind of indication that their variable is tied to a frontend, backend, or global scope. Otherwise I have the feeling having a bunch of un-prefixed variables throwing vcc scope errors when used incorrectly will be confusing.</div><div><br></div><div>Also, the implementation is fairly simple because I piggybacked on the vmod/vrt priv_task implementation. Request scoped objects are basically given a shimmed struct vmod_priv. I had to jump thru a few small hoops in vcc code to get the priv->priv to cast into an actual struct that the VMOD expects. This may or may not be related to VIP#1, but it would be cleaner to move objects to something more priv like than trying to pass in an explicit struct. However, for the patch, I kept the object interface the same and made use of the previously mentioned vcc/vrt shims.</div><div><br></div><div>The patch is enough to have the examples work and give you guys an idea of how it would work. I wanted to get some feedback before spending more time on this. Its based off of this commit [1], so feel free to comment on github if you want.</div><div><br></div><div><br></div><div>[0] <a href="https://github.com/rezan/libvmod-types" target="_blank">https://github.com/rezan/libvmod-types</a></div><div>[1] <a href="https://github.com/rezan/varnish-cache/commit/b547bd9ad2fca9db1ef17ee73b8e9b7df9950c34" target="_blank">https://github.com/rezan/varnish-cache/commit/b547bd9ad2fca9db1ef17ee73b8e9b7df9950c34</a></div><div><br></div><div>Thanks!</div><div><br clear="all"><div><div><div dir="ltr">--<br>Reza Naghibi<br>Varnish Software</div></div></div>
</div></div>
<br></div></div>_______________________________________________<br>
varnish-dev mailing list<br>
<a href="mailto:varnish-dev@varnish-cache.org" target="_blank">varnish-dev@varnish-cache.org</a><br>
<a href="https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev" rel="noreferrer" target="_blank">https://www.varnish-cache.org/lists/mailman/listinfo/varnish-dev</a><br></blockquote></div><br></div>
</blockquote></div><br></div></div></div>
</blockquote></div><br></div>