From your directives I assume you are working directly in the main server config or <VirtualHost>
container (as opposed to a <Directory>
or .htaccess
context).
no restrictions on the path , it can have any number of segments
This slightly complicates matters as there is no "simple" way to replace arbitrary characters in the URL without using a recursive loop to replace each instance of the character using a selective regex.
Try something like the following in your vHost:
# 1. Copy URL parameter value to URL-path and replace the first slash with underscore
RewriteCond %{QUERY_STRING} ^opath=/([^&]*)&appId=
RewriteRule ^/my/service$ $0._%1.html
# 2. Replace subsequent slashes with underscores in copied value in the URL-path
# Query string is passed through unaltered
RewriteRule ^(/my/service\._.*)/(.*\.html)$ $1_$2 [N=20]
UPDATE: $0
, $1
and $2
are backreferences to the captured subgroups (parenthesized subpatterns) in the RewriteRule
pattern. $0
represents the whole match.
Since you are keeping the query string unaltered there is nothing special you need to do in this regard, since the query string is passed through by default (providing you don't state a query string in the substitution string).
The first rule rewrites the initial request to copy the URL parameter value to the URL-path, replacing just the first slash. From example, given an initial request of the form:
/my/service?opath=/content/home/page&appId=myapp
Gets rewritten to:
/my/service._content/home/page.html?opath=/content/home/page&appId=myapp
The next rule then rewrites this rewritten URL further and recursively replaces each slash in the second part of the URL-path with an underscore. The N
(next
) flag forces the rewrite engine to loop until all the slashes are replaced (at which point the rule fails to match and processing continues). Note that in this case the rewrite engine effectively starts over, so the order of directives is important.
The 20
in N=20
(requires Apache 2.4.8+) is a fail-safe and represents, in this scenario, an upper limit for the number of slashes that might need to be replaced. The N
flag can be a bit tricky - if done incorrectly (with no option to fail) it can quickly run out of control and literally bring Apache to a grinding halt (before crashing). By default, it will fail after 32,000 iterations - but that is often too much for a server to handle!
Rewriting continues to:
/my/service._content/home_page.html?opath=/content/home/page&appId=myapp
to:
/my/service._content_home_page.html?opath=/content/home/page&appId=myapp
Depending on whether /my/service._content_home_page.html
represents a physical filesystem path or virtual path that is further rewritten, you may still have issues with path-info, so you might need the DPI
(Discard Path Info) flag on the second rule.
UPDATE: ...help me understand in this rule, how does the replace of forward slash to underscore happen RewriteRule ^(/my/service\._.*)/(.*\.html)$ $1_$2
This rule only replaces one slash at once. It is called repeatedly to replace all slashes in the URL-path.
Note that the RewriteRule
pattern (ie. ^(/my/service\._.*)/(.*\.html)$
) only matches against the URL-path, so we can ignore the query string for now. (The query string is automatically appended later.)
The regex ^(/my/service\._.*)/(.*\.html)$
is broken down as follows:
(/my/service\._.*)
- this captures the URL-path up to (but not including) the last slash in the URL-path. The pattern .*
is "greedy", so it matches up to the last slash, not the first. This is saved in the $1
backreference. eg. Given the URL-path /my/service._content/home/page.html
(after the first rewrite), this matches /my/service._content/home
and saves this in $1
.
/
- this simply matches a slash (and effectively throws it away).
(.*\.html)
- this captures the remaining URL-path after (but not including) the last slash and saves it in the $2
backreference. eg. Given the URL-path /my/service._content/home/page.html
(after the first rewrite), this matches page.html
and saves this in $2
.
The URL is then internally rewritten to $1_$2
- the contents of the $1
and $2
backreferences (as mentioned above) joined together with an underscore (where a slash once was). For example, from the above example, this results in the URL-path /my/service._content/home
+ _
+ page.html
, ie. /my/service._content/home_page.html
.
The N
flag causes the rewritten URL to be immediately passed back to the rewrite engine for further processing - to replace the remaining slashes.
/content/home/page
always in the same format? ie. 3 path segments:/path1/path2/path3
(slash prefix, no-slash suffix)? Or what are the restrictions here?http://example.com/content/home/page
.