Last-Modified and NSAPI Filters

Recently, the admin for one of Sun's larger internal websites was concerned that his web server -- Sun Java System Web Server 6.1 -- wasn't returning Last-Modified headers on some responses. The Last-Modified header is part of the HTTP protocol that lets clients know when the content at a particular URL was last modified. In his case, he was concerned because Sun's internal search engine wasn't displaying modification dates in the search results for some of his pages.

It turns out that the site made extensive use of Server Side Includes (also known as SSI or SHTML). Because SHTML content is dynamically generated, there really isn't any way to figure out when the served content last changed. Because he considered the dynamically generated parts of the response to be unimportant -- they were page headers and footers that were shared across many different pages -- he wanted the server to simply set the Last-Modified header to the time the .shtml file was last modified. The Apache HTTP Server happens to have a kludge designed exactly for this particular task, XBitHack full. When XBitHack Full is set in httpd.conf, Apache checks the group execute bit of the .shtml file. If the bit is set, it sets the Last-Modified header to the time the .shtml file was last modified. Unfortunately, that particular hack isn't available in Web Server 6.1.

I thought this would be a good opportunity to demonstrate a new technology in Web Server 6.1, NSAPI filters. NSAPI lets you extend a web server with custom plugins, and it's been part of Sun's Web Server for years. Sun inherited NSAPI from Netscape, where it appeared in Netscape Enterprise Server. Other web server products, like Zeus Web Server, also offer support for NSAPI. Web Server 6.1 expands upon NSAPI by introducing NSAPI filters, allowing plugins to intercept -- and optionally modify -- data as it enters and leaves the server.

I created a simple plugin named lastmodified that sets the Last-Modified header to the time the .shtml file was last modified. Here's what the code looks like:

/\*
 \* If a Last-Modified header would not normally be sent, set-file-last-modified
 \* instructs Web Server to send a Last-Modified header that contains the file
 \* modification time.  This is useful for resources where the output is
 \* dynamically generated but will only change if the file modification time
 \* changes.
 \*/

static int output_set_file_last_modified(pblock \*pb, Session \*sn, Request \*rq)
{
    struct stat \*finfo;
    struct tm mtm;
    char last_modified[HTTP_DATE_LEN];

    if (pblock_find(LAST_MODIFIED, rq->srvhdrs) != NULL)
        return REQ_NOACTION;

    finfo = request_stat_path(NULL, rq);
    if (finfo == NULL)
        return REQ_NOACTION;

    util_gmtime(&finfo->st_mtime, &mtm);
    util_strftime(last_modified, HTTP_DATE_FMT, &mtm);
    pblock_nvinsert(LAST_MODIFIED, last_modified, rq->srvhdrs);        

    return REQ_NOACTION;
}

(If you're familiar with NSAPI filters, you'll notice that lastmodified isn't really an NSAPI filter at all. In fact, it's an NSAPI SAF that leverages the new Output directive that was introduced for the benefit of filters.)

Now, the cool thing about Sun's web servers is how they seamlessly integrate different web technologies. You can see an example of this tight integration when you use the lastmodified plugin. Unlike the Apache XBitHack full directive, this plugin works with any type of content served by Web Server. You can use the plugin in conjunction with JSP, PHP, or CGI, and everything "just works".

If you're using Web Server 6.1 or higher, you might like to try the lastmodified plugin or use it as a starting point for developing your own plugins. I've placed the source code for lastmodified.c online, as well as prebuilt Solaris SPARC, Solaris SPARC (64-bit), and Linux x86 shared objects and a Windows DLL.

To use the plugin, simply add the following directive to Web Server's magnus.conf configuration file:

Init fn="load-modules" shlib="/opt/SUNWwbsvr/plugins/lastmodified.so"

(Where /opt/SUNWwbsvr/plugins/lastmodified.so is the filename of the plugin shared object or DLL.)

Then add the following lines to the top of Web Server's obj.conf configuration file:

<Object ppath="\*.shtml">
Output fn="set-file-last-modified"
</Object>

(Where \*.shtml is the wildcard pattern that matches files where the Last-Modified header should be set to the file modification time.)

I hope to share some other NSAPI plugins in the future. Have any of you done anything interesting with NSAPI?

Comments:

[Trackback] Sun Java System (SJS) Web Server の開発エンジニアである Chris Elving が, SJS Web Server ネタを blogs.sun.com で書き始めたみたい. elving's web server logs 一本目のエントリからいきなり前振りなしに, Apache HTTP Server の XBi...

Posted by tkudo's weblog on March 28, 2006 at 11:52 AM PST #

Post a Comment:
  • HTML Syntax: NOT allowed
About

elving

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today