آموزش URL Rewrite در آپاچی به زبان ساده

اغلب سایت های پویا در آدرس های URL صفحات سایت خود متغیرهایی دارند که برای سایت مشخص می کند که چه اطلاعاتی را برای کاربر به نمایش بگذارند. برای مثال ، نمونه URL زیر به اسکریپت مربوطه در سمت سرور می گوید که اطلاعات محصول شماره 7 را نمایش بدهد.

دوره های شبکه، برنامه نویسی، مجازی سازی، امنیت، نفوذ و ... با برترین های ایران
http://www.pets.com/show_a_product.php?product_id=7

مشکلات ساختار این نوع از url ها این است که اصلا در ذهن نمی مانند، خواندن این نوع url ها از پشت تلفن کار سختی هست (شگفت زده میشین اگه بدونین این روش انتقال url خیلی رایج هست). موتورهای جستجو و همچنین کاربران، از روی این نوع URL ها اطلاعات مفیدی راجع به محتوای صفحه بدست نمی آورند.

URL Rewriting چیست؟

با فرض اینکه این آدرس URL آدرس صفحه وبی باشد که برای خرید طوطی نروژی آبی رنگ هست اما آدرس URL اصلا این را از خود بروز نمی دهد. اگرچه این نوع ادرس دهی یک فرمت استاندارد و منصفانه میان تمامی صفحات وب هست اما می توان ان را معنایی تر ساخت.حال آدرس URL بالا را با آدرس URL زیر با هم قایسه کنید:

http://www.pets.com/products/7/

واضح است که URL دوم خیلی کوتاهتر ، خواناتر و مرتب تر شده است. اما بازهم محتوای واقعی صفحه را از روی URL نمی توان تشخیص داد. و همینطور موتورهای جستجو نیز نمی توانند محتوای صفحه را از روی URL تشخیص دهند. اما خوب ما هنوز هم می توانیم رویایی تر فکر کنیم. URL زیر را ببینید:

http://www.pets.com/parrots/norwegian-blue/

حالا با آدرس URL بالا حتی می توانید دقیقا بگوئید که به دنبال چه محتوایی در صفحه وب هستید. موتورهای جستجو می توانند واژه های درون URL را بر اساس علامت dash (-) به کار رفته از هم تفکیک کنند و بنابراین برای تشخیص بهتر محتوای صفحات وب از آن ها استفاده کنند. و همینطور این نوع URL به راحتی قابل به ذهن سپاری است و قابل انتقال به فرد دیگر است.

اما متاسفانه آدرس URL اخیر به راحتی قابل درک برای سرور وب نیست و ما باید با یک سری کارها که آن را بازنویسی URL (URL Rewriting) می نامیم برای سرور قابل فهم کنیم. در واقع با تکنیک URL Rewriting ما آدرس URL را برای درک سرور ترجمه می کنیم.

پلتفرم ها و ابزارهای URL Rewrite در آپاچی

بسته به نرم افزاری که روی سرور شما در حال اجرا است دسترسی شما به ماژول بازنویسی URL (URL Rewriting) می تواند باز باشد. اگر اینطور نیست خیلی ساده می توانید با تماس با شرکت میزبان وب خود این خواسته را در میان گذاشته تا دسترسی شما فعال شود.آپاچی ساده ترین سیستمی هست که اجرای URL Rewriting در آن فعال است. و معمولا با فعال شدن ماژول درون ساخته خودش به نام mod__Rewrite بازنویسی URL را امکان پذیر می کند.

و کار با ماژول mod__Rewrite به سادگی ویرایش و بارگذاری یک فایل متنی text است.و اما IIS، که نرم افزار سرور مایکروسافت است، قابلیت URL rewriting را به عنوان یک استاندارد در درون خودش ندارد اما add-onهایی برای آن وجود دارد که این عملکرد را برای آن فعال می کند. ISAPI__Rewrite که کار با آن توصیه می شود. مثال هایی که ما در ادامه به آن می پردازیم مبتنی بر ماژول mod__rewrite سرور آپاچی هست.

بازنویسی URL ساده چگونه انجام می شود؟

