در توسینسو تدریس کنید

و

با دانش خود درآمد کسب کنید

آموزش URL Rewrite در آپاچی قسمت 2

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

الگو (عبارات باقاعده):

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

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

. نماینده وجود یک کاراکتر دلخواه است برای مثال 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]
  • برای یادگیری ، ساخت و تست عبارات باقاعده ابزار انلاین بسیار خوبی در این لینک وجود دارد.

پرچم ها

پرچم ها برای این منظور در انتهای قوانین بازنویسی اضافه می شوند که به آپاچی بگویند که چگونه قانون را تفسیر و مدیریت کند. برای مثال به آپاچی می گویند با قانون مورد نظر به صورت 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)

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

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

# 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

o HTTPUSERAGENT

o HTTP_REFERER

o HTTP_COOKIE

o HTTP_FORWARDED

o HTTP_HOST

o HTTPPROXYCONNECTION

o HTTP_ACCEPT

• Connection Variables

o REMOTE_ADDR

o REMOTE_HOST

o REMOTE_USER

o REMOTE_IDENT

o REQUEST_METHOD

o SCRIPT_FILENAME

o PATH_INFO

o QUERY_STRING

o AUTH_TYPE

• Server Variables

o DOCUMENT_ROOT

o SERVER_ADMIN

o SERVER_NAME

o SERVER_ADDR

o SERVER_PORT

o SERVER_PROTOCOL

o SERVER_SOFTWARE

• Dates and Times

o TIME_YEAR

o TIME_MON

o TIME_DAY

o TIME_HOUR

o TIME_MIN

o TIME_SEC

o TIME_WDAY

o TIME

• Special Items

o API_VERSION

o THE_REQUEST

o REQUEST_URI

o REQUEST_FILENAME

o 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 قبلی با شرایط و انطباق الگو مطابق بوده و در نتیجه اجرا شده است و احتمالا به دلیل وجود پرچم 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 رقمی باشد که بعید به نظر می آید.

در پایان شایان ذکر است که این مقاله درواقع ترجمه بنده از مقاله اصلی است

نویسنده : Prober

منبع : جزیره لینوکس و سیستم های متن باز وب سایت توسینسو

هرگونه نشر و کپی برداری بدون ذکر منبع و نام نویسنده دارای اشکال اخلاقی است

#شرطهای_بازنویسی_url #ماژول_mod_rewriting #دستورات_آپاچی #بازنویسی_url_صفحات_وب
عنوان
1 آموزش URL Rewrite در آپاچی قسمت 1 رایگان
2 آموزش URL Rewrite در آپاچی قسمت 2 رایگان
زمان و قیمت کل 0″ 0
3 نظر
پارسا یوسفی

بسیار مفید و عالی بود

این مقاله رو با کمی تغییر به نام regex هم میتونین منتشر کنین :)

prober

ممنون منظورتون رو متوجه نمیشم

پارسا یوسفی

Regular Expression

https://httpd.apache.org/docs/current/rewrite/intro.html
نظر شما
برای ارسال نظر باید وارد شوید.
از سرتاسر توسینسو
تنظیمات حریم خصوصی
تائید صرفنظر
×

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