Richard PB
Richard PB

Reputation: 55

Redirect to new URL having looked up new "ID" in RewriteMap which appears in two places in the target URL

This one may have been answered but I can't seem to find one that fits my specifics. So apologies if it sounds old.

My rewrite consists of using a rewrite map and a redirect to another domain.

For example:

An old site has moved and new id's have been generated along with file name changes

So this URL:

https://www.example.com/gallery/951/med_U951I1424251158.SEQ.0.jpg

would need to be redirected to

https://www.example2.com/gallery/5710/med_U5710I1424251158.SEQ.0.jpg

The new value 5710 comes from a rewrite map lookup where I pass 951

there are two changes needed and the 2nd change has two possible variations:

  1. The first change is gallery/951 to gallery/5710

  2. The 2nd change is the filename where the id can be delimited in either of 2 ways:

    • U951I - delimited between a U and an I

    or

    • U951. - delimited between a U and a .

I started with something like this:

RewriteRule "^gallery/(\d+)/(\s+)$"  

But that is as far as I can get.

Upvotes: 1

Views: 159

Answers (1)

MrWhite
MrWhite

Reputation: 45829

You could do something like the following:

RewriteCond ${MapName:$1|XXX} (.+)
RewriteRule ^/?gallery/(\d+)/(.*U)\1([I.][^/]+)$ https://www.example2.com/gallery/%1/$2%1$3 [R=302,L]

I'm assuming the domain being redirected to resides on a different server, otherwise (if this is in .htaccess) you would need to check the requested hostname in an additional condition (RewriteCond directive).

Explanation:

  1. The regex ^/?gallery/(\d+)/(.*U)\1([I.][^/]+)$ matches and captures the relevant parts of the source URL...

    • ^/?gallery/ - Literal text (optional slash prefix if this is being used in a server context, as opposed to .htaccess)
    • (\d+) - Captures the "old" member ID (later available using the $1 backreference and used to lookup the "new" member ID from the RewriteMap)
    • / - literal slash
    • (.*U) - Captures the first part of the filename before the "old" member ID. Later available in the $2 backreference.
    • \1 - An internal backreference matches the "old" member ID that occurred in the 2nd path segment - Not captured.
    • ([I.][^/]+)$ - Captures the last part of the filename after the "old" member ID - Later available in the $3 backreference. The character classs [I.] matches either an I or a literal . (the dot does not need to be escaped when used inside a character class). And [^/]+ matches everything thereafter to the end of the filename (URL-path).
  2. The RewriteCond directive serves to lookup the new member ID (using the old member ID saved in the $1 backreference) in the rewrite map defined earlier in the server config. The result is then captured, which is later available in the %1 backreference. I set a default XXX so it would be easy to spot any lookups that fail.

    Using the RewriteCond directive means we only lookup the rewrite map once. (Results are probably cached anyway, but it saves repetition at the very least.)

  3. /%1/$2%1$3 - The substitution string is then constructed from the backreferences captured earlier:

    • %1 is the new member ID (captured in the preceding CondPattern)
    • $2 is the part of the filename before the member ID (captured by the RewriteRule pattern against the URL-path).
    • $3 is the part of the filename after the member ID.

Note that backreferences of the form $n refer to captured groups in the RewriteRule pattern and backreferences of the form %n refer to captured groups in the last matched CondPattern (RewriteCond directive).

Upvotes: 1

Related Questions