برای شروع یک مثال ساده را در نظر می گیریم. در این مثال ما یک اسکریپت ساده php داریم که تنها یک صفحه وب را سرویس دهی می کند. URL این صفحه وب به صورت زیر است:

http://www.pets.com/pet_care_info_07_07_2008.php

ما می خواهیم URL صفحه وب ما واضح ترو خواناتر باشد و در ایده آل ترین حالت می خواهیم به صورت زیر باشد:

http://www.pets.com/pet-care/

برای اینکه این اتفاق بیفتد ما باید به نحوی به سرور بگوئیم که همه درخواست هایی که برای URL « pet-care» به سرور ارسال می شود به صورت داخلی به URL « pet_care_info_07_07_2008.php» ری‌دایرکت شود. حتما باید این اتفاق یعنی ری دایرکت شدن به صورت داخلی در سرور انجام شود زیرا ما نمی خواهیم کاربر در آدرس بار مرورگر خود تغییر آدرس را ببیند.

برای تحقق این خواسته ابتدا ما بایستی یک سند متنی با نام «.htaccess» ایجاد کنیم تا دربرگیرنده قوانین بازنویسی باشد. این فایل حتما باید با همان نام باشد (مثلا « .htaccess.txt» و یا « rules.htaccess» نباشد). این فایل باید در دایرکتوری ریشه سایت قرار گیرد (مانند پوشه « pet_care_info_07_07_2008.php » در مثال ما). ممکن هم هست که در حال حاضر همچنین فایلی با نام .htaccess در دایرکتوری مذکور قرار داشته باشد که در این صورت کافی است آن را مطابق آنچه گفته خواهد شد ویرایش نمائید. و حال دستورات زیر را به فایل اضافه کنید:

# Turn on the rewriting engine
RewriteEngine On 
# Handle requests for "pet-care"
RewriteRule ^pet-care/?$ pet_care_info_01_02_2008.php [NC,L] 

دو نکته را به یاد داشته باشید: یکی اینکه هر آنچه که در یک خط بعد از علامت # تایپ شده باشد کامپایلر آپاچی آن را به عنوان کامنت در نظر گرفته و اجرا نمی کند. و دیگر اینکه خط دربرگیرنده RewriteEngine تنها یک بار در هر فایل .htaccess باید بیاید.و اما خط RewriteRule آن اتفاق سحرانگیزی است که باید رخ دهد. این خط به 4 قسمت شکسته می شود:

کلمه کلیدی RewriteRule: این کلمه کلیدی به آپاچی می گوید که باید یک بازنویسی URL انجام دهد.الگوی ^pet-care?$ : این الگو به آپاچی می گوید که هر درخواست URL ای به سمت سرور آپاچی ارسال شد آن را چک کند و ببیند آیا با این الگو منطبق هست یا نه.

و اگر URL درخواستی با الگو منطبق بود سرور آپاچی باید بخش جایگزین شونده دستور (که در زیر معرفی می کنیم) را ، جایگزین URL درخواستی نماید.بخش جایگزین « pet_care_info_01_02_2003.php » : چنانچه URL درخواستی با الگو منطبق بود سرور آپاچی باید این بخش جایگزین شونده را ، جایگزین URL درخواستی نماید و سپس پردازش کند.

پرچم های [NC,L] : این پرچم ها به آپاچی می گویند که قانون بازنویسی را با چه شرایطی اجرا کند. در این مثال ما از 2 پرچم استفاده کردیم. پرچم « NC» که به آپاچی می گوید که قانون را بدون حساسیت روی بزرگی و کوچکی حروف (case-insensitive) اجرا کند. و پرچم «L» که به آپاچی می گوید که چنانچه این قانون شرایط انطباقش احراز شد و در نتیجه اجرا گردید دیگر قوانین بازنویسی بعد از این قانون را اجرا نکند.قانونی که در مثال بالا بررسی کردیم ساده ترین قانون بازنویسی URL و نیز اساس بسیاری از قوانین بازنویسی URL می باشد.

الگوها و جایگزین ها در URL Rewrite

