How To Rewrite URLs with mod_rewrite for Apache on Debian 9

Introduction

Apache's mod_rewrite module lets you rewrite URLs in a cleaner fashion, translating human-readable paths into code-friendly query strings. It also lets you rewrite URLs based on conditions.

An .htaccess file lets you create and apply rewrite rules without accessing server configuration files. By placing the .htaccess file in the root of your web site, you can manage rewrites on a per-site or per-directory basis.

In this tutorial, you'll enable mod_rewrite and use .htaccess files to create a basic URL redirection, and then explore a couple of advanced use cases.

Prerequisites

To follow this tutorial, you will need:

Step 1 — Enabling mod_rewrite

In order for Apache to understand rewrite rules, we first need to activate mod_rewrite. It's already installed, but it's disabled on a default Apache installation. Use the a2enmod command to enable the module:

sudo a2enmod rewrite

This will activate the module or alert you that the module is already enabled. To put these changes into effect, restart Apache:

sudo systemctl restart apache2

mod_rewrite is now fully enabled. In the next step we will set up an .htaccess file that we'll use to define rewrite rules for redirects.

Step 2 — Setting Up .htaccess

An .htaccess file allows us to modify our rewrite rules without accessing server configuration files. For this reason, .htaccess is critical to your web application's security. The period that precedes the filename ensures that the file is hidden.

Note: Any rules that you can put in an .htaccess file can also be put directly into server configuration files. In fact, the official Apache documentation recommends using server configuration files instead of .htaccess thanks to faster processing times.

However, in this simple example, the performance increase will be negligible. Additionally, setting rules in .htaccess is convenient, especially with multiple websites on the same server. It does not require a server restart for changes to take effect or root privileges to edit rules, simplifying maintenance and the process of making changes with an unprivileged account. Popular open-source software like Wordpress and Joomla relies on .htaccess files to make modifications and additional rules on demand.

Before you start using .htaccess files, you'll need to set up and secure a few more settings.

By default, Apache prohibits using an .htaccess file to apply rewrite rules, so first you need to allow changes to the file. Open the default Apache configuration file using nano or your favorite text editor:

sudo nano /etc/apache2/sites-available/000-default.conf

Inside that file, you will find a <VirtualHost *:80> block starting on the first line. Inside of that block, add the following new block so your configuration file looks like the following. Make sure that all blocks are properly indented.

/etc/apache2/sites-available/000-default.conf

<VirtualHost *:80>
    <Directory /var/www/html>
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    . . .
</VirtualHost>

Save and close the file.

Check your configuration:

sudo apache2ctl configtest

If there are no errors, restart Apache to put your changes into effect:

sudo systemctl restart apache2

Now, create an .htaccess file in the web root:

sudo nano /var/www/html/.htaccess

Add this line at the top of the new file to activate the rewrite engine.

/var/www/html/.htaccess

RewriteEngine on

Save the file and exit.

You now have an operational .htaccess file that you can use to govern your web application's routing rules. In the next step, we will create sample website files that we'll use to demonstrate rewrite rules.

Step 3 — Configuring URL Rewrites

Here, we will set up a basic URL rewrite which converts pretty URLs into actual paths to pages. Specifically, we will allow users to access http://your_server_ip/about, and display a page called about.html.

Begin by creating a file named about.html in the web root:

sudo nano /var/www/html/about.html

Copy the following HTML code into the file, then save and close it.

/var/www/html/about.html

<html>
    <head>
        <title>About Us</title>
    </head>
    <body>
        <h1>About Us</h1>
    </body>
</html>

You can access this page at http://your_server_ip/about.html, but notice that if you try to access http://your_server_ip/about, you will see a 404 Not Found error. To access the page using /aboutinstead, we'll create a rewrite rule.

All RewriteRules follow this format:

General RewriteRule structure

