RewriteMap help

Hello.

I am web developer newbie who creates the php class who converts the ugly look of the url to the friendly one. Result of the usage of this class is friendly url output and generated htaccess file with rules and conditions for particular urls.

Sample: I have some url who looks as follows:

index.php?a=1&b=2&c=3

, where any of these variables can have value {numbers, letters}. Variables values are collected from database tables.


a=1 => webtest_1
a=2 => webtest_2
...
a=x => webtest_x
-------------------------------
b=1 => photo_1
b=2 => photo_2
...
b=x => photo_x
--------------------------------
c=1 => pc_1
c=2 => pc_2
...
c=x => pc_x
--------------------------------
...
...
...
--------------------------------
z=1n => last_variable_1n
z=2n => last_variable_1n
...
z=xn => last_variable_xn


So, my htaccess contains something like:


Options +FollowSymlinks
RewriteEngine on

RewriteRule ^webtest_1/photo_2/pc_3\\.html$ /index.php?a=1&b=2&c=3 [L]
RewriteRule ^webtest_2/photo_1/pc_1\\.html$ /index.php?a=2&b=1&c=1 [L]
...
...
...

I have been done with this class so far - i am able to use it, only one disadvantage - lack of knowledge in htaccess coding. The htaccess file is huge and depends on the number of variables selected in url and number of rows assigned from the DB tables. I am looking for option to optimize it and speed up the loading of the web.

Could anyone advice and might be show how to use RewriteMap for my case. I have read a lot but have not got a solution for it.

Thank you in advance.

First, I must say I’ve never personally used RewriteMap, though where I work there is a website where we are considering it (we have a similar situation to what you have, lots of vars in the URL).
Oh, and welcome to SitePoint!

A rewrite map isn’t necessarily faster than writing a hundred separate rewriteRules, but may be easier to maintain esp if you’ve got some script making a list anyway.

You’d want to decide what kind of map file you want. You can do plain text or you can do something that’s indexable like a DBM (which would be faster searching for Apache).

Then before your regular rewrite rules, but after your Rewrite on statement, you’d have to tell Apache that you’re using a map, tell it what name you’ve given it, what type it is, and where it is (well, problem here is, I read in the docs that RewriteMap directive still has to go into the main config file, and I personally have never used .htaccess so I’m unclear which parts go in your .htaccess and which parts go in the main config file). If I understand correctly the RewriteMap lines go in the main config and the rules where you actually list matches stay in your .htaccess file.

So I think it would be
in main httpd config
RewriteEngine On
RewriteMap nameofyourmapfile type:url

then I think your .htaccess has (after its RewriteEngine On etc)
RewriteRule ^somepattern ${nameofyourmapfile:$1|thedefault} flagz

where thedefault seems to be a url (if Apache can’t find a match in your map file, it should just redirect to that url instead).

The rewrite rules you posted seem to be missing capturing parenthesis and matches so I hope that is just a muddled example.

The benefit of a map would be that your script could change the text in the map whenever and Apache will be able to use it to match to new urls, instead of you having to manually update the rewrite rules all the time.

Yes, Mallory, the httpd.conf file (or equivalent) is where the RewriteMap is authorized - it cannot be initiated from an .htaccess file making it irrelevent to 99% of the members here.

Basically, it’s a programming technique to use programmed responses to URI requests. I’ve aided a member with one of these (difficult because it was third or fourth party where nobody seemed to know what I was talking about). FWIW, Options +FollowSymLinks SHOULD already be set in the server’s config file.

staz,

Imagine my horror at your statement that your .htaccess file is very long! .htaccess should be reserved for only the last moment redirections (or directory specific directives) and NEVER a place to waste machine cycles reading the file for every request. If you are on a shared server, you should be removed for such abuse.

Now that that’s out of my system, I saw patterns to your variables so, if you are using photo, pc, etc and follow with an underscore and single digit, that’s the type of pattern that mod_rewrite’s regex excells in handling! If not, can you work with variables defined as ([a-z0-9_]+) - that’s lowercase letters, digits and underscores? If you can describe your problem in a little more detail, it would help - but it was good to see that you can handle mod_rewrite code!

You might benefit from reading the mod_rewrite tutorial linked in my signature as it contains explanations and sample code. It’s helped may members and should help you, too.

Regards,

DK

Thanks dklynn and Stomme poes.

I have read your replies and appreciate that. I have tried to make RewriteMap on my own using your suggestions and suggestions and examples provided on the NET without success. looks like it is over my head to get it right on my own.

Answering on the questions:

  1. hundreds of lines it is disaster - that is the reason for willingness to use RewriteMap. If i would use proper way of handling the variables and their values while doing my past web applications, i would be able to use patterns without insulting dklynn :slight_smile:

  2. Using patterns - in my perspective of view it can not be done because values assigned to the variables are dynamic, picked up from the DB tables (could be ‘web’, ‘photo’, could be ‘test999’ or ‘just simple 999test’ etc.)

  3. benefit from reading the mod_rewrite tutorial linked in my signature. Thanks for link, it was good tool to learn but unfortunately i did not find it relevant to my specific needs.

+

my one line of the code in .htaccess file is as follows:

RewriteRule ^andis-services/web-design/search-engine-optimization/page-( [^-]*)\\.html$ index.php?m=1&s=3&p=$1 [L]

the link in simple php file looks like:


echo '<a href = " andis-services/web-design/search-engine-optimization/page-100.html ">test</a>';

the issue is that link does not target the same page all the time. after every click on it, i am getting redirection to:

2nd click goes to:


andis-services/web-design/search-engine-optimization/andis-s ervices/web-design/search-engine-optimization/page-100.html

3rd click goes to:


andis-services/web-design/search-engine-optimization/andis-s ervices/web-design/search-engine-optimization/andis-services /web-design/search-engine-optimization/page-100.html

etc.

Could anyone have a look on this case and give me some advice on it?

straz,

The .htaccess file is no place to put a long list of redirections. If you have access to the server’s configuration files, put them in the VirtualHost section so they only need to be read once (NOT for every request!).

IMHO, not changing links in a logical fashion (patterns) is the sign of a lack of planning. Okay, I’m throwing rocks in general, NOT specifically at you. In this case, you have a problem and I was pointing out that the POWER of mod_rewrite is its ability to use regular expressions to match and redirect a massive number of requests with a single expression. If you don’t have that ability, then there are TWO ways to handle the situation:

  1. Place redirections in EVERY link. If you’re merely using the database to pull your links and generate pages, this adds impossible to impractable.

  2. Use a RewriteMap to take the request as input and give a redirection as output. A RewriteMap can be a simple text file (per Apache.org’s example) or it can, as I’ve used it, access a PHP script which accesses a database which can map the old request to the new.

[INDENT]RewriteMap for non‐System Admins

If you don’t have system administrator access (to your server
or VirtualHost configuration files), you can simulate a
RewriteMap’s prg: function, i.e., database access using PHP.
Okay, that IS a cheat but it can be effective!

Since the RewriteMap offers access to scripts, you can use
mod_rewrite to redirect requests to a PHP handler script to
do the same thing. That script can query the database for the
information required and use PHP’s header(“Location:…”)
function to effect the required redirection. Of course, you
should remember to set the Apache response code with
another header(“Status:…”) before the location directive if
altering the status code is desired.[/INDENT]

Okay, IF you are a sys admin, you have access to the server conf file (or VirtualHost file) so:

The format of the command (to enable a RewriteMap) is: RewriteMap MapName MapType:MapSource where MapName is what you want to use as the name of your mapping function, MapType (for a PHP file) is prg and MapSource is the full location of the script on your server, e.g.,

RewriteMap goFetch prg:/usr/local/apache/conf/gofetch.php

To use this program function, you would call it with a format like ${ MapName : LookupKey } OR ${ MapName : LookupKey | DefaultValue }. This would translate to

RewriteRule ^/go/(.*) ${goFetch:$1|/404.html} [L]

Your gofetch.php will have to act like a function in that it accepts the value of the LookupKey and returns the redirection. Because it’s been ages since I’ve done this, a search through my test files gave me:

<?php
$stdin = fopen ('php://stdin', 'r');
$output = fopen('php://output', 'w');
ob_implicit_flush (true);  // Use unbuffered output
while ($uri = fgets ($stdin)) 
{
    $uri = trim($uri);
    [COLOR="Red"]echo "mynewURL.php?" . $uri . "\
";
//  REPLACE with your database lookup![/COLOR]
}
?>

Does that help?

Regards,

DK

thank you dklynn.

I do appreciate your suggestions and time spent to help to figure out the best resolution for such specific issue.

I am trying to put the pieces of jigsaw together - so much info in my head and it is boiling. Looks like it is over my head for sure - at least for now.

I do apologize but i have to start from very basic things - using RewriteMap etc.

At the beginning i am trying to set up RewriteMap for work and no success there (i am getting 500 internal error)

The test code used looks as follows:

  • index.php


    php echo '<a href = "index.php?m=11">test</a>';

  • .htaccess

    Options +FollowSymlinks RewriteEngine on RewriteMap menus txt:C:/wamp/www/SEO/test/menu.txt RewriteRule ^(.*)$ index.php?m=${menus:$1|0}

  • path to the host directory is C:/wamp/www/
  • path to the web directory C:/wamp/www/SEO
  • path to the map C:/wamp/www/SEO/test/menu.txt
  • path to the .htaccess file C:/wamp/www/SEO
  • content of the menu.txt

    web 11 photo 12 pc 13

I have tried to use just simple path to the directories and files, and tried them put in the quotes - no result.

What could be the issue with it?

straz,

While you did not show your menu.txt file, the obvious problem is that you’ve still not “enabled” your RewriteMap in httpd.conf (or extras\httpd-vhosts.conf) so your RewriteMap CANNOT work (RewriteMap is an illegal directive in the .htaccess which is, apparently, resulting in the 500’s).

No apologies necessary. This is a complex subject (not for newbies - but you ARE doing well … with the exception of the RewriteMap directive in the .htaccess) and, unless you have sys admin access on your production server, it’s purely an academic exercise.

As mentioned in my last post, others have suggested (and I concur) that a “handler file” be used to effect the redirection to the correct link, i.e., any (non support file) requests be redirected to the handler which can take {THE_REQUEST} and redirect as required. It’s an extra step but it’s the only way a webmaster can implement a RewriteMap on someone else’s server.

Regards,

DK

Sorry for so late reply - was on holidays for a while :).

I have to apologize for being foolish but i can not figure out how to “activate” the rewrite map in config file.

Looks so simple, but no use for me while reading the apache website. Is that some module who must be uncommented in config file or some lines of the definition of rewritemap added?

straz,

ref: Post #5

Activate using the first code block (Post #5) in the <VirtualHost> block for your domain (in httpd-vhosts.conf in the WinDoze version - unknown in the 'Nix version but you know as you’ve created your domains somewhere). Specify the redirection (second code block) in the DocumentRoot’s .htaccess for the domain. The third code block would be your php script which returns the redirection.

Regards,

DK