قانون بازنویسی که در بالا برسی کردیم تنها برای ری دایرکت کردن درخواست ها به یک URL کار می کند. اما قدرت واقعی ماژول mod__rewrite زمانی بیشتر خودش را نشان می دهد که بوسیله آن گروهی از URL ها را بر اساس الگوهایی که بر آن منطبق می شوند بازنویسی کنیم.فرض کنید شما می خواهید تمامی URL های سایت خود را در مثالی که در ابتدا آوردیم بازنویسی کنید. در مثال اولیه ما آدرس URL به صورت زیر بود:

http://www.pets.com/show_a_product.php?product_id=7

و ما گفتیم که یک درجه بهتر این است که URL به صورت زیر باشد:

http://www.pets.com/products/7/

و اما حالا می خواهیم کلی تر به قضیه نگاه کنیم و با فرض اینکه آدرس URL تمامی صفحات مربوط به هر یک از محصولات شکل کلی زیر را دارند:

http://www.pets.com/show_a_product.php?product_id={یک عدد}

بر اساس این شکل کلی ما می خواهیم یک قانون بازنویسی URL کلی هم برای تمامی این صفحات بنویسیم. یعنی دوست داریم URL تمامی صفحات مربوط به محصولات مختلف آدرس URL ای به شکل زیر داشته باشند:

http://www.pets.com/products/{یک عدد}/

برای تحقق این امر ما نیازمند استفاده از «عبارات باقاعده» در تعریف الگویی هستیم که در قانون بازنویسی باید درج شود. عبارات باقاعده الگوهایی از رشته ها هستند که در فرمت خاصی نوشته می شوند تا برای سرور آپاچی به طور مناسبی قابل فهم و مدیریت باشند. یک نمونه الگوی نوعی که برای تعریف اعداد استفاده می شود به شکل زیر است:

[0-9]+

در مثال بالا براکت ها دربرگیرنده بازه ای از کاراکترها هستند و «0-9» مشخص می کند که این بازه کاراکتر محدود به ارقام بین 0 تا 9 می شود. علامت + بعد از براکت بسته نیز بیانگر تکرار حق انتخاب بین ارقام 0 تا9 است که براکت آن را مشخص می کند و این تکرار حق انتخاب حداقل یک بار باید رخ دهد.

و بنابراین در کل این الگوی رشته ای مشخص کننده هر عدد دلخواه با هر تعداد رقم است که در URL مد نظر ما به شماره محصول اشاره دارد.توجه: بخش الگوی درون یک قانون بازنویسی به صورت پیش فرض همانند یک عبارت باقاعده رفتار می کند.

# Handle product requests
RewriteRule   ^products/([0-9]+)/?$   show_a_product.php?product_id=$1    [NC,L] 

اولین چیزی که در قانون بالا باید دقت کنید این است که ما قسمت عبارت باقاعده را درون پرانتز قرار دادیم زیر این امر امکان «ارجاع بازگشتی» (back-reference) به آن بخش از الگو را در بخش جایگزین شونده قانون برای ما فراهم می کند. $1 که در بخش جایگزین شونده قانون آمده است به معنای ارجاع به هر آن چیزی است که در اولین پرانتز بخش الگوی قانون آمده است.

شما می توانید قوانینی بنویسید که چندین ارجاع بازگشتی داشته باشند و شماره هر ارجاع بازگشتی براساس ترتیب پرانتزها در الگوی قانون است.و اکنون این قانون اخیر به معنای این است که هر URL درخواستی به شکل domain.com//products//{number}// به URL قابل پردازش توسط سرور به صورت domain.com//show_a_product.php?product_id={same number} ری دایرکت گردد.در ادامه بخش های سازنده یک قانون بازنویسی را بیشتر بررسی خواهیم کرد تا نوشتن و خواندن قوانین بازنویسی ملموس تر و قابل فهم تر گردد. همچنین نحو و کاربرد دستورات پیش شرط قوانین بازنویسی را بیان خواهیم کرد.

عبارت با قاعده یا Regular Expressions چه هستند؟