RewriteRule pattern substitution [flags]

  • RewriteRule specifies the directive.
  • pattern is a regular expression that matches the desired string from the URL, which is what the viewer types in the browser.
  • substitution is the path to the actual URL, i.e. the path of the file Apache serves.
  • flags are optional parameters that can modify how the rule works.

Let's create our URL rewrite rule. Open up the .htaccess file:

sudo nano /var/www/html/.htaccess

After the first line, add the following RewriteRule and save the file:

/var/www/html/.htaccess

RewriteEngine on
RewriteRule ^about$ about.html [NC]

In this case, ^about$ is the pattern, about.html is the substitution, and [NC] is a flag. Our example uses a few characters with special meaning:

  • ^ indicates the start of the URL, after your_server_ip/.
  • $ indicates the end of the URL.
  • about matches the string "about".
  • about.html is the actual file that the user accesses.
  • [NC] is a flag that makes the rule case insensitive.

You can now access http://your_server_ip/about in your browser. In fact, with the rule shown above, the following URLs will also point to about.html:

  • http://your_server_ip/about, because of the rule definition.
  • http://your_server_ip/About, because the rule is case insensitive.
  • http://your_server_ip/about.html, because the original filename will always work.

However, the following will not work:

  • http://your_server_ip/about/, because the rule explicitly states that there may be nothing after about, since the $ character appears after about.
  • http://your_server_ip/contact, because it won't match the about string in the rule.

You now have an operational .htaccess file with a basic rule that you can modify and extend to your needs. In the following sections, we will show two additional examples of commonly used directives.

Example 1 — Simplifying Query Strings with RewriteRule

Web applications often make use of query strings, which are appended to a URL using a question mark (?) after the address. Separate parameters are delimited using an ampersand (&). Query strings may be used for passing additional data between individual application pages.

For example, a search result page written in PHP may use a URL like http://example.com/results.php?item=shirt&season=summer. In this example, two additional parameters are passed to the imaginary result.php application script: item, with the value shirt, and season with the value summer. The application may use the query string information to build the right page for the visitor.

Apache rewrite rules are often employed to simplify such long and unpleasant links as the example above into friendly URLs that are easier to type and interpret visually. In this example, we would like to simplify the above link to become http://example.com/shirt/summer. The shirt and summer parameter values are still in the address, but without the query string and script name.

Here's one rule to implement this:

Simple substition

RewriteRule ^shirt/summer$ results.php?item=shirt&season=summer [QSA]

The shirt/summer is explicitly matched in the requested address and Apache is told to serve results.php?item=shirt&season=summer instead.

The [QSA] flags are commonly used in rewrite rules. They tell Apache to append any additional query string to the served URL, so if the visitor types http://example.com/shirt/summer?page=2 the server will respond with results.php?item=shirt&season=summer&page=2. Without it, the additional query string would get discarded.

While this method achieves the desired effect, both the item name and season are hardcoded into the rule. This means the rule will not work for any other items, like pants, or seasons, like winter.

To make the rule more generic, we can use regular expressions to match parts of the original address and use those parts in a substitution pattern. The modified rule will then look like this:

Simple substition

RewriteRule ^([A-Za-z0-9]+)/(summer|winter|fall|spring) results.php?item=$1&season=$2 [QSA]

The first regular expression group in parenthesis matches a string containing alphanumeric characters and numbers like shirt or pants and saves the matched fragment as the $1 variable. The second regular expression group in parentheses matches exactly summer, winter, fall, or spring, and similarly saves the matched fragment as $2.

The matched fragments are then used in the resulting URL in item and season variables instead of the hardcoded shirt and summer values we used before.

The above will convert, for example, http://example.com/pants/summer into http://example.com/results.php?item=pants&season=summer. This example is also future proof, allowing multiple items and seasons to be correctly rewritten using a single rule.

Example 2 — Adding Conditions with Logic Using RewriteConds

Rewrite rules are not necessarily always evaluated one by one without any limitations. The RewriteConddirective lets us add conditions to our rewrite rules to control when the rules will be processed. All RewriteConds abide by the following format:

