WS7+PHPPack: PHP Path Info for URL Rewrites

I've got WS7.0u1 running with PHPPack 5.2.0. Before cutting over our production servers running a PHP application, I thought I'd give it a spin on a personal server running Gallery2. One of the feature you want to enable with Gallery is URL rewriting, which can be done via Apache mod_rewrite, IIS ISAPI_Rewrite, or PHP Path Info. Clearly only the last is a viable option for me, however when I tried to run the test to verify it would work, it would fail with "No input file specified."

After much searching, I found this is a common problem with PHP when enabled as FastCGI, and some folks claimed adding this to php.ini would clear it up:

cgi.force_redirect = 1

However the only thing that worked for me was to define doc_root in php.ini as well. Once I set that, the Gallery "PHP Path Info" test passed. Thats progress, but I do plan on running virtual hosts within a single WS7 instance, each with its own doc_root. Is there a way to accomplish this?

thanks-

Rama

[1007 byte] By [rama-ra] at [2007-11-27 10:24:40]
# 1

web server 7 supports url rewriting as well. pl. check out the following links

http://docs.sun.com/app/docs/doc/820-1062/6ncoqnpea?a=view

http://docs.sun.com/app/docs/doc/820-1062/6ncoqnpej?a=view#gdada

I am not sure about the directive

cgi.force_redirect

Let me look into this more and let you know

chilidevelopera at 2007-7-28 17:29:16 > top of Java-index,Web & Directory Servers,Web Servers...
# 2

I haven't tried this directly, so I'm not positive this will work. I think this would do the trick for you though:

Basically you want a different set of preferences for the PHP engine for each VS (a different doc root, etc).

#Sun FastCGI config

Service fn=responder-fastcgi

app-path="/export/SOWS/third-party/php/php_fcgi"

bind-path="$(lc($urlhost))"

req-retry=5

type="*magnus-internal/fastcgi*"

app-env="PHPRC=/export/SOWS/third-party/php/$(lc($urlhost))_config"

app-env="PHP_FCGI_CHILDREN=10"

app-env="PHP_FCGI_MAX_REQUEST=200"

min-procs=1

restart-interval=10

rlimit_cpu=60

This would use a different PHP process and php.ini for each host name (extracting the Host: header from the request). The php.ini file would live in an appropriately named sub directory of /export/SOWS/third-party/php/ (e.g. /export/SOWS/third-party/php/www.foobar.com_config).

It might be possible to directly set the document root in the obj.conf instead of the php.ini though:

#Sun FastCGI config

Service fn=responder-fastcgi

app-path="/export/SOWS/third-party/php/php_fcgi"

bind-path="$(lc($urlhost))"

req-retry=5

type="*magnus-internal/fastcgi*"

app-env="PHPRC=/export/SOWS/third-party/php/config"

app-env="PHP_FCGI_CHILDREN=10"

app-env="PHP_FCGI_MAX_REQUEST=200"

app-env="DOCUMENT_ROOT=/home/$(lc($urlhost))/"

min-procs=1

restart-interval=10

rlimit_cpu=60

This would use the same php.ini for all PHP processes (and would still use a separate PHP runtime for each VS), and would set the DOCUMENT_ROOT environment variable for PHP to /home/whatever/ (where whatever is the extracted lower case value of the HTTP Host: request header).

Experiment a little. Let me know what you come up with. I've been wanting to use the URL Rewrite option of Gallery2 for a little while and have been considering re-writing the mod_rewrite expressions into WS7 syntax.

JoeMcCabea at 2007-7-28 17:29:16 > top of Java-index,Web & Directory Servers,Web Servers...
# 3

These rewrite directives work for me to get gallery2 to work with rewriting enabled.

-

To enable the rewrite rules for Gallery 2 use the following procedure:

1. Edit your obj.conf file, and add a NameTrans directive for URI mapping:

NameTrans fn="pfx2dir"

from="/gallery2"

dir="/path/to/gallery2"

name="gallery2

2. Still in obj.conf, add the following object to handle the URL rewriting for Gallery.

# obj.conf

....

<Object name="gallery2">

<If $url =~ '/gallery2/d/([0-9]+)-([0-9]+)/([^\/\?]+)(\?(.*)|())'>

NameTrans fn="restart" uri="/gallery2/main.php?g2_view=core.DownloadItem&g2_itemId=$1&g2_serialNumber=$2&g2_fileName=$3&$5"

</If>

<If $url =~ '/gallery2/v/([^?]+)(\?(.*)|())'>

NameTrans fn="restart" uri="/gallery2/main.php?g2_view=core.ShowItem&g2_path=$1&$3"

</If>

</Object>

nseguraa at 2007-7-28 17:29:16 > top of Java-index,Web & Directory Servers,Web Servers...
# 4

Nice Nelson.

Doesn't this still require activating the "rewrite" plugin of Gallery2?

JoeMcCabea at 2007-7-28 17:29:16 > top of Java-index,Web & Directory Servers,Web Servers...
# 5

