Forum OpenACS Q&A: How to use ns_register_filter to establish a route to be served by NaviServer

We are currently using the reverse proxy with great success. It handles what we want it to quite nicely. We have come up with a case that we are wondering about though. Is there a way to specify a route that will fall through and be served by NaviServer?

Here is an example:

# I have a route /some-site-loc/* that gets forwarded to a target but, I want two of the sub-routes to be handled else where.
# I want a separate target to handle requests to the sub-route /some-site-loc/names/*; this filter works as expected
# I want NaviServer to handle the sub-route /some-site-loc/ns-special/*; can this be done?

ns_register_filter postauth * /some-site-loc/names/* ::revproxy::upstream -target $target_1_url -url_rewrite_callback my::rewrite_url
ns_register_filter postauth * /some-site-loc/ns-special/* some_call ; # this route I want NaviServer to serve.
ns_register_filter postauth * /some-site-loc/* ::revproxy::upstream -target $target_2_url -url_rewrite_callback my::rewrite_url

The requests to target_1_url and target_2_url work well and as expected. Is there something that I can put in the place of some_call, in the second filter above, that will cause a request to /some-site-loc/ns_special/* to be served by NaviServer itself?

Thanks,

-Tony Kirkham

The filters are processed sequentially. For one URL, it is possible, that multiple filters of the same filter type are processed.... provided that the filter in this chain allow this.

The behavior is controlled by the return value of a filter [1]. When a filter returns "filter_break", no other filter of the same type will be processed. So, if you arrange your filters such that the special case is in the filter chain before the revproxy call, and the filter for the special case returns "filter_break", the revproxy filter should not be called. Check the order of the registered postauth filters on your server with

lmap f [ns_server filters] {if {[lindex $f 2] ne "postauth"} continue; set f}

[1] https://naviserver.sourceforge.io/n/naviserver/files/ns_register.html#3

I have been unable to find what to use in place of "some_call" in

ns_register_filter postauth /some-site-loc/ns-special/* some_call

to obtain the desired behavior. Owing to the fact that I do not really understand how the filters work, I tried to copy other ns_register_filter calls I could find in other places and, trying to follow your suggestions, I attempted to write a proc that called things like rp_filter and then returned filter_break which I placed in the place of "some_call" above. It did prevent the calling of any later filter but, it did not render the requested page.

I continued reading through the documentation that you referenced and found the call ns_shortcut_filter that only takes when method urlPattern as arguments. If I replace the middle call in my original post with

ns_shortcut_filter postauth * /some-site-loc/ns-special/*

It works exactly how I want!

Is this the call I should use for this purpose, or is there something better and are there any negative side effects of making this call? Like I mentioned, I do not really understand how the filters work. I have read through the request processor documentation but, have not found anything specifically related to the filters and how they work. Is there documentation somewhere that would help me get a better understanding?

Thank you very much for all of your help. I am a bit slow at times with my responses but, I really appreciate and value your help.

-Tony

Hi Tony

I can't believe I'm linking to a Philip Greenspun article from the 1990s, but I always recall this article when I work with registered filters/procs as he explained it very clearly https://philip.greenspun.com/wtr/aolserver/introduction-1.html

This is his explanation:
ns_register_proc GET /foo -- instead of looking in the file system for a file to serve, run a specified procedure whenever a user requests a URL starting with "/foo"
ns_register_filter GET /foo* -- in addition to what else the server might do in serving a request starting with "/foo", also run a specified procedure at a specified time (before or after the page is served)

I think in your case, ns_register_proc might be what you need.

Hope this helps
Brian

Here is a diagram to visualize the differences between procs in the filter chain (filter procs) and the usual request content handlers ((pre-) registered procs stored on disk or in handlers).

Note that the filters are less efficient, since for every incoming request, all filters procs of a filter chain are sequentially matched and are potentially executed, unless a filter proc terminates the chain explicitly. This happens for every filter chain. Under certain uncaught error conditions, some of the steps are skipped.