General RewriteCond structure

RewriteCond TestString Condition [Flags]

  • RewriteCond specifies the RewriteCond directive.
  • TestString is the string to test against.
  • Condition is the pattern or condition to match.
  • Flags are optional parameters that may modify the condition and evaluation rules.

If a RewriteCond evaluates to true, the next RewriteRule will be considered. If it doesn't, the rule will be discarded. Multiple RewriteConds may be used one after another, though all must evaluate to true for the next rule to be considered.

As an example, let's assume you would like to redirect all requests to non-existent files or directories on your site back to the home page instead of showing the standard 404 Not Found error page. This can be achieved with following conditions rules:

Redirect all requests to non-existent files and directories to home page

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /

With the above:

  • %{REQUEST_FILENAME} is the string to check. In this case, it's the requested filename, which is a system variable available for every request.
  • -f is a built-in condition which verifies if the requested name exists on disk and is a file. The ! is a negation operator. Combined, !-f evaluates to true only if a specified name does not exist or is not a file.
  • Similarly, !-d evaluates to true only if a specified name does not exist or is not a directory.

The RewriteRule on the final line will come into effect only for requests to non-existent files or directories. The RewriteRule itself is very simple and redirects every request to the / website root.

Conclusion

mod_rewrite lets you create human-readable URLs. In this tutorial, you learned how to use the RewriteRule directive to redirect URLs, including ones with query strings. You also learned how to conditionally redirect URLs using the RewriteCond directive.

If you'd like to learn more about mod_rewrite, take a look at Apache's mod_rewrite Introduction and Apache's official documentation for mod_rewrite.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末雪猪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子柔滔,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嗜诀,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)爆捞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勾拉,“玉大人嵌削,你說我怎么就攤上這事⊥眨” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵肌访,是天一觀的道長找默。 經(jīng)常有香客問我,道長吼驶,這世上最難降的妖魔是什么惩激? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮蟹演,結(jié)果婚禮上风钻,老公的妹妹穿的比我還像新娘。我一直安慰自己酒请,他們只是感情好骡技,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著羞反,像睡著了一般布朦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上昼窗,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天是趴,我揣著相機(jī)與錄音,去河邊找鬼澄惊。 笑死唆途,一個胖子當(dāng)著我的面吹牛富雅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播肛搬,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼没佑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了滚婉?” 一聲冷哼從身側(cè)響起图筹,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎让腹,沒想到半個月后远剩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡骇窍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年瓜晤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片腹纳。...
    茶點(diǎn)故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡痢掠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嘲恍,到底是詐尸還是另有隱情足画,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布佃牛,位于F島的核電站淹辞,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏俘侠。R本人自食惡果不足惜象缀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爷速。 院中可真熱鬧央星,春花似錦、人聲如沸惫东。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凿蒜。三九已至禁谦,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間废封,已是汗流浹背州泊。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留漂洋,地道東北人遥皂。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓力喷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親演训。 傳聞我的和親對象是個殘疾皇子弟孟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • rljs by sennchi Timeline of History Part One The Cognitiv...
    sennchi閱讀 7,294評論 0 10
  • **2014真題Directions:Read the following text. Choose the be...
    又是夜半驚坐起閱讀 9,399評論 0 23
  • “那些‘長大之后就會知道答案’的問題拂募,你現(xiàn)在知道了么?”“知道了少年不知愁滋味窟她,知道了很多東西不是靠長的陈症,而是感受...
    LeoManler閱讀 453評論 0 3
  • 筆者薔漾 _ 她覺得自己可能愛上了一座城,不可自拔震糖。 舊金山的冬季是旅游淡季录肯,尤其是剛剛過完年還不到一周,這里滿街...
    薔漾閱讀 260評論 0 0
  • 十二點(diǎn)起床吃飯 下午追完了一部劇 晚上希望可以睡早點(diǎn) 明天真的不能呆在寢室了吊说。
    渡河西閱讀 143評論 0 0