thanks all- i'll give that a shot. If I follow those obj.conf changes correctly, you wouldn't have to enable rewrite in gallery because as far as the app is concerned, its not aware of the rewriting?

Joe- offering a WS specific version of mod_rewrite I think is a great idea. Its probably a barrier for some folks switching over since so many projects rely on mod_rewrite syntax...

rama-ra at 2007-7-28 17:29:16 > top of Java-index,Web & Directory Servers,Web Servers...
# 6

The app needs to be aware of the rewriting so that URLs it generates are the "shortened" versions. Otherwise all the links generated by the app will still be the long ugly ones. You could use an output filter to rewrite the URLs too, but it should be easier to just turn on the feature in Gallery2.

Regarding mod_rewrite - I was talking about translating the mod_rewrite commands generated by Gallery2 and re-writing them into something that Web Server understands. Porting (or creating) an mod_rewrite config parser is well beyond my skill set.

JoeMcCabea at 2007-7-28 17:29:16 > top of Java-index,Web & Directory Servers,Web Servers...
# 7

SJS Web Server 7.0 offers a pretty good URL rewriting capabilities that should allow you perform some of the most commons rewriting tasks. Check the link to the blogs above.

With that said, I have seen that many times URL rewriting is used by apps to get over some apache limitations, and that in those cases it is more appropriate to use the proper feature that sun web server provides.

Take for example canonical host names. You will find the following rewriting directive used to provide this in Apache:

RewriteEngine On

# OTHER PORTS

RewriteCond %{HTTP_HOST}!^fully\.qualified\.domain\.name [NC]

RewriteCond %{HTTP_HOST}!^$

RewriteCond %{SERVER_PORT} !^80$

RewriteRule ^/(.*) http://fully.qualified.domain.name:%{SERVER_PORT}/$1 [L,R]

# PORT 80

RewriteCond %{HTTP_HOST}!^fully\.qualified\.domain\.name [NC]

RewriteCond %{HTTP_HOST}!^$

RewriteRule ^/(.*) http://fully.qualified.domain.name/$1 [L,R]

You can instead do this in SJS Web Server by using the <canonical-host-name> element of a virtual server

<virtual-server>

...

<canonical-server-name>http://host:port</canonical-server-name>

...

</virtual-server>

So when translating URL rewriting directives from applications written for apache, you should ask yourself what is being accomplished with the directives, and if sun web server can provide such feature as a feature.

nseguraa at 2007-7-28 17:29:16 > top of Java-index,Web & Directory Servers,Web Servers...
# 8

I've been putting off rewriting the Gallery2 mod_rewrite rules for a while. This discussion finally got me to stop being complacent and do it.

I've enable the Gallery2 URL Rewrite module with these options:

Show Item

Download Item

Add Comment

View Comments

Slideshow

RSS

Simple RSS Feed

Updates Album

Popular Album

Random Album

My Gallery2 has its own vanity domain, so it's deployed as the root of the URI space.

Gallery2 helpfully generated an htaccess file with these rules (I've annotated for my own understanding - Please point out errors for me):

RewriteBase /

# Stop processing is the requested file actually exists, or the request is

# for main.php or gallery_remote2.php

# I'm opting to skip this in my translation. It seems a bit unneeded to me.

RewriteCond %{REQUEST_FILENAME} -f [OR]

RewriteCond %{REQUEST_FILENAME} -d [OR]

RewriteCond %{REQUEST_FILENAME} gallery\_remote2\.php

RewriteCond %{REQUEST_URI} !/main\.php$

RewriteRule .-[L]

# If the request is for /popular, and the URI is _not) for /main.php, grab

# Restart the request with the URI changes to the canonical album syntax, and

# append the query string to the end of the new URL (used for paging to pages past

# the front page of the album).

# I notice that all the rules specifically call out main.php in their check. This seems

# overkill to me, so I'll just check once at the beginning of my translation

RewriteCond %{THE_REQUEST} /popular(\?.|\ .)

RewriteCond %{REQUEST_URI} !/main\.php$

RewriteRule ./main.php?g2_view=dynamicalbum.PopularAlbum[QSA,L]

# Same, but for Updates

RewriteCond %{THE_REQUEST} /updates(\?.|\ .)

RewriteCond %{REQUEST_URI} !/main\.php$

RewriteRule ./main.php?g2_view=dynamicalbum.UpdatesAlbum[QSA,L]

# Same, but for Random

RewriteCond %{THE_REQUEST} /random(\?.|\ .)

RewriteCond %{REQUEST_URI} !/main\.php$

RewriteRule ./main.php?g2_view=dynamicalbum.RandomAlbum[QSA,L]

# URI space for downloading items (e.g. "Save Image")

RewriteCond %{THE_REQUEST} /d/([0-9]+)-([0-9]+)/([^/?]+)(\?.|\ .)

RewriteCond %{REQUEST_URI} !/main\.php$

RewriteRule ./main.php?g2_view=core.DownloadItem&g2_itemId=%1&g2_serialNumber=%2&g2_fileName=%3[QSA,L]

# More of the same, but for the slideshow

RewriteCond %{THE_REQUEST} /v/([^?]+)/slideshow\.html(\?.|\ .)

RewriteCond %{REQUEST_URI} !/main\.php$

RewriteRule ./main.php?g2_view=slideshow.Slideshow&g2_path=%1[QSA,L]

# Comment viewing

RewriteCond %{THE_REQUEST} /c/view/([0-9]+)\.html(\?.|\ .)

RewriteCond %{REQUEST_URI} !/main\.php$

RewriteRule ./main.php?g2_view=comment.ShowAllComments&g2_itemId=%1[QSA,L]

# Comment adding

RewriteCond %{THE_REQUEST} /c/add/([0-9]+)\.html(\?.|\ .)

RewriteCond %{REQUEST_URI} !/main\.php$

RewriteRule ./main.php?g2_view=comment.AddComment&g2_itemId=%1[QSA,L]

# RSS and Simple RSS rules

RewriteCond %{THE_REQUEST} /rss/([^\/\?]+)(\?.|\ .)

RewriteCond %{REQUEST_URI} !/main\.php$

RewriteRule ./main.php?g2_view=rss.Render&g2_name=%1[QSA,L]

RewriteCond %{THE_REQUEST} /srss/([0-9]+)(\?.|\ .)

RewriteCond %{REQUEST_URI} !/main\.php$

RewriteRule ./main.php?g2_view=rss.SimpleRender&g2_itemId=%1[QSA,L]

# The main URL cruft for viewing most items. I should probably make this my first

# "Real" rule

RewriteCond %{THE_REQUEST} /v/([^?]+)(\?.|\ .)

RewriteCond %{REQUEST_URI} !/main\.php$

RewriteRule ./main.php?g2_path=%1[QSA,L]

My translated rewrite rules for Web Server 7 are:

# At the top of my default block

# Only enter this stanza if this request is for my vanity VS for photos, and the URI isn't

# for /main.php

<If $urlhost = "photos.foo.com"

and $uri !~ '/main\.php'>

# If the request is for /popular

<If $url =~ '/popular(\?(.*)|())'>

# Restart the request with the canonical URI (and query string, represented here

# by "&$2" - Watch for it below too, but notice that the backreference ID changes

# based on where the parens are in the expression)

AuthTrans fn="restart" uri="/main.php?g2_view=dynamicalbum.PopularAlbum&$2"

</If>

# If the request is for /updates

<ElseIf $url =~ '/updates(\?(.*)|())'>

# Restart with canonical URI and query string

AuthTrans fn="restart" uri="/main.php?g2_view=dynamicalbum.UpdatesAlbum&$2"

</ElseIf>

# etc

<ElseIf $url =~ '/random(\?(.*)|())'>

AuthTrans fn="restart" uri="/main.php?g2_view=dynamicalbum.RandomAlbum&$2"

</ElseIf>

# etc

<ElseIf $url =~ '/d/([0-9]+)-([0-9]+)/([^/?]+)(\?(.*)|())'>

# Restart with the canonical URI and query string, but notice that the backreference

# for the query match is now $5 rather than $2 above

AuthTrans fn="restart" uri="/main.php?g2_view=core.DownloadItem&g2_itemId=$1&g2_serialNumber=$2&g2_fileName=$3&$5"

</ElseIf>

# etc

<ElseIf $url =~ '/v/([^?]+)/slideshow\.html(\?(.*)|())'>

AuthTrans fn="restart" uri="/main.php?g2_view=slideshow.Slideshow&g2_path=$1&$3"

</ElseIf>

# etc

<ElseIf $url =~ '/c/view/([0-9]+)\.html(\?(.*)|())'>

AuthTrans fn="restart" uri="/main.php?g2_view=comment.ShowAllComments&g2_itemId=$1&$3"

</ElseIf>

# etc

<ElseIf $url =~ '/c/add/([0-9]+)\.html(\?(.*)|())'>

AuthTrans fn="restart" uri="/main.php?g2_view=comment.AddComment&g2_itemId=$1&$3"

</ElseIf>

# etc

<ElseIf $url =~ '/rss/([^\/\?]+)(\?(.*)|())'>

AuthTrans fn="restart" uri="/main.php?g2_view=rss.Render&g2_itemId=$1&$3"

</ElseIf>

# etc

<ElseIf $url =~ '/srss/([0-9]+)(\?(.*)|())'>

AuthTrans fn="restart" uri="/main.php?g2_view=rss.SimpleRender&g2_itemId=$1&$3"

</ElseIf>

# etc

<ElseIf $url =~ '/v/([^?]+)(\?(.*)|())'>

AuthTrans fn="restart" uri="/main.php?g2_path=$1&$3"

</ElseIf>

</If>

I'm pretty happy with the results so far.

Also remember that this set of rules only restarts requests coming into the server; it does nothing to make Gallery2 write the URLs in a shorter, friendlier way. You still have to turn on the Gallery2 URL Rewrite module, etc. This tickles the Gallery2 code that generates the links, etc.

JoeMcCabea at 2007-7-28 17:29:16 > top of Java-index,Web & Directory Servers,Web Servers...