ns_register - Register Tcl/ADP handlers
This document describes various command to bind Tcl code and/or ADP-pages to URL patterns.
Requests to the server which match the method and URL will trigger the ADP page request handler. If file is given then it is the specific ADP page which should respond to all matching requests. Otherwise, the ADP page will be located at request time using ns_url2file.
This command works similar as ns_register_tcl, but registers an ADP file instead of a Tcl script.
Use ns_unregister_op to unregister an ADP request.
This command register given URL to be processed by fast path subsystem, i.e. all requests that match will be served by corresponding .adp files if resolved. This can be used when there is no global fast path handler installed.
The argument method is restricted to GET, POST or HEAD
ns_register_filter registers a Tcl filter script for the specified method/URL combination on a virtual server. When -first is used, it is added to the front of the filter list, otherwise to the end.
The when argument specifies, when the filter script is called. preauth means pre-authorization, postauth means post-authorization, and trace means at the end of the request, after the page data has been returned to the user, and the connection has been processed and closed.
The filter will be called at the specified stage of a connection, if the method/URL combination for the filter matches the method/URL combination for the connection using glob style matching.
The URL can contain standard string-matching characters. For example, these are valid URLs:
/employees/*.tcl /accounts/*/out
Using pre-authorization, the procedure will be called (assuming that the method/URL combination matches) just before authorization. If the procedure returns with a code of:
TCL_OK (script ends with: return "filter_ok"): The server will continue to the next pre-authorization filter for this connection, or, if there are no more pre-authorization filters, it will continue on with authorization.
TCL_BREAK (script ends with: return "filter_break"): The server will not process any more pre-authorization filters for this connection, and it will continue on with authorization.
TCL_RETURN (script ends with: return "filter_return"): The server will close the connection and will not run any more pre-authorization filters. It will not authorize the request, and it will not run the function registered for this METHOD/URL. It WILL run any trace functions registered for this METHOD/URL, usually including logging. It is assumed that the filter has sent a proper response (e.g., using ns_return) to the client before returning TCL_RETURN.
Using post-authorization, the procedure will be called (assuming that the method/URL combination matches) just after successful authorization. If the procedure returns:
TCL_OK (script ends with: return "filter_ok"): The server will continue to the next post-authorization filter for this connection, or, if there are no more post-authorization filters, it will run the function registered to handle this request.
TCL_BREAK (script ends with: return "filter_break"): The server will not process any more post-authorization filters for this connection, and it will run the function registered to handle this request.
TCL_RETURN (script ends with: return "filter_return"): The server will close the connection and will not run any more post-authorization filters and it will not run the function registered for this METHOD/URL. It WILL run any trace functions registered for this METHOD/URL, usually including logging. It is assumed that the filter has returned a proper response (e.g., using ns_return) to the client before returning TCL_RETURN.
Using trace, the procedure will be called (assuming that the method/URL combination match) after the connection has been totally processed and closed. If the procedure returns:
TCL_OK (script ends with: return "filter_ok"): The server will continue to the next trace filter.
TCL_BREAK, TCL_RETURN (script ends with: return "filter_break" or return "filter_return"): The rest of the trace filters are ignored.
ns_register_filter/ns_register_trace and ns_register_proc are similar, but significantly different. With ns_register_proc, the specified URL is used to match that URL and any URL below it in the hierarchy. Wildcards such as "*" are meaningful only for the final part of the URL, such as /scripts/*.tcl. With ns_register_filter, the URL is used to match URLs as a string with standard string-matching characters. ns_register_proc results in a single match, whereas multiple ns_register_filters/ns_register_trace can be matched and will be called.
Be aware that executing the same ns_register_filter statement more than once (as you might do when re-initializing Tcl) will add the filter more than once! You may want to have a shared variable set to avoid multiple registrations. Filters can be shortcutted via ns_shortcut_filter.
ns_register_proc registers the procname to handle the specified method/URL combination. When the server gets a matching request, it calls procname with the connection id and any arguments specified here.
If -noinherit is specified, the requested URL must match the specified URL exactly. For example, if the URL specified with ns_register_proc is /foo/bar, procname will not be called unless the requested URL is exactly /foo/bar.
If -noinherit is not specified, the requested URL can match the specified URL or any URL below it. For example, if the URL specified with ns_register_proc is /foo/bar, procname will be called for /foo/bar, /foo/bar/hmm, and any other URL below /foo/bar, provided there is not already another procedure registered for that exact URL or for a URL with a closer match. Note that you must use a glob-style matching character if you want inheritance for filenames. For example, if you want /foo/bar to match /foo/bar.html, you must use:
ns_register_proc /foo/bar*
You can register two procedures for any given method/URL combination by calling ns_register_proc once with the -noinherit flag set and once without it. Only one of the procedures will be called for any given request, depending on whether the URL was an exact match or not. For example:
ns_register_proc -noinherit GET /foo/bar Aproc ns_register_proc GET /foo/bar Bproc ns_register_proc GET /foo/bar/hmm Cproc
Aproc will be called when the requested URL is exactly /foo/bar. Bproc will be called when the requested URL is below /foo/bar, provided there is not already another procedure registered to be called for that exact URL or for a URL with a closer match. Cproc (not Bproc) will be called when the requested URL is equal to or below /foo/bar/hmm.
The following example shows how arguments can be passed at registration time to the registered Tcl command:
ns_register_proc GET /noargs noargs ns_register_proc GET /onearg onearg 1 ns_register_proc GET /twoargs twoargs 1 2 ns_register_proc GET /threeargs threeargs 1 2 3 proc noargs { } { ns_returnnotice 200 "testing" "noargs" } proc onearg { x } { ns_returnnotice 200 "testing" "onearg gets $x" } proc twoargs { x y } { ns_returnnotice 200 "testing" "twoargs gets $x $y " } proc threeargs { x y z } { ns_returnnotice 200 "testing" "threeargs gets $x $y $z" }
ns_register_proxy registers a Tcl script as a handler for the specified method/protocol combination.
Example of a trivial HTTP proxy server (there is a much more elaborate reverse proxy server available as NaviServer module.
ns_register_proxy GET http http_proxy_handler proc http_proxy_handler { args } { set port [ns_conn port] if {$port == 0} { set port 80 } set url http://[ns_conn host]:$port[ns_conn url]?[ns_conn query] set d [ns_http $url] set content_type [ns_set iget [dict get $d headers] content-type] ns_return [[dict get $d status] $content_type [dict get $d body]] }
Register Tcl file to be called when request matches method/URL combination. This is to enable extension-less URLs or for mapping actual files into virtual URLs. The command ns_register_tcl works similar as ns_register_adp except the file to evaluate should be a Tcl file which might use ns_return, ns_write etc. to respond to the request.
If this argument file is omitted, the command will register standard C-based callback which will resolve URLs into absolute Tcl file and execute it.
Use ns_unregister_op to unregister a Tcl request handler.
ns_register_trace registers a Tcl script as a special filter for the specified method/URL combination. After the server handles the request for the specified method on a URL that matches the URL, it calls the trace script with the connection id and any arguments (args) specified. ns_register_trace is very similar to ns_register_filter trace (known internally as void_traces). The script registered by this command fires after the scripts registered by ns_register_filter trace and differ by the fact that they only execute if a response was successfully sent to the client (i.e. not a Server Error). In addition, their return value is ignored.
The URL can contain standard string-matching characters. For example, these are valid URLs:
/employees/*.tcl /accounts/*/out
ns_register_trace is similar to ns_register_proc except that the pattern-matching for the URL is performed differently. With ns_register_proc, the specified URL is used to match that URL and any URL below it in the hierarchy. Wildcards such as "*" are meaningful only for the final part of the URL, such as /scripts/*.tcl. With ns_register_trace, the URL is used to match URLs as a string with standard string-matching characters.
ns_register_proc results in a single match, whereas multiple ns_register_trace's can be matched and will be called.
These commands are used to perform run time resolving of the requested URLs into corresponding files that will be served to the client. They use ns_url2file interface which resolves file for current URL. ns_register_fasturl2file register the default fast url2file proc for the given URL. The Tcl script provided to ns_register_url2file is used to return full path to the requested URL.
Unregister a Tcl or ADP request handler for the specified method/URL combination. This command unregisters any Tcl or C functions previously registered for this method/URL combination and with the same inheritance setting. That is, if the -noinherit flag is specified with ns_unregister_op, the function previously registered with the -noinherit flag using ns_register_proc (or the NS_OP_NOINHERIT flag in ns_RegisterRequest) will be unregistered. If -noinherit is omitted, the function previously registered without the -noinherit flag (or the NS_OP_NOINHERIT flag) will be unregistered.
The option -noinherit specifies the (virtual) server from where the handler should be unregistered. If this option is not specified, the current server is used.
The command is the inverse command to ns_register_url2file. The option -noinherit specifies the (virtual) server from where the resolver should be unregistered. If this option is not specified, the current server is used.
The HTTP method, such as HEAD, GET or POST, which will be compared using exact string equality to the HTTP request.
foreach method {HEAD GET POST} { ns_register_adp $method /foo/bar "hmm.adp" }
The URL pattern to match against the URL in each HTTP request. The last component of the URL may contain the globbing characters * and ?.
ns_register_adp GET /dynamic/*.htm?
In this example, a URL where the last component matches the pattern *.htm?, such as /dynamic/foo.htm or /dynamic/a/b/c/bar.html, will be run by the ADP engine.
Only the last component of the URL may be a pattern. If this is too restrictive, try using ns_register_filter.
The optional argument file is either an absolute path to a file in the filesystem, or a path relative to the page root directory of the virtual server.
ns_register_adp GET /a "a.adp" ; # relative to page root ns_register_adp GET /b "b/b.adp" ; # relative to page root ns_register_adp GET /c "/c.adp" ; # absolute in file-system root
The first and second lines specify a file relative to the page root directory. The full path is constructed each time the ADP page is requested using ns_pagepath, so ns_serverroot and ns_register_url2file callbacks will be taken into account.
In the third example, a specific ADP file in the server's filesystem is registered for a similarly named URL (and all URLs below it). There are no calls to ns_pagepath or ns_url2file during the request.
In the following example, all files with the .adp extension in and below the /big URL should be served by the ADP handler, with the options stricterror and stream enabled:
foreach method {GET HEAD POST} { ns_register_adp -options {stream stricterror} -- $method /big/*.adp }
In the following example, we return for every GET request for a .php file in the given path an info message.
ns_register_proc GET /foo/bar/*.php { ns_return 200 text/plain "Server refuses to execute PHP scripts here" }
This example shows how to expire all HTML files after an hour:
if {![nsv_exists filters installed]} { nsv_set filters installed 1 ns_register_filter postauth GET /*.html ExpireSoon 3600 } proc ExpireSoon {seconds why} { ns_set update [ns_conn outputheaders] Expires [ns_httptime [expr {$seconds + [ns_time]}]] }
The command ns_server can be used to list the currently registered filters, traces or procs.
ns_server filters ns_server traces ns_server requestprocs