NaviServer - programmable web server
4.99  5.0

[ Main Table Of Contents | Table Of Contents | Keyword Index ]

ns_register(n) 5.0.0a naviserver "NaviServer Built-in Commands"

Name

ns_register - Register Tcl/ADP handlers

Table Of Contents

Synopsis

Description

This document describes various command to bind Tcl code and/or ADP-pages to URL patterns.

COMMANDS

ns_register_adp ?-noinherit? ?-expires t? ?-options options? ?--? method URL ?file?

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.

ns_register_fastpath ?-noinherit? ?--? method URL

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 ?-first? ?--? when method URL script ?args?

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 ?-noinherit? ?--? method URL myproc ?args?

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 method protocol script ?args?

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 run $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]]
 }
ns_register_tcl ?-noinherit? ?-cache cache? ?--? method URL ?file?

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 method URL script ?args?

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.

ns_register_url2file ?-noinherit? ?--? URL script ?args?
ns_register_fasturl2file ?-noinherit? ?--? URL ?basepath?

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.

ns_unregister_op ?-noinherit? ?-recurse? ?-server server? ?--? method 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.

ns_unregister_url2file ?-noinherit? ?-recurse? ?-server server? ?--? URL

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.

OPTIONS

-cache t

Specifies for how long to keep result in the cache, in seconds or absolute time.

-expires t

Specifies that the result of evaluating the ADP page should be cached for t seconds (or a value with a time unit). If t is large, it expresses a time in the future (expressed as seconds after the epoch).

-noinherit

Specifies that the directory portion of the request URL should match exactly and not also apply to a URL lower in the hierarchy. This is the default.

Different ADP page handlers can be registered for the same method and URL if one uses the ?-noinherit? option and the other does not.

 ns_register_adp            GET /a x.adp
 ns_register_adp -noinherit GET /b y.adp

In the previous example, a.adp will run for the requests /a, /a/b, /a/b/c and so on. But b.adp will only run when the requested URL is exactly /b. The request /b/c will result in a 404 Page Not Found error.

 ns_register_adp            GET /a x.adp
 ns_register_adp -noinherit GET /a y.adp

In this example, a request for the exact URL /a will run the y.adp page, while /a/b and /a/b/c will run the x.adp page. The y.adp page is more specific than the x.adp page, and hides it for the /a request, which matched it exactly.

-options options

A list of one or more ADP options that should be added to the default set which are in effect while the ADP page runs. Options can only be enabled, not disabled. Valid options are those that ns_adp_ctl accepts, which can be used by ADP code to fine tune the options.

-recurse

if specified, the delete operation will be recursive.

ARGUMENTS

string method

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"
 }
string URL

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.

string ?file?

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.

EXAMPLES

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

See Also

ns_adp, ns_adp_register, ns_conn, ns_server, ns_shortcut_filter, ns_time

Keywords

ADP, callback, fastpath, filter, handler, request, server built-in, urlspace