علائم زیر به سان بلوک های ساختمانی کوچکی هستند برای ساختن عبارات باقاعده و قوانین بازنویسی. قطعا انچه در زیر آمده است یک فرهنگ لغت کامل از عبارات باقاعده نیست اما برای شروع کافی است و به شما کمک می کند تا بتوانید قواعد بازنویسی را بخوانبد و درک کنید و نیز متناسب با نیاز کار خود قوانین بازنویسی لازم را بنویسید.

کاراکتر معنای کاراکتر مثال

  • . نماینده وجود یک کاراکتر دلخواه است برای مثال c.t با رشته های cat، cot، cut منطبق می شود.
  • + به معنای تکرار الگوی قبل از خود به تعداد حداقل یک بار می باشد. برای مثال a+ با رشته های a، aa، aaa و ... منطبق می شود.
  • ** به معنای تکرار الگوی قبل از خود به تعداد حداقل صفر بار می باشد. برای مثال a* با رشته های a، aa، aaa و ... و نیز رشته تهی منطبق می شود.
  • ? به معنای اختیاری بودن حضور یا عدم حضور کاراکتر قبل از خود در عبارت نهایی می باشد. برای مثال colou?r با دو رشته colour و color منطبق می گردد.
  • ^ نماد شروع یک عبارت با یک کاراکتر خاصی است که بعد از آن می آید. برای مثال ^a به هر رشته ای که با کاراکتر a شروع شود منطبق می گردد.
  • $ نماد پایان یافتن یک عبارت با کاراکتر خاصی است که قبل از آن می آید. برای مثال a$ به هر رشته ای که با کاراکتر a خاتمه یابد منطبق می گردد.
  • () قسمتی از الگوی عبارت باقاعده را که درون آن قرار می گیرد یک واحد در نظر می گیرد برای مثال (ab)+ یعنی هر تعداد تکرار (حداقل یک بار) از رشته ab پشت سرهم. مثلا : ab, abab, ababab, ….
  • [] بیانگر یک کلاس کاراکتر است و با یکی از کاراکترهای درون کروشه انطباق رشته محقق می گردد. برای مثال c[uoa]t با رشته های cat، cot، cut منطبق می شود.
  • [^ ] بیانگر نفی یک کلاس کاراکتر است. تاکید بر عدم وجود کاراکترهای بعد از^ درون کروشه در عبارت نهایی دارد. برای مثال c[^]t با رشته c=t منطبق است اما با ct انطباق نمی یابد.
  • ! چنانچه قبل از یک عبارت باقاعده بیاید آن را نفی می کند. برای مثال colo!ur تنها با رشته color منطبق می گردد و تاکید دارد که در رشته حرف u در جایگاه تعیین شده وجود نداشته باشد.

دقت داشته باشید که کاراکترهای فوق ، کاراکترهای خاص هستند و همانطور که در بالا با مثال بیان کردیم هریک کاربرد و معنای خاصی درون یک عبارت باقاعده برعهده دارند. بنابراین باید حواسمان باشد که چنانچه در یک عبارت باقاعده یکی از این کاراکترهای خاص را بخواهیم عینا به عنوان یک کاراکتر از رشته نهایی به کار ببریم باید قبل از آن علامت بک اسلش قرار دهیم وگرنه نقش کاراکتر خاص را بازی خواهد کرد. برای مثال در قانون بازنویسی زیر الگو نه تنها به URL «rss.xml» انطباق دارد بلکه به URLهای «rss1xml» و «rss-xml» و ... نیز انطباق می یابد.

RewriteRule ^rss.xml$ rss.php [NC,L] # Change feed URL

و اگر منظور ما این است که فقط به «rss.xml» انطباق پیدا کند باید ان را به صورت زیر بنویسیم:

RewriteRule ^rss\.xml$ rss.php [NC,L] # Change feed URL

و حالا با استفاده از عبارات باقاعده می توانیم قانون بازنویسی بنویسیم که URL اولیه مثال ما که به صورت زیر بود:

http://www.pets.com/get_product_by_name.php?product_name=norwegian-blue

به صورت URL خواناتر و معنایی تر زیر به کار رود و در سمت سرور به URL قبلی ری دایرکت گردد.

http://www.pets.com/parrots/norwegian-blue/

