0

I am trying to rewrite a semi static URL path to a dynamic path without much luck. In full transparency, I am pretty new to NGINX and regex, so please bare with me.

I am redirecting from this path: /locations/schedule-tour/locationnumber (this is a real number and dynamic based on the location you are viewing) and I want it to redirect to a path like this: /locations/state/city/address--locationnumber. I can get the location number and #scheduletour to come to the new URL, but I can't figure out how to get the state/city/address portion of the URL to come across. Even looking at rewriting the path name in the server block has stumped me because I don't know how to pull in that state/city/address portion given it's dynamic nature. I'm trying to write one redirect instead of thousands. Any help is appreciated.

You can see what I've tried below. But even if I can change the path name instead of doing a rewrite, then how do I capture the state/territory abbreviation, city name and address dynamically in nginx? Simple redirects have been relatively easy for me, but this one is kicking my butt. Any help is greatly appreciated!

I have tried this:

rewrite (?i)^/locations/schedule-tour/(\d+)$ /locations/$2--$1%23scheduletour permanent;

rewrite (?i)^/locations/schedule-tour/(\d+)$ /locations/(.*)--$1%23scheduletour permanent;

location = /locations/schedule-tour/(\d+)$ {
                return 301 /locations/[^/]/[^/]/[^/]--$1%23scheduletour;
            }

The second attempt worked the best, but obviously is showing (.*) in the URL instead of the state/city/address/ that I actually need.

2
  • how should nginx know about, which number is the correct one?
    – djdomi
    Commented Apr 16 at 18:43
  • I provided a long answer below, and now I'm hoping I didn't misunderstand your problem statement... if you're just looking for multiple capture groups then you can extract /state/city/address if it is present in the URI... capture using Regex and then rewrite using not only $1, but also $2, $3, and $4... etc. just as "easy". But I didn't think State-City-Address was in URI.
    – bellasys
    Commented May 2 at 6:09

1 Answer 1

0

Interesting question and zero answers so far... I will do my best to help but there's some missing info... as djdomi hints in the comment - how would Nginx know the correct City, State, Address? "How" in this case prepares the scope of the solution.

Let us assume that there is a Table of Data in which a Numbered Row [locationnumber] references columns with State, City, Address, at least. If that data could be retrieved as $s, $c, $a, then in theory a new URI could be constructed as: /locations/schedule-tour/$s/$c/$a--[locationnumber]%23scheduletour

You can get the [locationnumber] via $1 from Regex on the URI; what's missing is the mechanism to map [locationnumber] to the other required data such that correct URL's would be built.

So in Nginx there is a Map component which would take Static inputs and output a corresponding static string very neatly, ready to inject into a rewritten URI. That code block looks like this:

http {
    ...

    #first map here extracts the locationnumber from uri and sets $loc_num
    map $request_uri  $loc_num {
        ~^/locations/schedule-tour/(\d+)$  $1 ;
        default "" ;
    }
    #second map renders value in $loc_num as uri component
    map $loc_num $loc_uri {
        default "" ;
        123   /California/Dana_Point/One_Ritz-Carlton_Dr ;
        1234  /Oregon/Cannon_Beach/539_S_Hemlock_St ;   
        12345 /Hawaii/Kihei/3900_Wailea_Alanui_Dr ;
    }
    
    server {
        ...
        location *~ ^/locations/schedule-tour/(\d+) {
            #effectively concats the new uri with $loc_uri and extracted $1
            rewrite ~ ^(.*)$  /locations/schedule-tour$loc_uri--$1%23scheduletour ;
            ... 
        }
    }
}

According to the above code a Requested URL of https://my.server.com/locations/schedule-tour/1234 would get rewritten and render the same result as requesting https://my.server.com/locations/schedule-tour/Oregon/Cannon_Beach/539_S_Hemlock_St--1234#scheduletour

However, the "map" solution could be a problem depending on the scale of your locations... meaning if you have more than 50, or if these would be constantly changing, then Static Mapping may not be suitable for the problem. Technically there is nothing really wrong with using more static data in Maps, even if more than 50, or even if dynamic... but it's now how I'd go depending on scale. I mean, who wants to manually update Server configs all the time?

Which is why I wondered about how locationnumbers transform into the State/City/Address you need.

For more complex operations (massively dynamic tour routes, or massive number of them) in which case something like a Database or at least some Table would be used to catalog the locationnumbers, there is a more complex solution involving Lua scripting. Essentially, data is retrieved and injected via Lua code into the Rewrite using variables provided by the Lua Script, and injected into the resulting uri... this is not a lot more complex, but then you would be using Nginx as an Application Server, not just a Proxy.

And there's nothing wrong with that!

This answer's pretty long already, but I hope at least a couple different viable mechanisms have been presented.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .