The Sun Java System Web Server 7 Technology Preview was released today! There's a whole bunch of new stuff in 7, and you can use it free of charge.
One of the features I worked on is the <If> tag. As its name implies, <If> makes things conditional. There's a lot of hidden power in the <If> tag, though, especially when combined with regular expressions. When you pair <If> with the redirect SAF, you get some of the flexibility of Apache HTTP Server's mod_rewrite module.
In Web Server, features such as URL forwarding are implemented as Server Application Functions (SAFs). Back in 1994 when Web Server was named Mosaic Netsite, Rob McCool checked in the first version of the redirect SAF. In the decade that followed, redirect learned how to deal with path parameters and query strings. Beyond that, it was largely unchanged.
The redirect SAF lets you redirect URIs that match a certain prefix. (A URI is the part of the URL a web browser sends in its HTTP request.) You specify that prefix with the from parameter and the URL to redirect to with the either the url or url-prefix parameters. In Web Server 7, the from parameter is now optional. If from is omitted, all URIs are redirected. Obviously, that's not particularly useful by itself, but it means you can use <If> to decide which URIs to redirect.
For example, you might have used the following directive in obj.conf in Sun ONE Web Server 6.1:
NameTrans fn="redirect"
from="/docs"
url="http://docs.sun.com"
With Sun Java System Web Server 7, you can use a regular expression instead of the from parameter:
<If $uri =~ '^/docs'>
NameTrans fn="redirect"
url="http://docs.sun.com"
</If>
Given the weird syntax and additional line, I guess that's not really an improvement.
However, suppose you want to do something a little fancier; maybe you want to redirect all requests for /docs/partnumber to http://docs.sun.com/source/partnumber/index.html. With the <If> tag and regular expressions, you can do that:
<If $uri =~ '^/docs/(.*)'>
NameTrans fn="redirect"
url="http://docs.sun.com/source/$1/index.html"
</If>
Here, the <If> tag assigns whatever value matches (.*) to the variable $1. The $1 in the url parameter is dynamically replaced with the value from the original request. That means the above obj.conf snippet will cause a request for /docs/817-6248 to be redirected to http://docs.sun.com/source/817-6248/index.html. (You can get even fancier. For example, if you added a second set of parentheses to your regular expression, <If> would also create a variable named $2 whenever the regular expression matched the requested URI.)
I mentioned that the combination of <If> and redirect offers only some of the flexibility of mod_rewrite. That's true. However, unlike mod_rewrite, <If> can be used for things other than redirecting and rewriting URLs. In fact, <If> can be used in conjunction with any SAF, including 3rd party plugins. All told, Web Server 7 now offers a superset of mod_rewrite's functionality.
In the coming weeks I hope to write about other ways to use <If> and introduce other new features in Web Server 7. Why not try it out and let me know what you think?
Trackback URL: http://blogs.sun.com/elving/entry/regular_expression_redirects_in_7
Posted by ttalex on May 31, 2006 at 09:49 AM PDT #
Actually, you can use variables in any obj.conf directive, even those outside of <If> containers. (The $1, etc. regular expression backreference variables are only defined inside an <If> container, of course, because that's the only place you can eveluate a regular expression.)
Here's a list of predefined variables:
You can also define your own variables using the <variable> element in server.xml.
Posted by Chris Elving on May 31, 2006 at 08:47 PM PDT #
Posted by ttalex on June 01, 2006 at 06:30 AM PDT #
Posted by Michael on January 24, 2007 at 11:04 AM PST #
Michael, these features are new in 7.0. Unfortunately, that means you need to upgrade in order to use them.
Posted by Chris Elving on January 24, 2007 at 05:12 PM PST #
Posted by Karl on March 22, 2007 at 07:28 AM PDT #
You'd typically add a new NameTrans fn="redirect" directive as the first NameTrans directive below the <Object name="default"> line.
Of course, it depends on what you're trying to do. If you want other NameTrans directives to take precedence, they should be listed first. You could even put NameTrans directives in other <Object>s.
Posted by Chris Elving on March 22, 2007 at 07:39 AM PDT #
Posted by BonnIE on April 01, 2007 at 03:00 AM PDT #
Posted by James on April 30, 2007 at 07:09 AM PDT #
You're right, James, this blog entry was about redirecting, not URL rewriting. Fortunately, Sun Java System Web Server 7.0 can do URL rewriting, too.
In my examples, redirects were done using the redirect SAF. You can use all the same <If> and regex magic with the new restart SAF. The restart SAF will restart processing internally, telling the server to pretend that the request was actually for a different URI. (There's also a new rewrite SAF, but it's for the more specific task of rewriting one file system path to another. It's useful for mass virtual hosting, but you probably don't want to use it for pretty URLs.)
Here's a quick example:
Posted by Chris Elving on April 30, 2007 at 05:51 PM PDT #
Posted by James on May 01, 2007 at 05:35 AM PDT #
Posted by Dheepak on July 13, 2007 at 02:16 PM PDT #
/* this little program helps me to understand the parameters I can use */
/* in the if conditionals in the obj.conf */
/* compile string: */
/* cd <server_root>/samples/nsapi */
/* cc -DNET_SSL -DSOLARIS -D_REENTRAN -DMCC_HTTPD -DXP_UNIX -DSPAPI20 -I../../include -c show_var.c */
/* ld -G show_var.o -o show_var.so */
/* insert following in magnus.conf: */
/* Init fn="load-modules" shlib="<server_root>/samples/nsapi/show_var.so" funcs="show_var */
/* insert following in obj.conf: */
/* <If $uri =~ "^/show_var"> */
/* NameTrans fn="show_var" var="<VARIABLE TO DISPLAY>" */
/* </If> */
/* example of var: */
/* "uri = $uri<br>url = $url<br>urlhost = $urlhost<br>ip = $ip<br>dns = $dns" */
#ifdef XP_WIN32
#define NSAPI_PUBLIC __declspec(dllexport)
#else /* !XP_WIN32 */
#define NSAPI_PUBLIC
#endif /* !XP_WIN32 */
#include <stdio.h>
#include <stdlib.h>
#include "nsapi.h"
int msg_and_exit(char *msg, Session *sn, Request *rq) {
if (pblock_findval("content-type", rq->srvhdrs))
param_free(pblock_remove("content-type", rq->srvhdrs));
pblock_nvinsert("content-type", "text/html", rq->srvhdrs);
protocol_status(sn, rq, PROTOCOL_OK, NULL); // 200 response
protocol_start_response(sn, rq);
if (net_write(sn->csd, msg, strlen(msg)) == IO_ERROR)
return REQ_EXIT;
net_flush(sn->csd);
return REQ_PROCEED;
}
NSAPI_PUBLIC show_var(pblock *pb, Session *sn, Request *rq) {
char *var,*msg;
int len;
msg = (char *) MALLOC(1024);
/*check program arguments*/
var = pblock_findval("var",pb);
if (!var) {
len = util_sprintf(msg,"Program Error: Misconfigured\n");
return msg_and_exit(msg,sn,rq);
}
len = util_sprintf(msg,"<html><body><h1>%s</h1></body></html>\n",var);
return msg_and_exit(msg,sn,rq);
}
Posted by Curzio Della Santa on June 20, 2008 at 01:03 AM PDT #
Curzio, that's a neat idea, but you probably should not deploy that NSAPI plugin on a production website. It contains a potential buffer overflow that could allow an attacker to take control of the web server. It also doesn't HTML encode its output, so it could be used to launch cross-site scripting attacks.
Posted by Chris Elving on June 25, 2008 at 04:12 PM PDT #
I have avery specific query::
I am using Sun AM 7 + Webserver 7
AM is configured to protect "*" i.e ALL apps are protected.
I give the following in "default" tag in obj.conf
<If $uri =~ '^/myAppContext'>
NameTrans fn="redirect" url="http://abcserver001.clientdomain.com:4567/myAppContext"
</If>
The sso page has stopped comming & it directly takes me to the application first page. I.e. without asking for user / pwd.
Is there any other step I need to do ?
/Cheers
Posted by kanwaljit singh on July 02, 2008 at 04:49 AM PDT #
We got it working for the CU with help from Web Server team.
Posted by kanwaljit singh on January 26, 2009 at 09:42 PM PST #