و آن قانون بازنویسی به صورت زیر خواهد بود:

# Process parrots
RewriteRule arrots/([A-Za-z0-9-]+)/?$ get_product_by_name.php?product_name=$1 [NC,L]

پرچم ها یا Flags در URL Rewrite

پرچم ها برای این منظور در انتهای قوانین بازنویسی اضافه می شوند که به آپاچی بگویند که چگونه قانون را تفسیر و مدیریت کند. برای مثال به آپاچی می گویند با قانون مورد نظر به صورت Case-insensitive (غیر حساس به بزرگی و کوچکی حروف) رفتار کند و یا مثلا می گویند که اگر این قانون اجرا شد پردازش قوانینی که بعد از آن خواهد آمد را متوقف کند و یا بسیاری موارد مختلف دیگر از طریق پرچم ها به آپاچی یادآوری می شود.

این پرچم ها در یک براکت قرار می گیرند و با کاما (,) از هم جدا می شوند. در زیر لیستی از این پرچم ها را به همراه معنای انها ارائه می کنیم. (نیازی به حفظ کردن این پرچم ها نیست و هر زمان می توانید از طریق رجوع به چیت شیت مربوطه لیست این پرچم ها به همراه کاربردشان را ببینید.) البته تصمیم دارم در مقاله بعدی کاربرد پرچم های پرکاربردتر رو همراه با مثال بیان کنم.

C (chained with next rule)
CO=cookie (set specified cookie)
E=var:value (set environment variable var to value)
F (forbidden - sends a 403 header to the user)
G (gone - no longer exists)
H=handler (set handler)
L (last - stop processing rules)
N (next - continue processing rules)
NC (case insensitive)
NE (do not escape special URL characters in output)
NS (ignore this rule if the request is a subrequest)
P (proxy - i.e., apache should grab the remote content specified in the substitution section and return it)
PT (pass through - use when processing URLs with additional handlers, e.g., mod_alias)
R (temporary redirect to new URL)
R=301 (permanent redirect to new URL)
QSA (append query string from request to substituted URL)
S=x (skip next x rules)
T=mime-type (force specified mime type)

جابه جا کردن محتوا در URL Rewrite

دستور بازنویسی زیر را در نظر بگیرید:

# Temporary Move
RewriteRule ^article/?$ http://www.new-domain.com/article/ [R,NC,L] 

افزودن پرچم R در بخش پرچم های یک دستور بازنویسی عملکرد آن را تغییر می دهد. به طوری که با وجود این پرچم ، آپاچی به جای اینکه ریدایرکت سمت سرور به آدرس URL جدید انجام دهد ، یک پیام (http header) به مرورگر سمت کلاینت ارسال می کند مبنی بر اینکه این صفحه موقتا به URL جدید (URL موجود در بخش جایگزین شونده دستور) انتقال یافته است. در بخش جایگزین شونده دستور می تواند یک URL مطلق قرار گیرد و یا یک URL نسبی. هدری که به سمت مرورگر کلاینت برگشت داده می شود حاوی کد 302 است که بیانگر موقتی بودن این انتقال است. و اما حال دستور زیر را در نظر بگیرید:

# Permanent Move
RewriteRule ^article/?$ http://www.new-domain.com/article/ [R=301,NC,L] 

اگر بخواهیم این انتقال به URL جدید دائمی باشد شماره کد 301 به جلوی پرچم R الحاق می گردد تا بدین وسیله آپاچی به مرورگر کلاینت بفهماند که این انتقال دائمی است. برخلاف پیشفرض پرچم R که کد 302 را دارد، پرچم R=301 همچنین به مرورگر می گوید که URL ری دایرکت شده را در آدرس بار خود نمایش دهد.این متد یکی از رایج ترین شیوه های بازنویسی URL برای مواردی است که انتقال محتوا به url جدید بایستی انجام گیرد.

شرط ها (rewrite conditions) در ماژول mod_rewrite

قوانین بازنویسی می توانند با یک یا چند شرط بازنویسی آغاز شوند. که این شرط های بازنویسی پشت سرهم قبل از قانون بازنویسی صف می کشند . شرط های بازنویسی این امکان را در اختیار ما می گذارند تا قوانین بازنویسی مشخصی را برای یک زیرمجموعه خاص از درخواست های کلاینت ها اعمال کنیم. شرطهای بازنویسی با معیارها و ضوابطی بیش از ضوابط محدود کننده URL ها می توانند بازه اجرای قانون بازنویسی را کنترل کنند. برای مثال:

RewriteCond %{HTTP_HOST} ^addedbytes\.com [NC]
RewriteRule ^(.*)$ http://www.addedbytes.com/$1 [L,R=301]

در مثال بالا قانون بازنویسی تمامی URL های درخواستی از سمت کلاینت رو به یک URL مشابه در دامنه www.addedbytes.com نگاشت می دهد و در واقع اگر شرط بازنویسی قبل از این قانون بازنویسی نباشد یک چرخه یا لوپ بی معنا اتفاق می افتد یعنی همه URL ها دوباره به خودشان ترجمه می شوند.

اما با قرار دادن شرط بازنویسی قبل از قانون بازنویسی ، مشخص می شود که هدف ما از بازنویسی چیست و اینکه قانون بازنویسی ما یک قانون بی معنا نخواهد بود چرا که در شرط بازنویسی چک می شود که چنانچه URL درخواستی از سمت کلاینت بدون www در ابتدای URL درخواست شده است آنگاه به سراغ قانون بازنویسی برود.

به این ترتیب قانون بازنویسی در این مثال اینچنین URL هایی را ری دایرکت دائمی (به دلیل استفاده از R=301) می کند به همان URL اما با حضور www . در واقع این شرط و قانون در کنارهم با هدف تصحیح URL های درخواستی ای هستند که با www شروع نمی شوند و آنها را به این ترتیب تصحیح می کنند.

شرط های بازنویسی هم مانند قانون بازنویسی عمل می کنند . کلمه کلیدی RewriteCond به ماژول mod_rewrite آپاچی می گوید که این خط حاوی یک شرط بازنویسی است. پس به ترتیب زمانی که یک قانون بازنویسی می خواهد اجرا شود باید چند مورد چک شود: اول از همه شرط و یا شرطهای بازنویسی موجود قبل از آن قانون بازنویسی و دوم بررسی انطباق URL درخواستی در الگوی قانون بازنویسی و سوم پرچم های قانون بازنویسی.

بخش اول در یک دستور RewriteCond بخشی است که در ان متغیرهای سرور قرار می گیرند . این متغیرها کلمات کلیدی تعریف شده ای هستند که تعیین می کنند که رشته مورد بررسی شرط یعنی بخش دوم دستور RewriteCond روی چه چیز قرار است تست شود.

مثلا می تواند تست روی دامنه های درخواست شده کلاینت ها باشد و یا مورد تست می تواند مرورگر کلاینت باشد و یا URL های ارجاعی (که سبب ایجاد هات لینک می شوند) باشد و یا می توان IP کلاینت ها باشد و خیلی موارد دیگر که بر اساس متغیر سروری که در بخش اول دستور RewriteCond قرار می گیرد متفاوت است. فرمت متغیرهای سرور به طور کلی به صورت زیر است:

%{VARIABLE_NAME}

لیستی از انواع متغیرهای سرور را می توانید در زیر ببینید:

HTTP Headers
HTTPUSERAGENT
HTTP_REFERER
HTTP_COOKIE
HTTP_FORWARDED
HTTP_HOST
HTTPPROXYCONNECTION
HTTP_ACCEPT
Connection Variables
REMOTE_ADDR
REMOTE_HOST
REMOTE_USER
REMOTE_IDENT
REQUEST_METHOD
SCRIPT_FILENAME
PATH_INFO
QUERY_STRING
AUTH_TYPE
Server Variables
DOCUMENT_ROOT
SERVER_ADMIN
SERVER_NAME
SERVER_ADDR
SERVER_PORT
SERVER_PROTOCOL
SERVER_SOFTWARE
Dates and Times
TIME_YEAR
TIME_MON
TIME_DAY
TIME_HOUR
TIME_MIN
TIME_SEC
TIME_WDAY
TIME
Special Items
API_VERSION
THE_REQUEST
REQUEST_URI
REQUEST_FILENAME
IS_SUBREQ

بخش دوم دستور RewriteCond شامل یک الگو است همانند بخش الگو در دستور RewriteRule اما تنها با یک تفاوت‌. اینکه این بخش همیشه یک الگو برای انطباق محسوب نمی شود یعنی در مواقعی که علائم خاص قبل از این بخش بیاید دیگر این بخش به عنوان یک الگو تفسیر نمی شود. این کاراکترهای خاص عبارتند از:

  • < : آیا رشته مورد بررسی کوچکتر از الگو است؟
  • > : آیا رشته مورد بررسی بزرگتر از الگو است؟
  • = : آیا رشته مورد بررسی برابر با الگو است؟
  • -d : آیا رشته مورد بررسی یک دایرکتوری معتبر است؟
  • -f : آیا رشته مورد بررسی یک فایل معتبر است؟
  • -s : آیا رشته مورد بررسی یک فایل معتبر با سایز بیشتر از 0 است؟
  • -l : آیا رشته مورد بررسی یک لینک نمادین (symbolic link) است؟
  • -F : آیا رشته مورد بررسی یک فایل معتبر با امکان دسترسی از طریق زیردرخواست ها (subrequests) هست؟
  • -U : آیا رشته مورد بررسی یک URL معتبر با امکان دسترسی از طریق زیردرخواست ها (subrequests) هست؟

توجه شود که چون این کاراکترهای خاص تفسیر شرط را متفاوت می کنند پس باید توجه داشت چنانچه دقیقا بخواهیم این کاراکترها را به عنوان الگو در بخش دوم دستور RewriteCond به کار ببریم باید حتما قبل از آن علامت \ (بک اسلش) استفاده کنیم.

دستور RewriteCond نیز همانند دستور RewriteRule در انتهای خود می تواند پرچم داشته باشد. اما پرچم های قابل استفاده برای دستور RewriteCond فقط دو تا هستند. یکی پرچم NC که همانند کاربرد همین پرچم در دستور RewriteRule عمل می کند و به آپاچی می گوید که در بررسی انطباق رشته درخواستی با الگو حساسیت نسبت به بزرگی و کوچکی حروف نداشته باشد.

و دیگری پرچم OR هست که وقتی در پایان یک دستور RewriteCond قرار می گیرد آن شرط را با شرط بعدی در دستور RewriteCond بعدی OR می کند. یعنی اگر شرط دستور RewriteCond اول برقرار بود که دیگر نیازی به بررسی شرط دستور بعدی نیست اما اگر شرط برقرار نبود به سراغ دستور RewriteCond بعدی می رود و شرط آن را چک می کند. در حالت پیشفرض دستورات RewriteCond ای که پشت سرهم می آیند با منطق AND باهم جمع می شوند.

رفع تداخل قوانین بازنویسی در URL Rewrite

هر چه یک سایت پیچیده تر باشد مدیریت مجموعه قوانین بازنویسی پیچیده تر خواهد بود. مشکل زمانی پیش می آید که باید تداخل بین قوانین بازنویسی را حل کنیم. این اتفاق زمانی چهره زشت خودش را نشان می دهد که شما یک قانون جدید به انتهای فایل اضافه می کنید اما در عمل کار نمی کند و اثر ان را نمیبینید.

اگر خطا مربوط به نحو دستور جدید نباشد احتمال زیاد به این خاطر است که دستور بازنویسی URL قبلی با شرایط و انطباق الگو مطابق بوده و در نتیجه اجرا شده است و احتمالا به دلیل وجود پرچم L (مخفف Last: مانند break در C عمل می کند) در انتهای آن دستور، دستورات بازنویسی بعدی نادیده گرفته شده اند. مثال زیر را در نظر بگیرید:

# Process product requests
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/?$ get_product_by_name.php?category_name=$1&product_name=$2 [NC,L] 
# Process blog posts
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/?$ get_blog_post_by_title.php?category_name=$1&post_title=$2 [NC,L]

در مثال بالا صفحات مربوط به درخواست های کالا و صفحات مربوط به پست های بلاگ یک سایت، الگوی انطباق یکسانی دارند. اما قانون بازنویسی دوم هیچگاه اعمال نمی شود زیرا هر URL ای که درخواست شود در الگوی قانون بازنویسی اول انطباق می یابد و در نتیجه با پرچم L بازنویسی مجدد URL درخواستی توسط دستورات دیگر متوقف می شود و بنابراین به دستور دوم هرگز نمی رسد.یکی از راهکارهایی که برای حل این تداخل می توان به کار بست این است که یک بخش اضافه برای مشخص شدن نوع درخواست کلاینت به URL اضافه شود. مانند دستورات زیر:

# Process product requests
RewriteRule ^products/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/?$ get_product_by_name.php?category_name=$1&product_name=$2 [NC,L] 
# Process blog posts
RewriteRule ^blog/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/?$ get_blog_post_by_title.php?category_name=$1&post_title=$2 [NC,L] 

یک راه دیگر هم این هست که در یک فایل اسکریپت php همه انواع درخواست ها اعم از درخواست های مربوط به پست های بلاگ و درخواست های مربوط به محصولات را پردازش کنید. شاید از جنبه ای بتوان این روش را بهتر از راه قبلی دانست زیرا با وجود اینکه کمی بار روی سرور را افزایش می دهد و پردازش بیشتری به سرور متحمل می شود اما درعوض URL شسته رفته تری خواهید داشت. با این راهکار ، یک قانون بازنویسی به شکل زیر خواهید داشت:

# Process product and blog requests
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/?$ get_product_or_blog_post.php?category_name=$1&item_name=$2 [NC,L] 

و البته یک راه حل جایگزین قطعی که همیشه باید در نظر بگیرید این است که تاجایی که می توانید الگوی انطباق را دقیقتر بنویسید تا محدوده دقیق تری از رشته های قابل قبول در آن بگنجد. و نیز اینکه در رعایت ترتیب منطقی قانون ها دقت داشته باشید.

برای مثال فرض کنید وبلاگی دارید که دو نوع بایگانی برای پست ها در نظر می گیرد. یک بایگانی بر اساس سال درج ان پست و یک بایگانی بر اساس موضوع. با این فرض اگر دستورات بازنویسی URL را به صورت زیر بنویسید باز دچار همان مشکل تداخل دستورات که در بالا اشاره شد خواهید شد و در نتیجه دستور دوم اجرا نخواهد شد.

# Get archive by topic
RewriteRule ^([A-Za-z0-9-]+)/?$ get_archives_by_topic.php?topic_name=$1 [NC,L] 
# Get archive by year
RewriteRule ^([A-Za-z0-9-]+)/?$ get_archives_by_year.php?year=$1 [NC,L] 

اما مثلا برای این مورد مثال ما می توانیم الگوی انطباق مربوط به سال را سختگیرانه تر کنیم تا بازه انطباق کوچکتر و دقیقتری داشته باشد. قطعا سال یک عدد خواهد بود و شامل کاراکترهای رقم است و هیچگاه حروف در ان نخواهد بود پس الگوی مربوط به صفحات بایگانی بر اساس سال را تغییر می دهیم. دستورات زیر را ببینید:

# Get archive by year
RewriteRule ^([0-9]{4})/?$ get_archives_by_year.php?year=$1 [NC,L] 
# Get archive by topic
RewriteRule ^([A-Za-z0-9-]+)/?$ get_archives_by_topic.php?topic_name=$1 [NC,L] 

با دستورات فوق چنانچه URL درخواستی تنها شامل 4 رقم باشد دستور اول اجرا خواهد شد و در غیر اینصورت دستور دوم اجرا خواهد گردید. در این حالت تنها زمانی تداخل پیش می آید که موضوع یک پست هم یک عدد 4 رقمی باشد که بعید به نظر می آید.


عالیه زاری
عالیه زاری

کارشناسی ارشد مهندسی نرم افزار تجربه پیاده سازی مجازی سازی سرور و دسکتاپ در محیط عملیاتی

نظرات