Mod Rewrite path issues

2019-03-22 02:14发布

问题:

I have successfully created rewrite rules to handle URLs like

http://example.com/xyz

http://example.com/xyz/

http://example.com/xyz/abc

http://example.com/xyz/abc/

Here is the mod rewrite & regex:

Options +FollowSymlinks
RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^/?([0-9]+)(?:\/)?$ /index.php?p=$1 [L]
RewriteRule ^/?([-a-zA-Z0-9_+]+)(?:\/)?$ /index.php?n=$1 [L]
RewriteRule ^/?([-a-zA-Z0-9_+]+)/([-a-zA-Z0-9_+]+)(?:\/)?$ /index.php?n=$2 [L]

This works great, but the problem is that when I go to http://example.com/xyz/abc, my script gets the correct input (n=abc) but the paths are messed up, so all relative URLs in my code are broken, as they are now relative to xyz instead of the root.

Is there a way around this at all? As you can see above I have tried to redirect to /index.php to force the path to be correct. My brain is fried after a long day of regex and code, so I hope it's not something disastrously trivial.

回答1:

The three options are:

1) Use a base tag (this will affect every relative URI on your page, including links, images, scripts, stylesheets and so on)

<base href="http://yoursite/">

2) Change all of your links to fully qualified URIs

<a href="http://yoursite/yourpage.html">

3) Use the "/" prefix to show that the path is relative to the root on each URI.

<a href="/yourpage.html">

I have personally used the base-tag option the most, which does get some bad press (from people that have used it without really understanding it). When it comes to mod_rewrite, the base tag is perfect as you probably DO want all your paths to be relative to the root, including all your images, css, scripts and links.



回答2:

Use the HTML base element to force all relative URLs to use a different path than the one the browser displays.

<base href="http://www.example.com/"/>
...
<a href="relative/url">link</a>

The relative URL will use "http://www.example.com" as its base, even if the browser thinks it's looking at the page "http://www.example.com/xyz/". So the link goes to "http://www.example.com/relative/url" instead of "http://www.example.com/xyz/relative/url"

And there's the Stack Overflow way of doing it, in which every URL is either an absolute path (to resources like images) or paths including the root (i.e. "/feeds/questions/123"), which avoid the relative path issues.



回答3:

Edit: I assume you are talking about URLs in your HTML code, e.g. to images and stylesheets, that are broken.

Nope, as far as I know there is no way around it, because the browser sees a path, and requests resources relative to it. It has nothing to do with the server, and there is nothing you can do.

You will either have to resort to a different splitter that is not interpreted as a directory splitter (e.g. underscores), or use absolute paths, or use the <base> tag. I have never used the base tag myself, however, and it is not very well regarded wherever you look. The best thing would probably be to switch to absolute paths.



回答4:

modify your last RewriteRule to include the path. you have the path in the regular expression.

RewriteRule ^/?([-a-zA-Z0-9_+]+)/([-a-zA-Z0-9_+]+)(?:\/)?$ $1/index.php?n=$2 [L]

or alternatively (depending on what you are trying to achieve):

RewriteRule ^/?([-a-zA-Z0-9_+]+)/([-a-zA-Z0-9_+]+)(?:\/)?$ /index.php?n=$1/$2 [L]


回答5:

I tried using the BASE element in my pages as a shortcut instead of changing all urls. Add the base element as follows:

<base href="/">

And here are the results:

This:    <link type="text/css" rel="stylesheet" href="my.css">
Becomes: <link type="text/css" rel="stylesheet" href="/my.css">

This:    <script type="text/javascript" language="javascript" src="include/my.js"></script>
Becomes: <script type="text/javascript" language="javascript" src="/include/my.js"></script>

This:    <a href="foo.html">
Becomes: <a href="/foo.html">

This:    <a href="foo/bar.html">
Becomes: <a href="/foo/bar.html">

You can always override the base tag where necessary:

This:    <a href="/foo">
Remains: <a href="/foo">

This:    <a href="/foo/bar/">
Remains: <a href="/foo/bar/">