Nginx configuration for shortlink service: Rewrite

2019-07-29 03:32发布

问题:

Some time ago I developed a shortlink service (like goo.gl).

Shortlinks in the browsers addressbar are displayed as example.com/Lg1Q

Recently I migrated from Lighty to Nginx, due to performance benefits. In Lighttpd I used

url.rewrite-if-not-file = (
    "^/(.*)(\?.*)?$" => "/index.php?fwd=$1"
)

to hand over the "Lg1Q" part from the URL to the index.php script.

The index.php script processes the not-file-part from the URL as follows:

if ( !empty( $myUrl ) && $_SERVER['REQUEST_URI'] !== '/index.php' && $_SERVER['REQUEST_URI'] !== '/index.html' && $_SERVER['REQUEST_URI'] !$

        $query = htmlspecialchars( str_replace("fwd=","", $_SERVER['QUERY_STRING']) );
        require_once 'src/clsForwardURL.class.php';
        $myForward = new clsForwardURL();
        $url = $myForward->fForwardURL( $query );
        $url = ( $url[0]['su_longurl'] );
        echo header( 'location:'.$url );


}//end if

I tried to rebuild the rewrite rule from Lighttpd to Nginx syntax like:

rewrite "^/(.*)(\?.*)?$" /index.php?fwd=$1;

After that, I inserted this rule subsequently in the location ~ \.php block and the location / block of the nginx host container in /etc/nginx/sites-available.

Unfortunally in both cases the browser showed a '404' or a '500' error.

My question is: How can I properly setup the rewrite rule for the 'shortlink' purpose?

回答1:

The rewrite in the location / block will rewrite everything - not just your short URIs. You could qualify the rewrite operation using a try_files statement. See this document for more.

For example:

location / {
    try_files $uri $uri/ @rewrite;
}
location @rewrite {
    rewrite ^/(.*)$ /index.php?fwd=$1 last;
}

Notice that the query string component is not part of the normalised URI used by the rewrite directive. See this document for more.

You can simplify the above further, if you modify the PHP code to accept a leading / in the fwd parameter, in which case you could use:

location / {
    try_files $uri $uri/ /index.php?fwd=$uri;
}


回答2:

You don't need a rewrite, the whole capture logic can be in the root location itself, e.g:

location ~ \.php$ {
      ...
}

# using a name variable instead of $1
location ~ ^/(?<short_url>.*)$ {
   try_files $uri $uri/ /index.php?fwd=$short_url;
}