پیش از هرچیز به خوانندگان محترم عرض می نمایم که این مقاله تنها به منظور آشنایی شما با یکی از قدرتمندترین و کاراترین ماژولهای آپاچی به پدید آمده و برای کسب اطلاعات دقیقتر به منابع این سرور قدرتمند مراجعه نمائید.
مرجعی که من انتخاب کردم همون راهنمای خوبمون Apache Manual هست که اگه دوست داشتین می تونین بهش مراجعه کنین تکنیک کاری مونم ارائه مشکل و راه حل اینطوری بهترم هست، پیش از اینکه وارد بحث بشیم می خوام بهتون بگم که اصلا این قضیه مد ریرایت چی هست و به چه کاری میاد باید عرض کنم یکی از خفن ترین ماژولهای آپاچی همین مد ریرایت از هر نظر خفن این ماژول به شما این امکان رو میده که URL رو مطابق میلتون پردازش کنین و به هرشکلی که دوست دارین نمایش بدین بگفته خدایان امر این مدریرایت حکم چاقوی سویسی رو داره به هرشکل شاید ظاهر قضیه ساده باشه اما به حق یکی از پیچیده ترین یا شاید پیچیده ترین ماژول آپاچی همین مد ریرایت حالا با هم قدم به قدم میریم جلو:
منتها قبل از اینکه شروع کنیم اینو بهتون بگم ممکن سختی این مقوله اونقدر باشه که شما کاملا قضیه رو رها کنین اما تکنیکی که اینجا در پیش گرفته شده شما رو با ده ها راه حل روبرو می کنه که چنان جذب موضوع می شین که دیگه هیچ وقت این سختی شما رو عذاب نده و قضیه رو رها نکنین:
پیش از هر چیز شما باید درک کنید که آپاچی کی یک درخواست HTTP رو پردازش می کنه ببینید وقتی یک درخواست به آپاچی میرسه آپاچی در دو مرحله اونو بررسی میکنه اول آپاچی این قضیه رو بررسی می کنه که به یک سرور مجازی ارسال شده یا نه و پس از اون موتورهای بازنویس آپاچی اقدام به پردازش دستور دهنده ها از فایلهای پیکربندی اصلی می کنن که به وسیله اون دستورهاURL رو بازنویسی کنن چند گام جلوتر آپاچی آدرس را پیش می رود تا به شاخه ای که در خواست شده برسد و به دنبال فایلهای پیکربندی شاخه ای می گردد(.httaccess)که بوسیله اون مجددا (برای بار دوم) اقدام به بازنویسی یو آر ال میکنه در هر دو گام آپاچی با بهره گیری از فرامین مشخص شده اقدام به بازنویسی یو آر ال میکنه بیشتر از این قضیه رو باز نمی کنم چون واقعا خسته کننده میشه اما حالا می خواهیم کمی در مورد اون دستور دهنده ها بدونیم که چی هستن ببینید اون دستور دهنده ها در حقیقت یک سری عبارات با قاعده اند که تحت عنوان قوانین بازنویسی (RewriteRule) در فایلهای پیکربندی ذخیره می شن حتما می دونید عبارات باقاعده چی هستن دیگه، اگر نمی دونین هیچ خیالی نیست سه سوت بهتون می گم صد البته برای توضیحات بیشتر مراجعه کنید به منابع و کتب اما:
اول اینکه عبارات با قاعده (Regular Expression) برای این بکار می روند که ببینیم آیا یک رشته با یک الگوی مشخص مطابقت میکنه یا نه و اینکه یک الگوی خاص رو در یک رشته جستجو کنیم و نهایتا یک الگوی مشخص رو از یک رشته بیرون بیاریم حالا می گم چه جوری میشه به این اهداف دست یافت ببینیند یه سری دستور زبان وجود داره که تو عبارات باقاعده از اونها استفاده می کنیم که بطور خلاصه می گم
-این عبارت با قاعده با هر رشته حاوی “abc” مطابقت می کند “abc”
-عبارات با قاعده می توانند شاخه دار باشند “|” این شاخه ها مثل OR عمل می کنن یعنی “abc|xyz” یعنی هر رشته حاوی “abc” یا “xyz” مطابقت می کند
-براکت ها برای محدود سازی استفاده می شوند یعنی “[abc]” باهر رشته حاوی یک یا تمام کاراکترهای “a” یا “b” یا “c” مطابقت می کند
-برای خلاصه سازی از – استفاده می کنیم پس “[۰-۹]” با ارقام مطابقت می کند صفر تا نه تک تک یا چند تا یا همه خلاصه اینکه صفر تا نه ضمن اینکه داخل براکت هم هست
-اگر خواستین از – در عبارت با قاعده خود استفاده کنین از ‘- استفاده کنین
-برای مستثنی کردن یک ست از کاراکترها از ^ استفاده می کنیم که داخل براکت است یعنی “^abc” با همه کاراکترها بجز کاراکترهای “a” و “b” و یا “c” مطابقت می کند
-علامت “x+” با هر رشته حاوی حداقل یک “x” مطابقت می کند و علامت “x*” با هررشته حاوی صفر یا تعدا بیشتر “x” و علامت “x?” با هررشته حاوی صفر یا یک “x” مطابقت می کند
-کروشه ها تعداد توالی یک کاراکتر را به طور مشخص تعین می کند یعنی “xy{4}” با هر رشته حاوی یک “x” که بعد آن دقیقا چهار “y” آمده است مطابقت می کند و “xy{4,6}” تعداد “y”بین چهار تا شش و اگر عدد دوم (اینجا شش) ذکر نشود حداقل چهار ولی ماکزیممی ندارد
-پرانتزها برای تکرار توالی استفاده می شوند مثلا “x(yz)*” با یک رشته حاوی یک “x” و تعداد صفر یا نامحدود “yz” مطابقت می کند
-”.”با هر کاراکتری مطابقت می کند
-”^” با ابتدای رشته مطابقت می کند “^ab” رشته ای که ابتدای آن “ab” باشد توجه کنید اینجا دیگر داخل براکت نیست
-”$” مانند بالا اما این یکی با انتهای رشته مطابقت می کند
اگر از هریک از این کاراکترها خواستید به عنوان کاراکترهای معمولی استفاده کنید براحتی”\$” استفاده کنید یعنی یک اسلش قبلش بگذارید
خوب حالا شما هم تا حدودی با عبارات با قاعده آشنا شدید(من نمی دونم این خارجیها وقتی می خوان اسم انتخاب کنن حتما قبلش باید اب هویج بخورن آخه اینا چیش با قاعده هرچی قاعده تو دستور زبان هست به هم ریخته هنوز براتون هیچی نگفتم خودش به تنهایی یک کتاب داره این عبارات با قاعده ولی خوب لازمه حتما یاد بگیرینش بدردتون می خوره)
خوب حالا براتون یه عالمه مشکل رو با راه حل مثال می زنم اینجوری خیلی سریع می فهمین که چی به چیه و اگر مشکل شما در این مجموعه نباشه خودتون می تونین با استفاده از اینها راه حلش رو پیدا کنین فقط چون تعدادشون زیاده من اونها رو در دو سطح مقدماتی و پیشرفته تقسیم می کنم و مقدماتی هارو در این مقاله قرار می دم و قسمت پیشرفته را در مقاله ای جداگانه تقدیم می کنم:
قبل از هرچیز شما باید از نصب صحیح ماژول مدریرایت در آپاچیتون مطمئین بشید بدنبال
کد:
#LoadModule rewrite_module modules/mod_rewrite.so
در فایل پیکربندی اصلی آپاچی باشید و آنرا از حالت توضیح خارج کنید و آپاچی را ری استارت کنید
خوب حالا همه چیز محیاست فکر کنید که می خواهید با استفاده از GET چیزی مثل
کد:
myapp.php?target=showproducts&categoryid=123&listlimit=30
را به صفحه myapp ارسال کنیم و بعد از متغیرهای ارسال شده در یک کوری استفاده کنیم حالا فرض کنید یک کاربر ناقلای فوضول بیاد و URL رو به این شکل
کد:
myapp.php?target=showproducts&categoryid=youarebeinghacked&listlimit=30
تغییر بده خوب صفحه myapp حیوونی از همه چیز بی خبری تلپی همه چیز رو میگذاره تو کوری و واویلا یا مثلا تصور بفرمائین که شما فایلهای گوناگونی رو در یک شاخه دارین که با استفاده از یک برنامه URL رو پردازش میکنین (منظور همون GET) و کاربر رو به صفحه درخواستی میفرستین مثلا
خوب حالا فکر کنین این کاربر طفلی از این صفحات خوشش اومده و دوست داشته که اونها رو در لیست علاقه مندی هاش (Favorite) ذخیره کنه فکر می کنین می تونه بفهمه چی به چیه و کدوم آدرس ماله کدوم صفحه خوب حالا ما میایم و سلوشن میدیم البته ما که نه آپاچی میده
اون چیزهایی که ما باید در فایل های پیکربندی ذخیره کنیم فعلا فقط دو چیز
کد:
RewriteEngine on
RewriteRule Pattern Substitution [Flag(s)]
خط اول موتورهای بازنویس آپاچی رو استارت میکنه و خط دوم همون خطی که ما باید با استفاده از عبارات باقاعده به آپاچی بگیم که باید الگوی مشخص شده با عبارات باقاعده را (که بجای عبارت Pattern قرار می گیرد) با جانشینش (Substitution) جایگزین کنه حالا با هم چند مثال ساده می بینیم:
ما می خواهیم هروقت کاربر یا خود سایت چنین URL
را به سمت سرور ارسال کرد این URL به شکل
کد:
http://localhost/siteengine/products.php?id=34676
تغییر کنه تا با استفاده از اون صفحه products.php متغیر id را در اختیار بگیره این کار را به راحتی با استفاده از
کد:
RewriteRule /products/([0-9]+) /siteengine/products.php?id=$1
انجام می دهیم سعی کنید خودتون بفهمید عبارات با قاعده چه چیزهایی را الگو می کنن
خوب حالا همین مثال رو یه نموره میتابونیم می خواهیم آدرسی مشابه
کد:
http://somesite.hu/products/24334,d,3,2
را به صورت
کد:
http://localhost/siteengine/marso/content.php?id=24334&sort=d&order=3&start=2
بازنویسی کنیم خوب برای این کار ما از قانون زیر به سادگی استفاده می کنیم
کد:
RewriteRule ^/products/([0-9]+),([ad]*),([0-9]{0,3}),([0-9]*),([0-9]*$) /marso/content.php?id=$1&sort=$2&order=$3&start=$4
همون طوری که مشاهده می کنین کارها به سادگی قابل فهمند و چیزه پیچیده ای در کار نیست نکته ای رو که تا اینجا چیزی ازش نگفتم مساله [Flag(s)] بوده فکر می کنین چرا تابحال چیزی از اونها نگفتم ؟ خوب معلومه چون یادم رفت بگم که تو پرانتز اینجا بهتون می گم شما با استفاده از فلگها می تونین هدرهای خاصی رو به مرورگرها ارسال کنین مثلا اگر به جای [Flag(s)] قرار دهید [NC] یا [nocase] همونطور که متوجه شدین باعث میشود که Pattern به صورت case-insensitive در بیاد و فلگهای دیگر که توضیحات بیشتر در این باره را به مقاله تکمیلی موکول می کنم
اما این همه مدریرایت نبود مدریرایت انعطاف پذیرتر میشود و بازهم دست شما را برای بازنویسی URL بازتر می کند
کد:
RewriteCond Something_to_test Condition
بله این همون چیزیه که الان می خوام بهتون بگم دستور بازنویس RewriteCond اقدام به تست کردن آدرسی می کند که در جای Something_to_test قرار می گیر این رشته می تواند یک رشته ساده باشد یا یک عبارت باقاعده موتورهای بازنویس آپاچی اقدام به کنترل این رشته می کند اگر این رشته یا عبارت باقاعده با URL متچ شود موتور بازنویس اقدام به بازنویسی قاعده زیرین می کند وگرنه به دنبال ریرایت کاندیشن های دیگر می گردد و اگر ریرایت کاندیشن دیگری وجود نداشت به اجرای ریرایت رولهای باقی مانده می پردازد اما ما نیاز به یک سری مواد اولیه داریم تا بفهمیم که این ریرایت کاندیشن چقدر بدرد بخوره بجای عبارت Something_to_string می تونیم از موارد زیر بهره بگیریم
HTTP header variables: HTTP_USER_AGENT, HTTP_REFERER, HTTP_COOKIE, HTTP_FORWARDED,HTTP_HOST, HTTP_PROXY_CONNECTION, HTTP_ACCEPT
Connection & request variables: REMOTE_ADDR, REMOTE_HOST, REMOTE_USER, REMOTE_IDENT,REQUEST_METHOD, SCRIPT_FILENAME, PATH_INFO, QUERY_STRING, AUTH_TYPE
Server internal variables: DOCUMENT_ROOT, SERVER_ADMIN, SERVER_NAME, SERVER_ADDR,SERVER_PORT, SERVER_PROTOCOL, SERVER_SOFTWARE
System variables: TIME_YEAR, TIME_MON, TIME_DAY, TIME_HOUR, TIME_MIN, TIME_SEC,TIME_WDAY, TIME
mod_rewrite special values: API_VERSION, THE_REQUEST, REQUEST_URI, REQUEST_FILENAME,IS_SUBREQ
حتما با اکثر این موارد آشنائید و می توانید حدس بزنید که هریک چه کاری انجام می دن در یک مثال حسابمان را با ایم ریرایت کاندیشن تصویه می کنیم
کد:
RewriteCond %{HTTP_USER_AGENT} ^Mozilla .*
RewriteRule ^/$ /homepage.max.html [L]
RewriteCond %{HTTP_USER_AGENT} ^Lynx.*
RewriteRule ^/$ /homepage.min.html [L]
RewriteRule ^/$ /homepage.std.html [L]
[code/]
فکر می کنم اگر بیشتر توضیح بدم حرصتان در می آید همه چیز واضح است خط اول مرورگر کاربر را چک می کند که اگر با Mozilla شروع شده باشد مدریرایت زیرین استارت شده و کاربر به صفحه homepage.max.html ارجاع داده می شود و گرنه ریرایت کاندیشن دوم چک می شود که این نیز مانند قبلی نام مرورگر را کنترل می کند و مدریرایت اخر که برای باقی مرورگرها در نظر گرفته شده یا به عنوان مثال آخر شما با استفاده از خطوط زیر می توانید دسترسی کاربران را به تصاویر با پسوند gif یا jpg از خارج سایتتان را ببندید
[code]
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://localhost/.*$ [OR,NC]
RewriteCond %{HTTP_REFERER} !^http://mysite.com/.*$ [OR,NC]
RewriteCond %{HTTP_REFERER} !^http://www.mysite.com/.*$ [OR,NC]
RewriteRule .*\.(gif |GIF|jpg |JPG)$ http://mysite/images/bad.gif [L,R]
خوب حالا گام بعد را بر میداریم که آخرین گام ما در این مقاله است فکر کنید که شما ده ها صفحه دارید یا هزاران برنامه فکر نمی کنم هیچ انسان (البته با IQ بالاتر از ۹۰) پیدا شود که بنشیند و تمامی این فایلها و برنامه ها و صفحات را در فایلهای پیکر بندی آپاچی ذخیره و ریرایت رول برایشان تعریف کند اما به واقع چاره چیست آیا اصلا چاره هست چه جوری می شه این مشکل رو حل کرد و بقول یکی از دوستان سلوووووووشن چیه؟؟؟؟
فرض می کنیم که شما یه دیتابیس دارین با هزار برنامه که آدرس اون برنامه ها درون دیتابیس با یک آی دی ذخیره شده شاید بگین خوب ما اون هزارتا فایل رو داریم اما دیتا بیس رو نه منم می گم یه برنامه با پی اچ پی بنویس که این کار رو برات انجام بده خوب حالا فکر می کنم که شما اون دیتابیس رو دارین منظورم از دیتابیس در اینجا یه فایل مثلا categoryids.txt که اطلاعات رو داخلش اینجوری ذخیره کردیم
NetTools 3
NetTools/Messengers 34
.
.
.
[code/]
خوب حالا این موارد را به فایل پیکربندی اصلی آپاچی اضافه می کنیم تا با شروع به کار کردن آپاچی این اطلاعات نیز لود بشن
[CODE]
کد:
RewriteMap categories txt:/path/to/file/categoryids.txt
RewriteRule ^(.*)$ open.php?categoryid=${categories:$1|0}
همونطور که مشاهده میشه فرامان جدیدی به میدان اومده بله ریرایت مپ که خود نیز ده ها امکان جالب به ما می دهد فکر می کنم سازوکار این دوخط هم کاملا واضح خط اول که فایل بانک اطلاعاتی ما رو لود میکنه و فایل دوم اون رو با استفاده از نام موجود در URL به آی دی موجود در فایل متچ می کنه و اگر درست شد آی دی در جای مذکور قرار می گیرد بطور مثال یک URL برایتان در اینجا قرار می دهم
http://www.mysite.com/NetTools/Messengers
[code/]
که با خط زیر بازنویسی میشه
[code]
http://www.mysite.com/open.php?categoryid=34
[code/]
مثلا می توانید با استفاده از آن کاربران را به آینه(mirror) خود بفرستید و بسیاری امکانات جالب دیگر که شاید خیلی از امکانات هنوز کشف و مورد استفاده قرار نگرفته باشن و در انتها برای شما چند مثال کوتاه و کارا نوشتم که می تونین از اونها استفاده کنین و با کمی خلاقیت چیزهای جالبتری خلق کنین به کاراکترهایی که آندرلاین شدن توجه کنین
[code]
http://www.mysite.com/1/2/3/details
=> content.php?category=1&subcat1=2&subcat2=3
http://www.mysite.com/bookshop/browse/bytitle
=> library.php?target=listbooks&order=title
http://www.mysite.com/bookshop/browse/byauthor
=> library.php?target=listbooks&order=author
http://www.mysite.com/bookshop/product/123
=> library.php?target=showproduct&itemid=123
http://www.mysite.com/bookshop/helpdesk/2
=> library.php?target=showhelp&page=2
http://www.mysite.com/bookshop/registration
=> library.php?target=reg
بیشتر مثالهای این نوشته از مقاله
mod_rewrite: A Beginner's Guide to URL Rewriting
By Tamas Turcsanyi
اقتباص گرفته شده است و روال بیان مطلب نیز بر اساس همین مقاله بوده است