Http
HTTP The Definitive Guide
توضیحات
جامعترین مرجع موجود درباره پروتکل HTTP که در سال ۲۰۰۲ توسط O’Reilly منتشر شد و نوشته دیوید گورلی و برایان توتی به همراه سه نویسنده دیگر است. کتاب در ۲۱ فصل و ۶۵۶ صفحه، نهتنها HTTP را توضیح میدهد بلکه تمام فناوریهای هستهای وابسته به آن - از مدیریت اتصال TCP، پراکسی و Cache، احراز هویت، HTTPS تا Redirect و Load Balancing - را با دیاگرامهای دقیق پوشش میدهد. این کتاب بیشتر یک «چرا و چطور» است تا یک مرجع header-by-header.
نظر
امتیاز: 08/10به دیگران توصیه میکنم: بلهدوباره میخوانم: بلهایده برجسته: مکانیزم HTTP Connection Management - کتاب بهخوبی نشان میدهد که چرا HTTP/1.1 با Keep-Alive و Pipeline، و چرا HTTP/2 با Multiplexing، هر کدام تلاشی برای حل مشکل «Head-of-Line Blocking» بودند. این درک لایهای از تکامل پروتکل، به مهندس کمک میکند که بهینهسازی performance را نه از روی حفظ بلکه از روی درک انجام دهد.تاثیر در من: وقتی روی API های .NET Core کار میکنم، حالا میدانم دقیقاً چه اتفاقی پشت هر Request میافتد - از TCP handshake تا Cache-Control header؛ این درک عمیقتر در Debug کردن مشکلات شبکه و طراحی درست Middleware ها تأثیر مستقیم داشته.نکات مثبت: کاملترین توضیح HTTP/1.1 که در قالب یک کتاب یافت میشود؛ دیاگرامهای فراوان که مفاهیم انتزاعی پروتکل را ملموس میکنند؛ پوشش عمیق موضوعاتی که اکثر کتابهای دیگر از آنها عبور میکنند مثل Web Robots، Content Negotiation و Internationalizationنکات منفی: HTTP/2 و HTTP/3 را پوشش نمیدهد چون قبل از آنها نوشته شده؛ نمونه کدها به Perl و C نوشته شدهاند که امروز بیربط به نظر میرسند؛ برای کسی که فقط دنبال کار با API های مدرن است، عمق کتاب بیش از نیاز است
مشخصات
نویسنده: دیوید گورلی و برایان توتی (David Gourley & Brian Totty)انتشارات: O’Reillyصفحه مشخصات:
بخشهایی از کتاب
فصل اول - بخش اول: HTTP چیست و چرا اهمیت دارد؟
معرفی و جایگاه HTTP
نویسندگان کتاب با یک ادعای ساده اما قوی شروع میکنند: «HTTP زبان مشترک اینترنت مدرن است.» این جمله را جدی بگیرید. وقتی میگویند «زبان مشترک»، منظورشان این است که تمام Web Browsers، Web Servers و Web Applications - بدون استثنا - برای تبادل اطلاعات روی HTTP تکیه میکنند.
نکتهای که اینجا مهم است و بسیاری از توسعهدهندگان نادیده میگیرند: HTTP یک Application-layer Protocol است. این یعنی HTTP اصلاً نگران جزئیات شبکه نیست - آن جزئیات را به TCP/IP واگذار کرده. این تقسیم مسئولیت (Separation of Concerns) در طراحی HTTP، یکی از تصمیمات معماری بنیادی این پروتکل است.
HTTP بهعنوان یک Multimedia Courier
نویسندگان HTTP را «پیک چندرسانهای اینترنت» مینامند. چرا؟ چون HTTP روزانه میلیاردها فایل از انواع مختلف - تصویر JPEG، صفحه HTML، فایل متنی، فیلم MPEG، فایل صوتی WAV و Java Applet - را با سرعت، راحتی و قابلیت اطمینان جابهجا میکند.
یک ویژگی حیاتی که کتاب روی آن تأکید میکند: HTTP از Reliable Data-Transmission Protocols استفاده میکند. این تضمین میدهد که داده شما در مسیر انتقال خراب یا تغییر نمیکند. برای شما بهعنوان یک توسعهدهنده .NET Core، این یعنی لایه HTTP زیرساخت انتقال را تضمین میکند و شما میتوانید تمام انرژی خود را روی منطق اپلیکیشن متمرکز کنید.
Web Clients و Web Servers
کتاب ساختار اصلی را اینگونه تعریف میکند:
- Web Server (HTTP Server): دادههای اینترنت را نگه میدارد و در پاسخ به درخواستها ارائه میدهد
- Web Client (HTTP Client): درخواستهایی به سمت سرور میفرستد و پاسخ دریافت میکند
- رایجترین Client روزمره: Web Browser (مانند Chrome یا Firefox)
نویسندگان یک مثال عملی میزنند: وقتی آدرس http://www.oreilly.com/index.html را در مرورگر تایپ میکنید، مرورگر یک HTTP Request به سرور www.oreilly.com ارسال میکند. سرور فایل /index.html را پیدا کرده و در قالب یک HTTP Response - به همراه نوع فایل، طول آن و سایر اطلاعات - برمیگرداند.
نکته معماری: Client و Server با هم «اجزای پایهای World Wide Web» را تشکیل میدهند. این یک معماری Client-Server خالص است.
فصل اول - بخش دوم: Resources، MIME Types و URI/URL
Web Resource چیست؟
نویسندگان تعریف دقیقی از Resource ارائه میدهند: «هر منبعی که محتوای وب تولید کند.»
دو نوع Resource وجود دارد:
- Static Resource: فایلهایی که روی فایلسیستم سرور ذخیره شدهاند - HTML، JPEG، Word، PDF، MP4 و هر فرمت دیگری. اینها ثابتاند؛ همیشه همان محتوا را برمیگردانند.
- Dynamic Resource: برنامههایی که محتوا را در لحظه تولید میکنند - بر اساس هویت کاربر، زمان روز، دادههای درخواستشده یا اطلاعات پایگاه داده.
مثالهای Dynamic Resource که کتاب ذکر میکند: تصویر زنده از یک دوربین، سیستم معامله سهام، جستجوی پایگاه داده ملک، یا فروشگاه آنلاین.
نتیجهگیری کتاب: Resource یعنی هر چیزی که منبع محتوا باشد - یک اسپردشیت فروش شرکت، یک Gateway برای جستجوی کتابخانه، یا یک موتور جستجو.
MIME Type - برچسب فرمت داده
از آنجا که اینترنت هزاران نوع داده مختلف دارد، HTTP به یک مکانیزم برچسبگذاری نیاز داشت. اینجاست که MIME Type (Multipurpose Internet Mail Extensions) وارد میشود.
MIME در اصل برای حل مشکل انتقال پیامها بین سیستمهای ایمیل مختلف طراحی شده بود. HTTP این استاندارد را «قرض گرفت» و برای برچسبگذاری محتوای چندرسانهای خود استفاده کرد.
ساختار MIME Type:
1
نوعاصلی/نوعفرعی
| MIME Type | توضیح |
|---|---|
text/html | سند HTML |
text/plain | متن ساده ASCII |
image/jpeg | تصویر JPEG |
image/gif | تصویر GIF |
video/quicktime | فیلم Apple QuickTime |
application/vnd.ms-powerpoint | ارائه PowerPoint |
وقتی Browser یک Object از سرور دریافت میکند، به MIME Type نگاه میکند تا بفهمد چطور آن را نمایش دهد. اکثر مرورگرها صدها نوع محتوا را میشناسند: نمایش تصویر، پارس HTML، پخش صدا از بلندگو، یا راهاندازی Plugin خارجی.
URI - آدرس پستی اینترنت
هر Resource روی سرور یک نام منحصربهفرد دارد که به آن URI (Uniform Resource Identifier) میگویند. نویسندگان URI را به «آدرس پستی اینترنت» تشبیه میکنند - بهطور یکتا یک Resource را در سراسر جهان شناسایی و مکانیابی میکند.
URI دو «طعم» دارد:
URL - مکان دقیق Resource
URL (Uniform Resource Locator) رایجترین شکل URI است. URL مکان دقیق یک Resource را روی یک سرور خاص توصیف میکند.
ساختار استاندارد URL از سه بخش تشکیل شده:
1
2
3
4
http://www.joes-hardware.com/specials/saw-blade.gif
│ │ │
Scheme Server Address Resource Path
(Protocol) (آدرس اینترنتی سرور) (مسیر Resource)
- Scheme: پروتکل دسترسی (معمولاً
http://) - Server Address: آدرس اینترنتی سرور (مثل
www.joes-hardware.com) - Resource Path: مسیر Resource روی سرور (مثل
/specials/saw-blade.gif)
چند مثال از کتاب:
| URL | توضیح |
|---|---|
http://www.oreilly.com/index.html | صفحه اصلی O’Reilly |
http://www.yahoo.com/images/logo.gif | لوگوی Yahoo |
ftp://joe:[email protected]/locking-pliers.gif | فایل تصویر با FTP احراز هویتشده |
URN - هویت مستقل از مکان
URN (Uniform Resource Name) یک نام یکتا برای یک محتوای خاص است - مستقل از اینکه آن Resource الان کجا قرار دارد.
مثال از کتاب:
1
urn:ietf:rfc:2141
این URN سند استاندارد اینترنتی «RFC 2141» را نامگذاری میکند، حتی اگر آن سند به مکان دیگری منتقل شود یا در چندین جا کپی باشد.
وضعیت فعلی URN: هنوز در مرحله آزمایشی است و بهطور گسترده پذیرفته نشده. دلیل اصلی: نیاز به یک زیرساخت پشتیبان برای Resolve کردن مکان Resource دارد که هنوز ایجاد نشده. بنابراین در عمل و در بقیه کتاب، URI و URL بهجای هم استفاده میشوند.
یک نکته معماری مهم
رابطه این مفاهیم را ذهن نگه دارید:
1
2
3
URI (مفهوم کلی شناسه)
├── URL (شناسه بر اساس مکان) ← مورد استفاده فعلی
└── URN (شناسه بر اساس نام) ← هنوز آزمایشی
این تمایز بعداً در فصلهای بعدی کتاب اهمیت پیدا میکند، بهویژه وقتی درباره Caching و Resource Identity صحبت میشود.
فصل اول - بخش سوم: Transactions، Messages و Connections
HTTP Transaction چیست؟
یک HTTP Transaction از دو بخش تشکیل میشود:
- Request Command: از Client به سمت Server ارسال میشود
- Response Result: از Server به سمت Client برمیگردد
این تبادل از طریق بلوکهای فرمتشده داده به نام HTTP Messages انجام میشود.
HTTP Methods - دستوراتی که به سرور میگویند چه کند
هر HTTP Request Message یک Method دارد که به سرور میگوید چه عملیاتی انجام دهد. پنج Method رایج که کتاب معرفی میکند:
| HTTP Method | توضیح |
|---|---|
GET | یک Resource نامدار را از سرور به Client ارسال کن |
PUT | دادههای Client را در یک Resource نامدار روی سرور ذخیره کن |
DELETE | یک Resource نامدار را از سرور حذف کن |
POST | دادههای Client را به یک Gateway Application سرور بفرست |
HEAD | فقط HTTP Header های Response را برای Resource نامدار بفرست |
Status Codes - نتیجه Transaction را گزارش میدهند
هر HTTP Response Message یک Status Code سهرقمی دارد که به Client میگوید درخواست موفق بوده یا نیاز به اقدام دیگری است.
| Status Code | توضیح |
|---|---|
200 OK | سند با موفقیت برگردانده شد |
302 Redirect | به جای دیگری برو تا Resource را بگیری |
404 Not Found | این Resource پیدا نشد |
یک نکته مهم که کتاب تأکید میکند: HTTP علاوه بر Status Code عددی، یک Reason Phrase متنی هم میفرستد - صرفاً برای توصیف. اما تمام پردازشها فقط بر اساس عدد انجام میشوند. به همین دلیل این چهار Response از نظر HTTP کاملاً یکسان هستند:
1
2
3
4
200 OK
200 Document attached
200 Success
200 All's cool, dude
Web Pages - مجموعهای از Resources، نه یک Resource
یک نکته معماری مهم که بسیاری از توسعهدهندگان نادیده میگیرند: یک اپلیکیشن اغلب چندین HTTP Transaction برای انجام یک کار صادر میکند.
وقتی مرورگر یک صفحه وب گرافیکی را بارگذاری میکند:
- ابتدا یک Transaction برای دریافت HTML Skeleton (ساختار صفحه) انجام میدهد
- سپس برای هر تصویر، هر Graphics Pane و هر Java Applet، یک Transaction جداگانه صادر میکند
- این Resource های جاسازیشده حتی ممکن است روی سرورهای مختلف باشند
نتیجه: یک «صفحه وب» در واقع یک مجموعه از Resources است، نه یک Resource واحد.
ساختار HTTP Messages
HTTP Messages رشتههای ساده و Line-Oriented از کاراکترها هستند. چون متن ساده (Plain Text) هستند نه باینری، خواندن و نوشتن آنها برای انسان آسان است.
دو نوع Message وجود دارد:
- Request Message: از Web Client به Web Server
- Response Message: از Server به Client
هر Message از سه بخش تشکیل میشود:
1
2
3
4
5
6
GET /tools.html HTTP/1.0 ← Start Line
User-agent: Mozilla/4.75 ← Header Fields
Host: www.joes-hardware.com ← Header Fields
Accept: text/html, image/gif ← Header Fields
← Blank Line (پایان Headers)
[بدنه اختیاری] ← Body
Start Line
اولین خط Message است. در Request میگوید «چه کاری انجام بده»؛ در Response میگوید «چه اتفاقی افتاد».
Header Fields
صفر یا بیشتر Header Field بعد از Start Line میآیند. هر Header از یک نام و یک مقدار تشکیل شده که با دونقطه (:) از هم جدا میشوند. Headers با یک Blank Line تمام میشوند.
Body
بعد از Blank Line، یک Body اختیاری قرار دارد که میتواند هر نوع دادهای باشد - برخلاف Start Line و Headers که متنی و ساختاریافتهاند، Body میتواند داده باینری دلخواه باشد (تصویر، ویدیو، فایل صوتی، نرمافزار).
Connections - چطور Messages جابهجا میشوند؟
لایهبندی شبکه
HTTP یک Application Layer Protocol است و جزئیات شبکه را به TCP/IP واگذار میکند.
1
2
3
4
5
HTTP ← Application Layer
TCP ← Transport Layer
IP ← Network Layer
Link Interface ← Data Link Layer
Physical Hardware ← Physical Layer
TCP سه تضمین اساسی ارائه میدهد:
- انتقال بدون خطا (Error-free data transportation)
- تحویل مرتب - داده دقیقاً به همان ترتیبی که فرستاده شده میرسد
- جریان داده بدون قطعهبندی - میتواند در هر اندازهای داده ارسال کند
IP Addresses و Port Numbers
قبل از اینکه HTTP Client بتواند پیامی بفرستد، باید یک TCP/IP Connection برقرار کند. برای این کار به دو چیز نیاز دارد:
- IP Address: آدرس سرور (مثل
207.200.83.29) - Port Number: شماره پورت نرمافزار روی سرور
از کجا IP Address و Port Number را پیدا میکند؟ از URL.
1
2
3
http://207.200.83.29:80/index.html ← IP Address صریح + Port صریح
http://www.netscape.com:80/index.html ← Hostname + Port صریح
http://www.netscape.com/index.html ← Hostname + Port پیشفرض (80)
وقتی Port در URL وجود نداشته باشد، مقدار پیشفرض 80 در نظر گرفته میشود. Hostname از طریق DNS (Domain Name Service) به IP Address تبدیل میشود.
مراحل کامل یک HTTP Connection
مراحلی که مرورگر برای نمایش یک صفحه طی میکند:
- استخراج Hostname از URL
- تبدیل Hostname به IP Address از طریق DNS
- استخراج Port Number از URL (یا استفاده از پیشفرض ۸۰)
- برقراری TCP Connection به سرور روی آن پورت
- ارسال HTTP Request Message به سرور
- خواندن HTTP Response Message از سرور
- بستن Connection
فصل اول - بخش چهارم: Protocol Versions و Architectural Components
نسخههای HTTP
کتاب چهار نسخه اصلی HTTP را معرفی میکند که هر کدام مشکلات نسخه قبلی را حل کردند:
HTTP/0.9
اولین نسخه HTTP، مربوط به سال ۱۹۹۱، بسیار ساده و ابتدایی بود. فقط از Method GET پشتیبانی میکرد و هیچ MIME Type، HTTP Header یا Version Number ای نداشت. هدف اولیهاش فقط انتقال داده HTML بود.
HTTP/1.0
اولین نسخهای که بهطور گسترده استفاده شد. در این نسخه Version Number، HTTP Headers، Method های اضافه و پشتیبانی از MIME Type اضافه شدند. این باعث شد HTTP بتواند انواع دادههای مختلف را منتقل کند.
نکته: HTTP/1.0 یک استاندارد رسمی نبود - بیشتر مستندسازی رفتارهای رایجی بود که در عمل استفاده میشدند.
HTTP/1.1
این نسخه اولین استاندارد رسمی HTTP است. روی بهینهسازی Performance، رفع ابهامات معماری و پشتیبانی از ویژگیهای پیشرفتهتر تمرکز کرد. مهمترین چیزی که اضافه کرد Persistent Connections بود - Connection ها دیگر بعد از هر Request بسته نمیشدند.
این نسخه همان چیزی است که بقیه کتاب عمدتاً روی آن تمرکز دارد.
HTTP-NG (HTTP/2)
نسخهای که در زمان نوشتن کتاب هنوز در مرحله طراحی بود. هدفش بهبود چشمگیر Performance از طریق Modular Architecture و Distributed Object بود.
Architectural Components of the Web
تا اینجا فقط درباره Client و Server صحبت کردیم. اما کتاب تأکید میکند که وب از اجزای معماری بیشتری تشکیل شده است.
Proxies
یک Proxy بین Client و Server قرار میگیرد. درخواستهای HTTP از Client را دریافت کرده و آنها را به سرور میفرستد.
Proxy ها اغلب برای امنیت استفاده میشوند - میتوانند همه Traffic را فیلتر کنند. مثلاً در یک محیط کارپوراتیو، Proxy میتواند محتوای خطرناک را شناسایی و مسدود کند قبل از اینکه به Client برسد.
Caches
یک Web Cache یا Caching Proxy نوع خاصی از Proxy است. نسخههای Local از اسناد پرتقاضا را نگه میدارد تا در دفعه بعدی نیازی به دریافت از سرور اصلی نباشد.
مزیت اصلی: کاهش چشمگیر Traffic و Latency. بهجای اینکه هر Client همان محتوا را از سرور دور دریافت کند، Cache نزدیکتر آن را تحویل میدهد.
Gateways
Gateway ها سرورهای خاصی هستند که بهعنوان واسط برای سرورهای دیگر عمل میکنند. اغلب برای تبدیل HTTP Traffic به پروتکل دیگری استفاده میشوند.
یک مثال رایج: HTTP/FTP Gateway - یک Gateway که درخواستهای HTTP را دریافت کرده و فایلها را از طریق FTP Fetch میکند. از دیدگاه Client، این Gateway فقط یک Web Server معمولی به نظر میرسد.
Tunnels
Tunnel ها اتصالات کوری هستند که داده خام را بین دو Connection انتقال میدهند بدون اینکه به محتوا نگاه کنند.
رایجترین کاربرد: انتقال SSL Traffic رمزنگاریشده از طریق یک HTTP Connection - به این ترتیب SSL Traffic میتواند از میان یک HTTP Firewall عبور کند، حتی اگر Firewall محتوا را نفهمد.
Agents
Agent ها Client هایی هستند که بهصورت خودکار و بدون نظارت انسانی درخواستهای HTTP صادر میکنند.
انواع Agent ها:
- Web Browser (آشناترین نوع)
- Web Spider / Web Crawler: وب را برای ایجاد ایندکس موتورهای جستجو میگردند
- Web Robot: وظایف خودکار مختلف انجام میدهند
جمعبندی معماری کلی وب
همه این اجزا در کنار هم یک تصویر کامل میسازند:
1
2
3
4
5
6
7
8
9
10
11
12
13
[Agent/Browser]
│
│ HTTP Request
▼
[Proxy] ──── [Cache]
│
│ HTTP Request (فیلترشده)
▼
[Gateway]
│
│ پروتکل دیگر (FTP، SSL، ...)
▼
[Origin Server]
نویسندگان این فصل را با یک جمله قدرتمند تمام میکنند: «این پایان شروع است.» یعنی همه چیزی که در این فصل گفته شد فقط یک نمای کلی بود - هر کدام از این مفاهیم در فصلهای بعدی با عمق کامل بررسی میشوند.
فصل دوم - بخش اول: URLs و ناوبری در منابع اینترنت
چرا URL اهمیت دارد؟
قبل از URL، دسترسی به منابع اینترنت یک کار پیچیده بود. کاربران باید پروتکلهای مختلف را میدانستند، آدرسهای متفاوت را حفظ میکردند و برای هر سرویس رویکرد متفاوتی داشتند.
URL این مشکل را حل کرد: یک فرمت یکپارچه و استاندارد که به کاربر و نرمافزار میگوید یک Resource کجاست و چطور باید به آن دسترسی داشت. نویسندگان URL را «نقطه شروع ناوبری در اینترنت» مینامند.
ساختار کامل URL Syntax
کتاب ساختار کامل URL را به این شکل تعریف میکند:
1
scheme://user:password@host:port/path;params?query#frag
هر بخش را جداگانه بررسی میکنیم:
Scheme - «چطور دسترسی داشته باشیم»
اولین بخش URL است و پروتکل دسترسی را مشخص میکند. Case-Insensitive است یعنی HTTP و http یکسان هستند. با :// از بقیه URL جدا میشود.
مثال: http، ftp، mailto، rtsp
Host و Port - «کجا برویم»
Host آدرس سرور را مشخص میکند - میتواند Hostname باشد (مثل www.joes-hardware.com) یا IP Address مستقیم (مثل 207.200.83.29).
Port شماره پورت TCP است. اگر حذف شود، مقدار پیشفرض پروتکل استفاده میشود - برای HTTP پیشفرض 80 است.
User و Password - «احراز هویت»
برخی سرورها قبل از دسترسی به داده نیاز به احراز هویت دارند. اگر Username بدون Password نوشته شود، مرورگر Password را درخواست میکند. اگر هیچکدام نباشند، بعضی Client ها Username پیشفرض anonymous را ارسال میکنند.
1
2
3
ftp://joe:[email protected]/locking-pliers.gif
─── ──────
User Password
Path - «چه Resource ای میخواهیم»
مسیر محلی Resource روی سرور است. از / شروع میشود و با / بخشهایش از هم جدا میشوند.
1
/specials/saw-blade.gif
Parameters - «اطلاعات ورودی اضافه»
بعضی پروتکلها به اطلاعات ورودی بیشتری نیاز دارند. Parameters با ; از Path جدا میشوند و میتوانند چندتایی باشند.
1
http://www.joes-hardware.com/hammers;sale=false/index.html;graphics=true
در این مثال دو Parameter داریم:
sale=falseبرای بخشhammersgraphics=trueبرایindex.html
Query String - «فیلتر کردن داده»
برای ارسال پارامترهای Query به Gateway Application ها (مثل پایگاه داده یا موتور جستجو) استفاده میشود. با ? شروع میشود و جفتهای key=value با & از هم جدا میشوند.
1
http://www.joes-hardware.com/inventory-check.cgi?item=12731&color=blue
Fragment - «بخش خاصی از Resource»
برای اشاره به یک بخش یا قسمت خاص از Resource استفاده میشود. با # شروع میشود.
1
http://www.joes-hardware.com/tools.html#drills
نکته مهم معماری: Fragment هرگز به سرور ارسال نمیشود. Browser آن را برای خودش نگه میدارد و بعد از دریافت کل سند، به آن بخش از صفحه Scroll میکند.
URL Shortcuts - میانبرهای URL
کتاب دو نوع Shortcut معرفی میکند که Browser ها از آنها پشتیبانی میکنند:
Relative URLs
بهجای نوشتن آدرس کامل، میتوان آدرس نسبی نوشت. Browser آدرس کامل را با ترکیب Base URL (آدرس صفحه فعلی) و Relative URL میسازد.
مثال: اگر در صفحه http://www.joes-hardware.com/tools.html باشیم:
1
<a href="./hammers.html">Hammers</a>
Browser این را به آدرس کامل تبدیل میکند:
1
http://www.joes-hardware.com/hammers.html
فرآیند تبدیل Relative URL به Absolute URL را Resolving میگویند.
Expandomatic URLs
Browser ها میتوانند URL را بهصورت خودکار کامل کنند - بدون اینکه کاربر آدرس کامل تایپ کند.
دو نوع Auto-Expansion وجود دارد:
- Hostname Expansion: اگر
yahooتایپ کنید، Browser اضافه میکندwww.و.comتاwww.yahoo.comبشود - History Expansion: Browser تاریخچه بازدیدها را چک میکند و URL های مشابه پیشنهاد میدهد
هشدار کتاب: این رفتار Auto-Expansion در Proxy ها میتواند مشکلساز باشد، چون Proxy URL اصلی تایپشده را میبیند نه URL کاملشده را.
فصل دوم - بخش دوم: کاراکترهای خاص و انواع Scheme ها
مشکل کاراکترهای خاص در URL
URL باید روی همه پلتفرمها و پروتکلها قابل استفاده باشد. این یعنی باید هم قابل حمل (Portable) باشد و هم کامل - بتواند هر Resource ای را نامگذاری کند.
این دو هدف با هم در تضاد هستند. چرا؟ چون سیستمهای مختلف کاراکترهای مختلفی را مجاز میدانند. برای حل این مشکل، طراحان URL یک مکانیزم Escape تعریف کردند.
URL Character Set - کاراکترهای مجاز
URL از US-ASCII بهعنوان مجموعه کاراکتر پایه استفاده میکند. دلیلش سادگی و سازگاری با سیستمهای قدیمی است.
کاراکترها در URL به سه دسته تقسیم میشوند:
| دسته | توضیح | مثال | |
|---|---|---|---|
| Unreserved Characters | همیشه مجاز، نیازی به Encode ندارند | A-Z، a-z، 0-9، -، _، .، ~ | |
| Reserved Characters | معنای خاص دارند؛ اگر بهعنوان داده استفاده شوند باید Encode شوند | /، ?، #، :، @، &، = | |
| Unsafe Characters | ممکن است در انتقال تغییر کنند یا حذف شوند | فاصله، <، >، {، }، ` | ` |
Percent Encoding - راهحل کاراکترهای غیرمجاز
هر کاراکتری که در URL مجاز نباشد باید با Percent Encoding کدگذاری شود. فرمت آن ساده است:
1
% + دو رقم هگزادسیمال از کد ASCII کاراکتر
چند مثال رایج:
| کاراکتر | Encoded |
|---|---|
| فاصله (Space) | %20 |
% | %25 |
/ (بهعنوان داده) | %2F |
@ (بهعنوان داده) | %40 |
مثال عملی:
1
http://www.joes-hardware.com/more%20tools.html
این URL در واقع فایلی به نام more tools.html (با فاصله) را درخواست میکند.
نکته مهم برای توسعهدهنده: در .NET Core متد
Uri.EscapeDataString()برای Encode کردن وUri.UnescapeDataString()برای Decode کردن استفاده میشود. هرگز URL را دستی Encode نکنید - جزئیاتی مثل کاراکترهای Reserved که نباید Encode شوند، بهراحتی فراموش میشوند.
انواع Scheme ها
کتاب مهمترین URL Scheme های موجود را معرفی میکند. هر Scheme قوانین و ساختار خاص خودش را دارد:
http - پرکاربردترین Scheme
1
http://host:port/path?query#frag
Port پیشفرض: 80. اگر Port نباشد، همان ۸۰ فرض میشود.
https - نسخه امن HTTP
1
https://host:port/path?query#frag
Port پیشفرض: 443. دقیقاً مثل http است اما از SSL/TLS برای رمزنگاری Connection استفاده میکند.
ftp - File Transfer Protocol
1
ftp://user:password@host:port/path
برای دانلود و آپلود فایل روی FTP Server استفاده میشود. Port پیشفرض: 21.
mailto - ارسال ایمیل
1
mailto:addr-spec
مثال:
1
mailto:[email protected]
این Scheme کمی با بقیه فرق دارد - به یک Resource روی شبکه اشاره نمیکند بلکه یک آدرس ایمیل است.
file - فایل محلی
1
file://host/path
برای دسترسی به فایلهای محلی روی همان دستگاه استفاده میشود. اگر host حذف شود، همان دستگاه محلی فرض میشود:
1
file:///C:/Documents/presentation.ppt
rtsp و rtspu - Streaming Media
1
2
rtsp://host:port/path
rtspu://host:port/path
برای Real Time Streaming Protocol استفاده میشود. rtsp از TCP و rtspu از UDP استفاده میکند.
news - Usenet Newsgroup
1
2
news:newsgroup
news:message-id
برای دسترسی به Usenet Newsgroup ها. یک ویژگی جالب: news URL اطلاعات کافی برای مکانیابی Resource ندارد - نمیگوید از کدام سرور باید خواند.
telnet - دسترسی به سرویسهای تعاملی
1
telnet://user:password@host:port/
برای ارتباط با سرویسهای Interactive روی شبکه استفاده میشود.
آینده URL - از URL به URN
کتاب در پایان این فصل یک مشکل بنیادی URL را مطرح میکند: URL به مکان وابسته است.
اگر یک Resource جابهجا شود، URL قدیمی دیگر کار نمیکند و همه Linkهایی که به آن اشاره میکردند «شکسته» میشوند. این مشکل معروف به Link Rot است.
راهحل پیشنهادی: URN (Uniform Resource Name) - یک نام ثابت برای Resource که مستقل از مکان آن است. با URN میتوان Resource را به هر جایی منتقل کرد بدون اینکه Link های موجود بشکنند.
اما چرا هنوز URN جایگزین URL نشده؟ کتاب دلیل را صریح بیان میکند: برای کار کردن URN به یک Resolution Infrastructure نیاز است - یک سیستم که بتواند نام URN را به مکان فعلی Resource تبدیل کند. ساخت و پیادهسازی چنین زیرساختی در مقیاس اینترنت بسیار پیچیده است.
فصل سوم - بخش اول: ساختار و جریان HTTP Messages
Messages چگونه جریان دارند؟
نویسندگان فصل سوم را با یک استعاره شروع میکنند: HTTP Messages مثل آب در لوله جریان دارند. اصطلاح Inbound و Outbound برای توصیف جهت جریان Message استفاده میشود.
- Inbound: Message به سمت Origin Server حرکت میکند
- Outbound: Message از Origin Server به سمت User Agent (Browser) برمیگردد
یک قانون مهم: همه Messages - چه Request چه Response - Downstream جریان دارند. یعنی همه Message ها از فرستنده به سمت گیرنده حرکت میکنند، صرفنظر از اینکه Request باشند یا Response.
دو نوع Message
HTTP دقیقاً دو نوع Message دارد و نه چیز دیگری:
- Request Message: از Client به Server - درخواست انجام یک عملیات
- Response Message: از Server به Client - نتیجه آن عملیات
ساختار کامل یک Message
هر HTTP Message از سه بخش اصلی تشکیل شده:
1
2
3
4
<start-line> ← یک خط - توصیف Message
<headers> ← صفر یا بیشتر - متادیتا
<blank line> ← یک خط خالی اجباری (CRLF)
<body> ← اختیاری - داده واقعی
ساختار Request Message:
1
2
3
4
5
GET /specials/saw-blade.gif HTTP/1.0 ← Request Line
Host: www.joes-hardware.com ← Header
Accept: image/* ← Header
← Blank Line
← (Body ندارد)
ساختار Response Message:
1
2
3
4
5
HTTP/1.0 200 OK ← Response Line (Status Line)
Content-type: image/gif ← Header
Content-length: 8572 ← Header
← Blank Line
[binary content of image] ← Body
Start Line - اولین خط هر Message
Request Line
در Request Message، Start Line را Request Line مینامند. از سه بخش تشکیل شده که با فاصله از هم جدا میشوند:
1
2
3
Method Request-URL HTTP-Version
│ │ │
GET /tools.html HTTP/1.0
- Method: عملیاتی که سرور باید انجام دهد
- Request-URL: آدرس کامل یا مسیر محلی Resource
- HTTP-Version: نسخه پروتکل که فرستنده از آن استفاده میکند
Status Line (Response Line)
در Response Message، Start Line را Status Line مینامند:
1
2
3
HTTP-Version Status-Code Reason-Phrase
│ │ │
HTTP/1.0 200 OK
- HTTP-Version: نسخهای که سرور پشتیبانی میکند
- Status-Code: عدد سهرقمی نتیجه عملیات
- Reason-Phrase: توضیح متنی Status Code - فقط برای انسان، نه برای ماشین
Headers - متادیتای Message
Header ها اطلاعات اضافی درباره Request یا Response فراهم میکنند. هر Header یک Name-Value Pair است که با : از هم جدا میشوند:
1
2
Content-type: text/html
Content-length: 403
قوانین مهم Header ها:
- هر Header باید در یک خط باشد
- اگر یک Header خط بعدی را نیاز داشت، میتوان با فاصله یا Tab در خط بعدی ادامه داد (به این Folding میگویند)
- Headers با یک Blank Line تمام میشوند
- Header Name ها Case-Insensitive هستند -
Content-Typeوcontent-typeیکساناند
دستهبندی Header ها
کتاب Header ها را به پنج دسته تقسیم میکند:
| دسته | توضیح | مثال |
|---|---|---|
| General Headers | هم در Request هم در Response استفاده میشوند | Date، Connection |
| Request Headers | فقط در Request Message | Host، Accept، User-Agent |
| Response Headers | فقط در Response Message | Server، WWW-Authenticate |
| Entity Headers | اطلاعات درباره Body | Content-Type، Content-Length |
| Extension Headers | Header های سفارشی که در استاندارد نیستند | هر X-Custom-Header |
Body - داده واقعی
Body بخش اختیاری Message است که داده واقعی را حمل میکند.
- Request Body: دادهای که Client به سرور میفرستد - مثل داده فرم در
POST - Response Body: محتوایی که سرور به Client برمیگرداند - HTML، تصویر، JSON و…
یک تفاوت اساسی با Start Line و Headers: Body میتواند داده باینری دلخواه باشد. تصویر، ویدیو، فایل صوتی، نرمافزار - هیچ محدودیتی در نوع داده وجود ندارد.
نکته Performance: اگر Body داده باینری دارد، هرگز نباید آن را بهعنوان متن parse کنید. در .NET Core برای خواندن Body بهصورت Stream از
Request.Bodyاستفاده کنید تا از کپی غیرضروری داده در حافظه جلوگیری شود.
فصل سوم - بخش اول: ساختار HTTP Messages
جریان Messages
کتاب با یک تعریف دقیق شروع میکند: HTTP Message ها بلوکهای پایهای داده هستند که بین HTTP Application ها ردوبدل میشوند.
پیامها در یک جهت مشخص جاری میشوند - نویسندگان عمداً از کلمه «flow» استفاده میکنند:
- Inbound: به سمت Origin Server
- Outbound: از Origin Server به سمت Client (بعد از پردازش)
- Downstream: صرفنظر از Request یا Response، همه پیامها به سمت Downstream جاری میشوند
نکته معماری: Sender همیشه نسبت به Receiver در Upstream قرار دارد. این مفهوم بعداً در فصل Proxies و Caching اهمیت پیدا میکند.
اجزای یک HTTP Message
هر HTTP Message از سه بخش تشکیل میشود:
1
2
3
4
5
GET /specials/saw-blade.gif HTTP/1.0 ← Start Line
Host: www.joes-hardware.com ← Headers
Accept: text/* ← Headers
← Blank Line (CRLF)
Start Line
در Request Message سه چیز مشخص میکند: Method، Request URL و نسخه HTTP.
1
2
3
GET /specials/saw-blade.gif HTTP/1.0
─── ─────────────────────── ────────
Method Request URL Version
در Response Message سه چیز مشخص میکند: نسخه HTTP، Status Code و Reason Phrase.
1
2
3
HTTP/1.0 200 OK
──────── ─── ──
Version Code Reason Phrase
Header Fields
صفر یا بیشتر Header به شکل Name: Value بعد از Start Line میآیند. Headers با یک Blank Line (CRLF خالی) تمام میشوند.
کتاب Headers را به پنج دسته تقسیم میکند:
| دسته | توضیح |
|---|---|
| General Headers | هم در Request و هم در Response استفاده میشوند |
| Request Headers | فقط در Request - اطلاعات بیشتر درباره درخواست |
| Response Headers | فقط در Response - اطلاعات بیشتر درباره پاسخ |
| Entity Headers | اطلاعات درباره Body (طول، نوع محتوا و …) |
| Extension Headers | Header های غیراستاندارد که توسط توسعهدهنده تعریف میشوند |
یک Header میتواند به چند خط تقسیم شود اگر خط بعدی با فاصله یا Tab شروع شود:
1
2
3
4
5
HTTP/1.0 200 OK
Content-Type: image/gif
Content-Length: 8572
Server: Test Server
Version 1.0
Body
بعد از Blank Line قرار میگیرد. میتواند هر نوع دادهای باشد - متن، HTML، تصویر، ویدیو، JSON، XML یا هر فرمت دیگری.
در Request، Body دادهای است که به سرور ارسال میشود (مثلاً دادههای یک Form). در Response، Body محتوای درخواستشده است.
HTTP Methods - جزئیات کامل
GET
رایجترین Method. از سرور میخواهد یک Resource را برگرداند. Body ندارد.
1
2
3
GET /seasonal/index-fall.html HTTP/1.1
Host: www.joes-hardware.com
Accept: *
پاسخ سرور:
1
2
3
4
5
6
7
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 617
<HTML>
<HEAD><TITLE>Joe's Hardware - Autumn</TITLE></HEAD>
...
HEAD
دقیقاً مثل GET است اما سرور فقط Headers را برمیگرداند، نه Body را.
کاربردهای اصلی:
- بررسی وجود یک Resource بدون دانلود محتوا
- بررسی تغییر Resource از آخرین بار (برای Caching)
- بررسی نوع و اندازه محتوا قبل از دانلود
1
2
3
HEAD /seasonal/index-fall.html HTTP/1.1
Host: www.joes-hardware.com
Accept: *
پاسخ سرور (بدون Body):
1
2
3
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 617
PUT
دادههای ارسالشده از Client را روی سرور ذخیره میکند. محتوای Body را در Resource مشخصشده در URL مینویسد.
نکته امنیتی که کتاب تأکید میکند: چون PUT به کاربر اجازه تغییر محتوای سرور را میدهد، بسیاری از Web Server ها آن را Disable میکنند یا نیاز به احراز هویت دارند.
POST
برای ارسال داده به یک Gateway Application (مثل یک Form HTML یا یک API Endpoint) استفاده میشود. داده در Body قرار میگیرد.
1
2
3
4
5
6
POST /inventory-check.cgi HTTP/1.1
Host: www.joes-hardware.com
Content-Type: application/x-www-form-urlencoded
Content-length: 27
product=1&quantity=5&price=150
TRACE
یک Request تشخیصی است. درخواست را از طریق تمام Proxy ها و Gateway های مسیر ردیابی میکند. سرور نهایی تمام Message دریافتشده را عیناً در Body Response برمیگرداند - به این ترتیب Client میتواند ببیند پیامش در مسیر چطور تغییر کرده.
1
2
3
TRACE /product-list.txt HTTP/1.1
Host: www.joes-hardware.com
Accept: text/*
پاسخ سرور:
1
2
3
4
5
6
7
HTTP/1.1 200 OK
Content-Type: message/http
Content-length: 96
TRACE /product-list.txt HTTP/1.1
Host: www.joes-hardware.com
Accept: text/*
محدودیت مهم: TRACE نباید Body داشته باشد.
OPTIONS
میپرسد سرور برای یک Resource خاص از چه Method هایی پشتیبانی میکند.
1
2
3
OPTIONS * HTTP/1.1
Host: www.joes-hardware.com
Accept: *
پاسخ سرور:
1
2
HTTP/1.1 200 OK
Allow: GET, POST, PUT, OPTIONS
DELETE
از سرور میخواهد یک Resource را حذف کند. اما نویسندگان یک نکته مهم را ذکر میکنند: سرور مجاز است این درخواست را نادیده بگیرد. Client نمیتواند مطمئن باشد که حذف واقعاً انجام شده.
فصل سوم - بخش دوم: Status Codes و Headers
Status Codes - دستهبندی کامل
Status Code ها در پنج دسته کلی تقسیم میشوند. رقم اول کد، دسته را مشخص میکند:
| دسته | محدوده | معنا |
|---|---|---|
| Informational | 100-199 | درخواست دریافت شد، پردازش ادامه دارد |
| Success | 200-299 | درخواست با موفقیت دریافت، فهمیده و پذیرفته شد |
| Redirection | 300-399 | برای تکمیل درخواست، اقدام بیشتری لازم است |
| Client Error | 400-499 | درخواست دارای خطای Syntax یا قابل اجرا نیست |
| Server Error | 500-599 | سرور در اجرای یک درخواست معتبر موفق نشد |
دسته 100 - Informational
100 Continue
یک Status Code چالشبرانگیز است. وقتی Client میخواهد یک Request با Body بزرگ ارسال کند، ابتدا یک درخواست اولیه با Header Expect: 100-continue میفرستد تا مطمئن شود سرور آماده دریافت است.
اگر سرور آماده باشد، 100 Continue میفرستد و Client Body را ارسال میکند. اگر سرور آماده نباشد، یک Error Code مناسب میفرستد و Client از ارسال Body جلوگیری میکند - این باعث صرفهجویی در Bandwidth میشود.
دسته 200 - Success
200 OK
رایجترین Response. درخواست موفق بوده. Body شامل Resource درخواستشده است.
201 Created
برای درخواستهای PUT یا POST که یک Resource جدید ایجاد کردند. سرور باید Location Header را با URL Resource جدید ارسال کند.
202 Accepted
درخواست پذیرفته شده اما پردازش هنوز کامل نشده. سرور تضمینی نمیدهد که پردازش حتماً کامل شود.
204 No Content
Response دارای Status Line و Headers است اما Body ندارد. اغلب بعد از یک عملیات موفق که نیازی به برگرداندن داده نیست استفاده میشود.
206 Partial Content
بخشی از یک Resource برگردانده شده. این Status Code مربوط به Range Request هاست - وقتی Client فقط بخشی از یک فایل بزرگ را درخواست میکند. Header های Content-Range و Date الزامی هستند.
دسته 300 - Redirection
301 Moved Permanently
Resource به آدرس جدیدی منتقل شده. سرور آدرس جدید را در Header Location برمیگرداند. Client و هر Proxy باید URL های ذخیرهشده را بهروز کنند.
302 Found
مشابه 301 اما موقتی است. Resource فعلاً در آدرس دیگری است اما در آینده به آدرس اصلی برمیگردد. Client نباید URL ذخیرهشده را تغییر دهد.
303 See Other
به Client میگوید Resource را از URL دیگری با Method GET بگیرد. معمولاً بعد از یک POST استفاده میشود تا از مشکل Double Submit (زدن دوباره دکمه Submit) جلوگیری شود.
304 Not Modified
وقتی Client یک Conditional Request میفرستد (با Header هایی مثل If-Modified-Since)، اگر Resource تغییر نکرده باشد، سرور 304 برمیگرداند بدون Body. Client از نسخه Cacheشده خودش استفاده میکند.
307 Temporary Redirect
مشابه 302 است اما با یک تفاوت مهم: Method و Body درخواست اصلی تغییر نمیکنند. در 302، بعضی Client ها POST را به GET تبدیل میکردند که رفتار اشتباهی بود.
دسته 400 - Client Error
400 Bad Request
Request دارای Syntax اشتباه است یا سرور نمیتواند آن را بفهمد.
401 Unauthorized
درخواست به احراز هویت نیاز دارد. سرور باید Header WWW-Authenticate را با نوع احراز هویت موردنیاز ارسال کند.
403 Forbidden
سرور درخواست را فهمیده اما از اجرای آن امتناع میکند - بدون توضیح دلیل. برخلاف 401، احراز هویت کمکی نمیکند.
404 Not Found
سرور Resource درخواستشده را پیدا نکرد. رایجترین Error Code ای است که کاربران با آن روبهرو میشوند.
405 Method Not Allowed
Method مورداستفاده برای این Resource مجاز نیست. سرور باید در Header Allow لیست Method های مجاز را برگرداند.
408 Request Timeout
Client در زمان مشخصشده Request را کامل نکرد.
409 Conflict
Request با وضعیت فعلی Resource در تضاد است - مثلاً آپلود یک فایل قدیمیتر از نسخه روی سرور.
410 Gone
مشابه 404 اما با یک تفاوت: سرور قطعاً میداند که Resource وجود داشته و برای همیشه حذف شده.
415 Unsupported Media Type
سرور نوع دادهای که Client فرستاده را پشتیبانی نمیکند.
دسته 500 - Server Error
500 Internal Server Error
عمومیترین Server Error. سرور با یک خطای غیرمنتظره مواجه شده.
501 Not Implemented
Client از یک قابلیت یا Method استفاده کرده که سرور از آن پشتیبانی نمیکند.
502 Bad Gateway
یک Proxy یا Gateway پاسخ نامعتبری از سرور بعدی در زنجیره دریافت کرده.
503 Service Unavailable
سرور موقتاً قادر به پاسخگویی نیست - معمولاً به دلیل حجم بالا یا در حال نگهداری (Maintenance). اگر مشخص باشد چه مدت طول میکشد، سرور باید Header Retry-After ارسال کند.
504 Gateway Timeout
مشابه 408 اما برای Proxy یا Gateway - سرور بعدی در زنجیره در زمان مقرر پاسخ نداد.
Headers - جزئیات کامل
General Headers
در هر دو Request و Response استفاده میشوند:
| Header | توضیح |
|---|---|
Connection | نحوه مدیریت Connection بعد از Transaction |
Date | تاریخ و زمان ساخت Message |
MIME-Version | نسخه MIME استفادهشده |
Trailer | مجموعه Header هایی که در Trailer یک Chunked Transfer هستند |
Transfer-Encoding | نوع Encoding که روی Body اعمال شده |
Via | Proxy هایی که Message از آنها عبور کرده |
Cache-Control | دستورالعملهای Caching |
Request Headers
| Header | توضیح |
|---|---|
Client-IP | IP Address کاربر |
From | آدرس ایمیل کاربر |
Host | Hostname و Port سرور مقصد |
Referer | URL صفحهای که لینک فعلی از آن آمده |
UA-CPU | نوع CPU کاربر |
User-Agent | اطلاعات Browser یا Client |
Accept | نوعهای محتوایی که Client میپذیرد |
Accept-Charset | Character Set هایی که Client میپذیرد |
Accept-Encoding | Encoding هایی که Client میپذیرد |
Accept-Language | زبانهایی که Client ترجیح میدهد |
Authorization | داده احراز هویت |
Cookie | Token هایی که سرور قبلاً ارسال کرده |
If-Modified-Since | فقط اگر بعد از این تاریخ تغییر کرده برگردان |
If-None-Match | فقط اگر ETag تغییر کرده برگردان |
Response Headers
| Header | توضیح |
|---|---|
Age | چه مدت است که Response در Cache بوده |
Server | نوع و نسخه نرمافزار سرور |
Allow | Method های مجاز برای این Resource |
Location | URL Redirect برای Redirection |
Set-Cookie | Token ای که سرور میخواهد Client ذخیره کند |
WWW-Authenticate | نوع احراز هویت موردنیاز |
Entity Headers
| Header | توضیح |
|---|---|
Content-Type | نوع MIME محتوای Body |
Content-Length | طول Body به Byte |
Content-Encoding | Encoding اعمالشده روی Body |
Content-Language | زبان محتوای Body |
Content-Location | آدرس جایگزین برای Resource |
Content-MD5 | Checksum MD5 از محتوا برای تأیید صحت |
Content-Range | محدوده Byte های ارسالشده در یک Partial Response |
Last-Modified | آخرین تاریخ تغییر Resource |
Expires | تاریخ انقضای محتوا |
ETag | یک شناسه یکتا برای نسخه فعلی Resource |
فصل چهارم - بخش اول: TCP Connections و Performance
چرا Connection Management مهم است؟
نویسندگان این فصل را با یک ادعای صریح شروع میکنند: اکثر توسعهدهندگان HTTP درک درستی از TCP Connections ندارند. این سوءتفاهم مستقیماً روی Performance اپلیکیشن تأثیر میگذارد.
HTTP پیامهایش را از طریق TCP Connection منتقل میکند. قبل از اینکه بتوان یک HTTP Request فرستاد، باید یک TCP Connection بین Client و Server برقرار شود.
TCP Connection - زیرساخت انتقال HTTP
TCP داده را به صورت جریان پیوستهای از Byte ها منتقل میکند. این Byte ها در قطعاتی به نام Segment بستهبندی میشوند و از طریق IP منتقل میشوند. هر Segment در یک IP Packet قرار میگیرد.
هر IP Packet شامل این اجزاست:
- IP Packet Header: آدرس IP مبدأ و مقصد، اندازه و سایر Flag ها
- TCP Segment Header: شماره Port مبدأ و مقصد، Flag های کنترلی و اطلاعات ترتیب داده
- TCP Data Chunk: بخشی از داده واقعی
TCP Performance - کجا زمان تلف میشود؟
کتاب دقیقاً مشخص میکند که در یک HTTP Transaction زمان صرف چه کارهایی میشود:
1
2
3
4
DNS Lookup → TCP Connection → HTTP Request → Processing → HTTP Response
│ │ │ │ │
~ms تا s Three-Way Header+Body Server Side Header+Body
Handshake ارسال پردازش دریافت
مهمترین تأخیرها:
1. TCP Connection Setup - Three-Way Handshake
قبل از اینکه یک Byte از داده HTTP منتقل شود، باید TCP Handshake انجام شود:
1
2
3
4
5
6
7
8
Client Server
│ │
│──── SYN ──────────────────────▶│ (۱) Client میگوید: «میخواهم وصل شوم»
│ │
│◀─── SYN + ACK ────────────────│ (۲) Server میگوید: «قبول دارم»
│ │
│──── ACK + HTTP Request ───────▶│ (۳) Client تأیید میکند + Request را میفرستد
│ │
این Handshake یک Round-Trip کامل قبل از هر Request اضافه میکند. برای Connection های طولانی این هزینه یکبار پرداخت میشود، اما برای Connection های کوتاه هر بار باید تکرار شود.
2. TCP Slow Start - آغاز کند اتصال
TCP برای جلوگیری از ازدحام شبکه (Congestion) از مکانیزمی به نام Slow Start استفاده میکند. یک Connection جدید نمیتواند فوراً با حداکثر سرعت داده بفرستد - باید ابتدا با سرعت کم شروع کند و به تدریج سرعت را افزایش دهد.
نتیجه عملی: Connection های قدیمی از Connection های جدید سریعتر هستند. یک Connection که مدتی در حال انتقال داده بوده، Slow Start را پشت سر گذاشته و میتواند با سرعت کامل کار کند.
این یکی از دلایل اصلی است که Persistent Connection ها در HTTP/1.1 اضافه شدند.
3. Nagle Algorithm و TCP_NODELAY
TCP یک الگوریتم دارد به نام Nagle Algorithm که Packet های کوچک را با هم ترکیب میکند تا تعداد Packet های شبکه را کاهش دهد.
اما این الگوریتم برای HTTP مشکلساز است چون:
- HTTP Header ها معمولاً کوچک هستند
- Nagle Algorithm آنها را نگه میدارد تا با داده بیشتری ترکیب کند
- این باعث تأخیر میشود
راهحل: فعال کردن TCP_NODELAY که Nagle Algorithm را غیرفعال میکند.
4. TIME_WAIT و Port Exhaustion
وقتی یک TCP Connection بسته میشود، آدرس IP و شماره Port به مدت 2MSL (حدود 2 دقیقه) در حالت TIME_WAIT باقی میمانند.
این برای جلوگیری از تداخل بین Connection های قدیمی و جدید است. اما در سرورهای پرترافیک میتواند منجر به Port Exhaustion شود - کمبود Port در دسترس برای Connection های جدید.
HTTP Connection Handling - مدیریت Connection ها
Connection Header
HTTP یک Header به نام Connection دارد که میتواند سه نوع Token داشته باشد:
- نام یک HTTP Header: آن Header فقط برای این Connection معتبر است و نباید به Downstream فرستاده شود
close: بعد از این Transaction، Connection بسته میشودkeep-alive: میخواهیم Connection را باز نگه داریم (HTTP/1.0)
نکته مهم: هر Proxy که
ConnectionHeader را دریافت میکند باید آن را پردازش و حذف کند قبل از اینکه Message را به جلو بفرستد.
انواع Connection - چهار رویکرد
1. Sequential Connections - سادهترین، کندترین
1
2
3
Connection 1: [Connect][Request][Response][Close]
Connection 2: [Connect][Request][Response][Close]
Connection 3: [Connect]...
برای هر درخواست یک Connection جدید باز میشود. کند است چون هر بار باید Handshake و Slow Start انجام شود.
2. Parallel Connections - چند Connection همزمان
چند HTTP Transaction بهصورت همزمان روی Connection های مختلف انجام میشوند.
1
2
3
4
Connection 1: [Connect][──── Request 1 ────]
Connection 2: [Connect][──── Request 2 ────]
Connection 3: [Connect][──── Request 3 ────]
Connection 4: [Connect][──── Request 4 ────]
مزایا:
- زمان کل کاهش مییابد
- اگر یک Connection کند باشد، بقیه ادامه میدهند
معایب:
- هر Connection به Memory و منابع نیاز دارد
- اگر Bandwidth محدود باشد، Parallel Connection ها با هم رقابت میکنند و ممکن است نتیجه بدتری بدهند
- سرور باید بار Connection های بیشتری را تحمل کند
محدودیت عملی: مرورگرها معمولاً تعداد Parallel Connection ها را به 6-8 محدود میکنند.
3. Persistent Connections - مهمترین بهبود HTTP/1.1
بعد از انجام یک Transaction، Connection باز میماند و برای Request های بعدی استفاده میشود.
1
Connection: [Connect][Request 1][Response 1][Request 2][Response 2][Request 3][Response 3][Close]
مزایا:
- هزینه Handshake فقط یکبار پرداخت میشود
- TCP Slow Start اثر کمتری دارد
- تعداد Connection های باز کمتر است
دو نوع Persistent Connection:
Keep-Alive (HTTP/1.0): باید صریحاً با Header Connection: keep-alive درخواست شود. سرور میتواند این پارامترها را تنظیم کند:
1
2
Connection: keep-alive
Keep-Alive: max=5, timeout=120
max=5: حداکثر ۵ Transaction دیگر روی این Connectiontimeout=120: اگر ۱۲۰ ثانیه بیاستفاده باشد بسته شود
Persistent (HTTP/1.1): در HTTP/1.1 تمام Connection ها بهصورت پیشفرض Persistent هستند. برای بستن Connection باید صریحاً Connection: close فرستاده شود.
4. Pipelined Connections - ارسال چند Request بدون انتظار
Pipelining اجازه میدهد چند Request پشت سر هم فرستاده شوند بدون اینکه منتظر Response بمانیم.
1
2
Client: [Request 1][Request 2][Request 3]───────▶
Server: ◀─────────────────[Response 1][Response 2][Response 3]
محدودیتهای مهم:
- فقط روی Persistent Connection ها کار میکند
- Response ها باید دقیقاً به همان ترتیب Request ها برگردند
- اگر سرور Connection را ببندد، Client باید Request های بیپاسخ را دوباره بفرستد
- فقط برای Idempotent Method ها مناسب است (مثل GET و HEAD، نه POST)
فصل چهارم - بخش دوم: Connection Close و رفتارهای پیچیده TCP
بستن Connection - ساده به نظر میرسد، اما نیست
نویسندگان این بخش را «رازهای Connection Close» مینامند. دلیلش این است که بستن یک TCP Connection ظاهراً ساده است، اما جزئیاتی دارد که میتوانند منجر به از دست رفتن داده شوند.
At Will Close - بستن دلخواه Connection
هر دو طرف Client و Server میتوانند در هر زمانی Connection را ببندند - حتی در وسط یک Transaction. اما کتاب تأکید میکند که این کار باید با احتیاط انجام شود.
سرورها معمولاً Connection را در این موارد میبندند:
- بعد از ارسال آخرین Response
- وقتی Connection برای مدت طولانی بیاستفاده بوده (Idle Timeout)
- وقتی تعداد Transaction های مجاز (
maxدر Keep-Alive) تمام شده
دو نوع TCP Close
TCP دو مکانیزم برای بستن Connection دارد که تفاوت مهمی بین آنهاست:
Full Close
هر دو کانال ارسال و دریافت بسته میشوند.
1
2
3
4
5
Client ──────────────────── Server
│ ◀── FIN ────────────── │ (Server کانال ارسالش را میبندد)
│ ──── ACK ──────────────▶│
│ ──── FIN ──────────────▶│ (Client کانال ارسالش را میبندد)
│ ◀── ACK ─────────────── │
Half Close
فقط یک کانال بسته میشود - معمولاً کانال ارسال (Output).
1
2
3
Client ──── Half Close Output ───▶ Server
│ (من دیگر نمیفرستم) │
│ ◀─── داده هنوز میتواند بیاد ────│
Half Close در HTTP اهمیت دارد چون به یک طرف اجازه میدهد بگوید «من کارم تمام شد» اما هنوز آماده دریافت داده باشد.
Reset Error - خطرناکترین رفتار
اگر یک طرف دادهای به یک Connection بستهشده بفرستد، طرف مقابل یک TCP Reset برمیگرداند.
مشکل اینجاست: TCP Reset میتواند Buffer های دریافت را پاک کند. این یعنی اگر سرور یک Full Close انجام داده باشد و Client هنوز داده میفرستد، وقتی Reset دریافت میشود، ممکن است دادهای که سرور قبلاً فرستاده و هنوز در Buffer است از بین برود - حتی اگر آن داده کاملاً معتبر بوده باشد.
Graceful Connection Close - روش صحیح بستن
برای جلوگیری از Reset Error، کتاب یک رویه مشخص توصیه میکند:
مراحل Graceful Close:
- Half Close کردن Output: فقط کانال ارسال را ببند
- منتظر ماندن: صبر کن تا طرف مقابل هم Output خودش را ببندد، یا یک Timeout رخ دهد
- Full Close کردن: حالا Connection را کاملاً ببند
1
2
3
4
5
طرفی که میخواهد ببندد:
│── Half Close Output ──▶ (من دیگر داده نمیفرستم)
│◀── دادههای باقیمانده ── (هنوز میخوانم)
│◀── Half Close Output ── (طرف مقابل هم تمام کرد)
│── Full Close ──────────▶ (حالا میتوان کاملاً بست)
نکته عملی: در .NET Core این رفتار از طریق
Socket.Shutdown(SocketShutdown.Send)قبل ازSocket.Close()پیادهسازی میشود.
جمعبندی Performance - راهکارهای عملی
کتاب در پایان فصل یک جمعبندی از راهکارهای بهبود Performance ارائه میدهد:
Parallel Connections
برای صفحاتی با منابع زیاد (تصویر، CSS، JS) مناسب است. اما تعداد زیاد Connection همزمان میتواند روی سرور فشار بیاورد.
مناسب برای: بارگذاری اولیه صفحات وب
Persistent Connections
بهترین راهحل برای اکثر سناریوها. هزینه Handshake و Slow Start را برای چندین Request جبران میکند.
مناسب برای: API Call های متعدد به یک سرور (مثلاً در یک Service مبتنی بر .NET Core که به چند Endpoint مراجعه میکند)
Persistent + Parallel ترکیب
در عمل مرورگرهای مدرن از ترکیب هر دو استفاده میکنند: چند Persistent Connection موازی.
Pipelined Connections
کمترین Latency را دارد اما پیچیدهترین پیادهسازی را هم نیاز دارد. فقط برای Method های Idempotent مناسب است.
یک دیدگاه انتقادی
نویسندگان در پایان فصل صادقانه اعتراف میکنند که مستندات HTTP/1.1 درباره Connection Management ناقص و گاهی متناقض هستند. بسیاری از رفتارهای واقعی در دنیای عملی از طریق آزمون و خطا کشف شدهاند، نه از طریق مستندات رسمی.
این توضیح میدهد که چرا پیادهسازیهای مختلف (Browser ها، Proxy ها، Server ها) گاهی رفتارهای متفاوتی دارند - همه آنها استاندارد را به شکل خود تفسیر کردهاند.
فصل پنجم - بخش اول: Web Servers و معماری داخلی آنها
Web Server چیست؟
نویسندگان از همان ابتدا تمایز مهمی میکشند: Web Server میتواند هم به نرمافزار و هم به سختافزار اشاره داشته باشد.
- نرمافزار: برنامهای که HTTP Request ها را پردازش میکند و HTTP Response برمیگرداند
- سختافزار: دستگاه فیزیکی که این نرمافزار روی آن اجرا میشود
Web Server ها در اشکال و اندازههای مختلف وجود دارند:
- Embedded Web Server: داخل دستگاههایی مثل پرینتر یا Router - بسیار کوچک و محدود
- General-Purpose Web Server: مثل Apache، Nginx، IIS - برای اکثر کاربردها
- E-Commerce Platform Server: بهینهشده برای فروشگاههای آنلاین
- Secure Server: با SSL/TLS داخلی
هفت مرحله پردازش یک Request
کتاب چرخه کامل پردازش یک Request در Web Server را به هفت مرحله تقسیم میکند. این مدل یکی از مهمترین بخشهای فصل است:
1
2
3
4
5
6
7
Step 1: Accept Connection ← اتصال را بپذیر
Step 2: Receive Request ← Request را بخوان
Step 3: Process Request ← Request را پردازش کن
Step 4: Map and Access Resource← منبع را پیدا کن
Step 5: Build Response ← Response بساز
Step 6: Send Response ← Response بفرست
Step 7: Log Transaction ← ثبت کن
مرحله اول: پذیرش Connection
Web Server دائماً روی Port 80 (یا Port دیگری) گوش میدهد. وقتی یک Client اتصال TCP برقرار میکند، چند حالت ممکن است:
حالت عادی: Server اتصال را قبول میکند، IP Client را ثبت میکند و آماده دریافت Request میشود.
Reverse DNS Lookup: Server میتواند IP Address را به Hostname تبدیل کند تا بفهمد از کجا آمده. اما کتاب هشدار میدهد: این کار میتواند کند باشد و Performance را تحت تأثیر قرار دهد. بسیاری از Server های پرترافیک این قابلیت را غیرفعال میکنند.
ident Protocol: یک مکانیزم قدیمی که به Server اجازه میدهد Username کاربر پشت Connection را بپرسد. امروزه به دلایل امنیتی و عدم پشتیبانی Firewall ها تقریباً منسوخ شده.
مرحله دوم: دریافت Request
Server باید Message ورودی را از روی شبکه بخواند. این کار ساده به نظر میرسد، اما چند چالش دارد:
Connection های پرسرعت
Web Server های پرترافیک ممکن است صدها یا هزاران Connection همزمان داشته باشند. برای مدیریت این همزمانی سه معماری رایج وجود دارد:
Single-Threaded: یک Thread به نوبت همه Connection ها را پردازش میکند. ساده اما کند - یک Request کند، همه را کند میکند.
Multi-Process / Multi-Threaded: برای هر Connection یک Process یا Thread جداگانه. ساده اما در تعداد زیاد Connection، مصرف Memory بالا میرود.
Multiplexed I/O: یک Thread چندین Connection را همزمان Observe میکند. فقط وقتی یک Connection آماده داده است، پردازش میشود. این روش در Server های مدرن (مثل Nginx و Node.js) رایج است.
مرحله سوم: پردازش Request
Server باید Request Message را Parse کند:
- Method، URL و نسخه HTTP را از Start Line استخراج کند
- Header های Request را بخواند (هر Header در یک خط، با
:جدا شده) - Body را بخواند (اگر
Content-LengthیاTransfer-Encoding: chunkedباشد)
مرحله چهارم: Map و دسترسی به Resource
این مرحله یکی از پیچیدهترینهاست. Server باید URL را به یک Resource واقعی تبدیل کند.
Docroot - ریشه محتوا
سادهترین نگاشت: URL Path مستقیماً به یک مسیر فایل در Document Root (Docroot) تبدیل میشود.
1
2
3
Request: GET /specials/saw-blade.gif HTTP/1.0
Docroot: /usr/local/httpd/files
Result: /usr/local/httpd/files/specials/saw-blade.gif
نکته امنیتی مهم: اگر یک Path Traversal Attack رخ دهد (
../../etc/passwd)، مهاجم میتواند به فایلهای خارج از Docroot دسترسی پیدا کند. Web Server های خوب این الگوها را شناسایی و رد میکنند.
Virtual Hosting - چند سایت روی یک سرور
یک Web Server میتواند برای چندین وبسایت مختلف روی یک IP Address هاست کند. این کار از طریق HTTP/1.1 Header Host ممکن است:
1
2
3
4
5
6
7
Request به همان سرور:
GET /index.html HTTP/1.1 GET /index.html HTTP/1.1
Host: www.joes-hardware.com Host: www.marys-antiques.com
│ │
▼ ▼
/docs/joe/index.html /docs/mary/index.html
Directory Listing
اگر URL به یک Directory اشاره کند نه یک فایل، Server میتواند:
- یک Index File (مثل
index.html) برگرداند اگر وجود داشته باشد - یک صفحه HTML با لیست محتوای Directory بسازد
- یک 403 Forbidden برگرداند
Dynamic Resource - اجرای برنامه
اگر URL به یک CGI Script یا یک Dynamic Resource اشاره کند، Server برنامه را اجرا میکند و خروجی آن را به Client برمیگرداند.
مرحله پنجم: ساختن Response
بعد از پیدا کردن Resource، Server باید Response Message بسازد:
انتخاب Status Code
- Resource پیدا شد:
200 OK - Resource پیدا نشد:
404 Not Found - Resource جابهجا شده:
301 Moved Permanently - خطای سرور:
500 Internal Server Error
تنظیم MIME Type
Server باید نوع محتوا را مشخص کند. این کار از چند طریق انجام میشود:
- mime.types File: بر اساس پسوند فایل (
.html→text/html،.jpg→image/jpeg) - Magic Typing: بررسی محتوای فایل برای تشخیص نوع آن - دقیقتر اما کندتر
- Explicit Typing: مدیر سرور نوع را صریحاً تنظیم کرده
- Type Negotiation: اگر چند نسخه از یک Resource وجود دارد، سرور بهترین را انتخاب میکند
مرحله ششم: ارسال Response
Server باید Response را از طریق همان TCP Connection برگرداند. برای Persistent Connection ها، Server باید مراقب باشد که Header های صحیح Content-Length را بفرستد تا Client بداند Body کجا تمام میشود.
مرحله هفتم: Logging
آخرین مرحله ثبت Transaction است. Web Server ها معمولاً اطلاعات زیر را ذخیره میکنند:
- IP Address Client
- تاریخ و زمان Request
- URL درخواستشده
- HTTP Method
- Status Code پاسخ
- اندازه Response به Byte
- Referer Header
- User-Agent Header
فصل ششم - بخش اول: Proxies و نقش آنها در وب
Web Intermediary - واسط شبکه
Proxy یک واسط (Intermediary) بین Client و Server است. یک Proxy هم بهعنوان Server (برای Client) و هم بهعنوان Client (برای Server) عمل میکند.
این تعریف ساده، یک معماری قدرتمند میسازد - چون Proxy میتواند هر چیزی که از کنارش رد میشود را بخواند، تغییر دهد یا مسدود کند.
چرا از Proxy استفاده میکنیم؟
کتاب دلایل متعددی برای استفاده از Proxy ذکر میکند:
امنیت (Security)
Proxy میتواند بهعنوان یک Firewall عمل کند. در شبکههای کارپوراتیو، تمام Traffic از Proxy عبور میکند و Proxy میتواند محتوای خطرناک را شناسایی و مسدود کند.
فیلترینگ محتوا (Content Filtering)
مدارس و سازمانها از Proxy برای مسدود کردن سایتهای نامناسب استفاده میکنند. Proxy میتواند بر اساس URL، MIME Type یا محتوا تصمیم بگیرد.
Document Access Control
Proxy میتواند کنترل دسترسی متمرکز ایجاد کند - یک نقطه واحد برای مدیریت دسترسی به منابع مختلف.
Caching
Proxy نسخههای Local از محتوای پرتقاضا را نگه میدارد. وقتی Client همان محتوا را دوباره درخواست میکند، Proxy از Cache پاسخ میدهد بدون اینکه به Origin Server مراجعه کند - این Bandwidth و زمان را کاهش میدهد.
Anonymity
Proxy میتواند HTTP Header هایی مثل From، Referer، Cookie و User-Agent را حذف کند تا هویت Client پنهان بماند.
Transcoding
Proxy میتواند محتوا را تبدیل کند - مثلاً تصاویر را فشردهتر کند برای دستگاههای موبایل، یا محتوای HTML را برای دستگاههای با صفحه کوچک تنظیم کند.
Private vs Shared Proxy
Private Proxy
فقط برای یک Client خاص کار میکند. معمولاً روی همان دستگاه Client نصب میشود.
Shared (Public) Proxy
بین چندین Client مشترک است. Caching Proxy ها معمولاً Shared هستند چون هرچه کاربران بیشتری از یک Cache استفاده کنند، نرخ Cache Hit بالاتر میرود و کارایی بیشتر میشود.
Proxy در مقابل Gateway
کتاب یک تمایز مهم بین Proxy و Gateway میکشد:
| ویژگی | Proxy | Gateway |
|---|---|---|
| پروتکل | هر دو طرف از HTTP استفاده میکنند | دو طرف ممکن است پروتکل متفاوت داشته باشند |
| نقش | واسط بین دو HTTP Client/Server | مترجم بین دو پروتکل مختلف |
| مثال | Caching Proxy، Security Proxy | HTTP/FTP Gateway، HTTP/SSL Gateway |
در عمل این تمایز همیشه تیز نیست - بعضی Proxy ها قابلیتهای Gateway هم دارند.
جایگاه Proxy در شبکه
Proxy ها میتوانند در جاهای مختلفی در مسیر بین Client و Server قرار بگیرند:
Egress Proxy
در خروجی شبکه محلی قرار میگیرد. هدف: کنترل Traffic خروجی از سازمان - فیلترینگ، Logging و امنیت.
1
[کاربران داخلی] ──▶ [Egress Proxy] ──▶ [اینترنت]
Ingress Proxy (Reverse Proxy)
در ورودی سرور قرار میگیرد. از دیدگاه Client مثل یک Web Server واقعی به نظر میرسد. هدف: Load Balancing، Caching و امنیت سرور.
1
[اینترنت] ──▶ [Reverse Proxy] ──▶ [سرورهای داخلی]
Surrogates (Reverse Proxies)
نوع خاصی از Reverse Proxy که جلوی یک یا چند Web Server قرار میگیرد و وانمود میکند که خود سرور است. درخواستها را Cache میکند و فقط در صورت نیاز به سرور اصلی میفرستد.
Network Exchange Proxy
در نقاط اتصال شبکههای بزرگ قرار میگیرد تا Traffic سنگین را مدیریت کند.
تنظیمات Proxy در Client
Client چطور میداند درخواستهایش را به Proxy بفرستد؟ کتاب چهار روش ذکر میکند:
Manual Configuration
کاربر آدرس و Port Proxy را دستی در تنظیمات مرورگر وارد میکند.
Browser Preconfiguration
سازمان مرورگرها را از قبل با تنظیمات Proxy پیکربندی میکند - کاربر نیازی به تنظیم دستی ندارد.
Proxy Auto-Configuration - PAC
یک فایل JavaScript با پسوند .pac که به مرورگر میگوید برای هر URL از کدام Proxy استفاده کند.
1
2
3
4
5
6
function FindProxyForURL(url, host) {
if (host == "www.joes-hardware.com") {
return "PROXY cache.joes-hardware.com:8080";
}
return "DIRECT";
}
Web Proxy Autodiscovery - WPAD
مرورگر بهصورت خودکار فایل PAC را پیدا میکند از طریق DHCP یا DNS - بدون اینکه کاربر آدرسی وارد کند.
رفتار Proxy با HTTP Messages
Request به Proxy
وقتی Client از طریق Proxy کار میکند، URL در Request Message کامل میشود - نه فقط Path:
بدون Proxy:
1
2
GET /specials/saw-blade.gif HTTP/1.0
Host: www.joes-hardware.com
با Proxy:
1
2
GET http://www.joes-hardware.com/specials/saw-blade.gif HTTP/1.0
Host: www.joes-hardware.com
این تفاوت مهم است: Proxy باید بداند به کجا Request را بفرستد، پس URL کامل لازم است.
Via Header - ردیابی مسیر
هر Proxy که یک Message از کنارش رد میشود باید یک Via Header اضافه کند:
1
Via: 1.1 proxy.joes-hardware.com
اگر چند Proxy در مسیر باشند، هر کدام نام خودشان را اضافه میکنند:
1
Via: 1.1 proxy1.joes-hardware.com, 1.1 proxy2.joes-hardware.com
این Header چند کاربرد دارد:
- تشخیص Loop: اگر Proxy نام خودش را در Via دید، یک Loop وجود دارد
- تشخیص Protocol: نسخه HTTP هر Proxy مشخص است
- Debugging: میتوان دید Request از کدام مسیر رفته
TRACE Method و Proxy ها
متد TRACE ابزار عالی برای دیدن مسیر دقیق Request از طریق Proxy هاست. هر Proxy نام خودش را به Via Header اضافه میکند و Server نهایی کل Message دریافتشده را برمیگرداند.
اما یک مشکل وجود دارد: اگر Proxy ها در مسیر حساس باشند (مثلاً یک Proxy محرمانه)، نمیخواهند نامشان فاش شود. برای این حالت HTTP یک Header داریم:
1
Max-Forwards: 2
این Header تعداد Proxy هایی که میتوانند Request را Forward کنند را محدود میکند.
فصل ششم - بخش دوم: Proxy Authentication و Proxy Interoperation
Proxy Authentication - احراز هویت در Proxy
Proxy ها میتوانند دسترسی به محتوا را کنترل کنند. اگر کاربر احراز هویت نشده باشد، Proxy میتواند محتوا را مسدود کند تا کاربر اعتبارنامه ارائه دهد.
چرخه احراز هویت در Proxy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Client Proxy Server
│ │ │
│── GET /resource ────────▶│ │
│ │ │
│◀── 407 Proxy Auth Req ──│ (Proxy میگوید: احراز هویت لازم است)
│ Proxy-Authenticate: │
│ Basic realm="..." │
│ │
│── GET /resource ────────▶│
│ Proxy-Authorization: │
│ Basic [credentials] │
│ │──── Request ───────────▶│
│ │◀─── Response ───────────│
│◀── 200 OK ──────────────│
دو Header کلیدی:
| Header | جهت | توضیح |
|---|---|---|
Proxy-Authenticate | از Proxy به Client | نوع احراز هویت موردنیاز را مشخص میکند |
Proxy-Authorization | از Client به Proxy | اعتبارنامه کاربر را حمل میکند |
تفاوت مهم با Server Authentication: در Server Authentication از
401 Unauthorizedو Header هایWWW-Authenticate/Authorizationاستفاده میشود. در Proxy Authentication از407 Proxy Authentication Requiredو Header هایProxy-Authenticate/Proxy-Authorizationاستفاده میشود. این دو مکانیزم مستقل از هم هستند و میتوانند همزمان فعال باشند.
مشکل Proxy Authentication در زنجیرههای چندگانه
وقتی چند Proxy در مسیر وجود دارد، هر Proxy میتواند احراز هویت مستقل خودش را داشته باشد:
1
Client ──▶ [Proxy 1: نیاز به Auth] ──▶ [Proxy 2: نیاز به Auth] ──▶ Server
Client باید با هر Proxy بهطور جداگانه احراز هویت کند. این میتواند تجربه کاربری پیچیدهای ایجاد کند.
Proxy Interoperation - همکاری Proxy با دیگران
مشکل Header های ناشناخته
یک Proxy ممکن است با Header هایی روبهرو شود که آنها را نمیشناسد. قانون کتاب صریح است:
Proxy باید Header های ناشناخته را بدون تغییر Forward کند.
این قانون برای Extensibility (قابلیت توسعه) HTTP حیاتی است. اگر Proxy ها Header های ناشناخته را حذف کنند، هیچ Header جدیدی نمیتوانست در اینترنت منتشر شود.
Blind Relay - مشکل Keep-Alive
یکی از معروفترین مشکلات Proxy، Blind Relay است. یک Proxy ساده که فقط Byte ها را بدون فهمیدن آنها منتقل میکند میتواند مشکل جدی ایجاد کند:
1
Client ──── Connection: keep-alive ────▶ [Proxy ساده] ──── Connection: keep-alive ────▶ Server
مشکل اینجاست: Proxy این Header را عیناً به Server میفرستد. Server فکر میکند Proxy میخواهد Connection را باز نگه دارد و منتظر میماند. اما Proxy نمیداند این Header چه معنایی دارد و Connection را میبندد.
نتیجه: Server و Proxy در یک Deadlock گیر میکنند - Server منتظر Request بعدی است، Proxy منتظر Response است.
راهحل: Proxy باید Connection Header را پردازش کند و قبل از Forward کردن حذف کند. این یکی از دلایلی است که Proxy نویسی پیچیده است.
Hop-by-Hop Headers - فقط برای یک Connection
برخی Header ها فقط بین دو نقطه مجاور (یک Hop) معنا دارند و نباید در طول زنجیره Forward شوند. به اینها Hop-by-Hop Headers میگویند:
ConnectionKeep-AliveProxy-AuthenticateProxy-AuthorizationTETrailersTransfer-EncodingUpgrade
هر Proxy باید این Header ها را پردازش و سپس حذف کند قبل از اینکه Message را به Hop بعدی بفرستد.
در مقابل، End-to-End Headers باید در تمام طول زنجیره تا Server نهایی حفظ شوند - مثل Content-Type، Authorization و Cache-Control.
SSL و Proxy - مشکل رمزنگاری
یک چالش مهم: وقتی Client از HTTPS استفاده میکند، تمام داده رمزنگاری شده است. Proxy نمیتواند محتوا را بخواند یا تغییر دهد.
راهحل HTTP برای این مشکل: CONNECT Method
1
2
3
4
5
6
7
8
Client ──── CONNECT www.joes-hardware.com:443 HTTP/1.0 ────▶ [Proxy]
(لطفاً یک Tunnel باز کن)
[Proxy] ──── 200 Connection Established ────▶ Client
(Tunnel آماده است)
Client ═══════════ SSL Traffic رمزنگاریشده ══════════════ Server
(Proxy فقط Byte ها را منتقل میکند بدون خواندن)
با CONNECT، Proxy یک TCP Tunnel کور ایجاد میکند. دادههای رمزنگاریشده بدون هیچ تغییری از این Tunnel عبور میکنند.
جمعبندی - چرا Proxy پیچیده است؟
نویسندگان در پایان فصل یک نکته صادقانه مطرح میکنند: پیادهسازی یک Proxy صحیح بسیار سختتر از آن چیزی است که به نظر میرسد. دلایل اصلی:
- باید هم رفتار Client و هم رفتار Server را پیادهسازی کند
- باید Header های Hop-by-Hop را شناسایی و حذف کند
- باید با Client هایی که HTTP/1.0 میفهمند و Client هایی که HTTP/1.1 میفهمند بهدرستی کار کند
- باید مشکلات Blind Relay را مدیریت کند
- باید Loop Detection داشته باشد
فصل هفتم - بخش اول: Caching و مبانی آن
چرا Cache وجود دارد؟
نویسندگان فصل را با چهار مشکل واقعی شبکه شروع میکنند که Cache برای حل آنها طراحی شده:
۱. Redundant Data Transfers - انتقالهای تکراری
اگر صد کاربر مختلف یک صفحه محبوب را باز کنند، همان محتوا صد بار از Server دانلود میشود. این یعنی صد بار همان Bandwidth مصرف میشود و صد بار همان فشار روی Server میآید. Cache این تکرار را حذف میکند.
۲. Bandwidth Bottlenecks - گلوگاه پهنای باند
بسیاری از شبکههای محلی (LAN) پهنای باند بیشتری نسبت به اتصال اینترنتی خود دارند. اگر محتوا در یک Cache محلی باشد، با سرعت LAN تحویل داده میشود نه با سرعت محدودتر اینترنت.
۳. Flash Crowds - ازدحام ناگهانی
گاهی یک رویداد (مثل خبر مهم یا تبلیغ تلویزیونی) باعث میشود تعداد زیادی کاربر همزمان به یک سایت هجوم ببرند. بدون Cache، این ازدحام میتواند Server را از پا دربیاورد. Cache این بار را توزیع میکند.
۴. Distance Delays - تأخیر فاصله
حتی با سرعت نور، ارسال داده از آمریکا به ایران چند صد میلیثانیه طول میکشد. Cache محلی این فاصله فیزیکی را حذف میکند.
Cache Hit و Cache Miss
دو حالت اصلی وجود دارد وقتی Client یک Request میفرستد:
Cache Hit: محتوای درخواستشده در Cache موجود است و مستقیم از Cache تحویل داده میشود - بدون مراجعه به Origin Server.
Cache Miss: محتوا در Cache نیست. Cache باید به Origin Server مراجعه کند، محتوا را بگیرد، در Cache ذخیره کند و به Client تحویل دهد.
Revalidation - بررسی تازگی Cache
حتی اگر محتوا در Cache باشد، ممکن است منقضی شده باشد. Cache میتواند از Origin Server بپرسد آیا محتوا تغییر کرده:
Revalidation Hit: سرور تأیید میکند محتوا تغییر نکرده (304 Not Modified). Cache همان نسخه قبلی را تحویل میدهد - فقط یک Request کوچک رفت و بدون Body برگشت.
Revalidation Miss: سرور میگوید محتوا تغییر کرده (200 OK). Cache نسخه جدید را دریافت، ذخیره و تحویل میدهد.
Object Deleted: سرور میگوید محتوا دیگر وجود ندارد (404 Not Found). Cache نسخه قبلی را حذف میکند.
Hit Rate - نرخ موفقیت Cache
Cache Hit Rate (یا Document Hit Rate) درصد Request هایی است که Cache توانسته بدون مراجعه به Server پاسخ دهد.
اما این معیار کامل نیست. یک فایل ۱۰۰ کیلوبایتی که Miss میشود خیلی بیشتر از ۱۰۰ فایل ۱ کیلوبایتی که Hit میشوند روی شبکه تأثیر میگذارد. به همین دلیل کتاب یک معیار دیگر معرفی میکند:
Byte Hit Rate: درصد Byte هایی که از Cache تأمین شدهاند. این معیار بهتر نشان میدهد Cache چقدر Bandwidth صرفهجویی کرده.
Cache Topologies - چیدمان Cache ها
Private Cache - Cache اختصاصی
فقط برای یک کاربر. مرورگرها یک Cache خصوصی روی دیسک و Memory دارند. سریع و شخصی است اما محتوا فقط برای یک کاربر قابل استفاده است.
Shared (Public) Cache - Cache مشترک
بین چندین کاربر مشترک است. هرچه کاربران بیشتری از یک Cache Proxy استفاده کنند، نرخ Hit بالاتر میرود.
1
2
3
[کاربر ۱] ─┐
[کاربر ۲] ─┤──▶ [Shared Cache Proxy] ──▶ [اینترنت]
[کاربر ۳] ─┘
Cache Hierarchy - سلسلهمراتب Cache
در سازمانهای بزرگ معمولاً چند لایه Cache وجود دارد:
1
2
3
4
5
6
7
8
9
10
[مرورگر کاربر]
│ Miss
▼
[Cache محلی شعبه]
│ Miss
▼
[Cache مرکزی سازمان]
│ Miss
▼
[Origin Server]
هر لایه Cache های لایههای پایینتر را «گرم» نگه میدارد. اگر Cache محلی Miss بخورد، به Cache مرکزی میرود و اگر آن هم Miss بخورد، به Origin Server میرود.
Mesh Networks - شبکه توری Cache
در این معماری پیشرفتهتر، Cache ها میتوانند با هم صحبت کنند - قبل از رفتن به Origin Server، یک Cache از Cache های همسطح خود میپرسد آیا محتوا را دارند.
به این رفتار Cache Peering میگویند و پروتکل ICP (Internet Cache Protocol) برای آن استفاده میشود.
مراحل پردازش Cache
کتاب پردازش هر Request در Cache را به هفت مرحله تقسیم میکند:
1
2
3
4
5
6
7
۱. دریافت Request
۲. Parse کردن URL
۳. جستجو در Cache
۴. بررسی Freshness
۵. ساختن Response
۶. ارسال Response
۷. Logging
مرحله سوم: جستجو در Cache
Cache URL را بهعنوان کلید برای جستجو استفاده میکند. اگر یک نسخه Cacheشده پیدا شد، بررسی Freshness آغاز میشود.
مرحله چهارم: بررسی Freshness
این مرحله پیچیدهترین بخش Caching است. Cache باید تصمیم بگیرد آیا نسخه ذخیرهشده هنوز تازه (Fresh) است یا منقضی (Stale) شده.
Freshness - تازگی محتوا
Document Expiration
Server میتواند صریحاً به Cache بگوید محتوا تا چه زمانی معتبر است. دو Header برای این کار وجود دارد:
Expires Header (HTTP/1.0):
1
Expires: Fri, 05 Jul 2002, 05:00:00 GMT
یک تاریخ و زمان مطلق مشخص میکند. مشکل: بستگی به همگام بودن ساعت Server و Cache دارد.
Cache-Control: max-age Header (HTTP/1.1):
1
Cache-Control: max-age=484200
مدت زمان نسبی به ثانیه مشخص میکند - از لحظهای که محتوا Cache شده. این رویکرد بهتر است چون به همگامسازی ساعت وابسته نیست.
Age محتوا چطور محاسبه میشود؟
Cache باید بداند محتوا چقدر پیر است. این از طریق Header Age انجام میشود:
1
Age: 600
یعنی این Response 600 ثانیه پیش از Origin Server دریافت شده.
فصل هفتم - بخش دوم: Revalidation، Cache-Control و Controlling Cachability
Server Revalidation - بررسی تازگی با سرور
وقتی Cache تشخیص میدهد محتوا ممکن است منقضی شده باشد، باید از Origin Server بپرسد آیا تغییری رخ داده. به این فرآیند Revalidation میگویند.
دو Header برای Revalidation وجود دارد:
If-Modified-Since - بر اساس زمان
1
2
GET /page.html HTTP/1.1
If-Modified-Since: Wed, 22 Nov 2001 18:26:32 GMT
Cache میپرسد: «آیا این فایل بعد از این تاریخ تغییر کرده؟»
- اگر تغییر نکرده: سرور
304 Not Modifiedبرمیگرداند - بدون Body - اگر تغییر کرده: سرور
200 OKبا محتوای جدید برمیگرداند
If-None-Match - بر اساس ETag
گاهی تاریخ کافی نیست. مثلاً:
- یک فایل هر چند ثانیه بازنویسی میشود اما محتوایش تغییر نمیکند
- یک سرور ساعت دقیقی ندارد
- محتوا در کمتر از یک ثانیه تغییر کرده
راهحل: ETag (Entity Tag) - یک شناسه یکتا برای نسخه خاصی از محتوا.
1
2
HTTP/1.1 200 OK
ETag: "v2.6"
Cache این ETag را نگه میدارد و دفعه بعد میپرسد:
1
2
GET /page.html HTTP/1.1
If-None-Match: "v2.6"
اگر ETag تغییر نکرده باشد، سرور 304 Not Modified برمیگرداند.
کدام بهتر است؟ کتاب توضیح میدهد که HTTP/1.1 ترجیح میدهد از ETag استفاده شود، اما هر دو روش میتوانند همزمان استفاده شوند. اگر هر دو فرستاده شوند، سرور باید هر دو را تأیید کند.
Cache-Control Directives - دستورات کنترل Cache
HTTP/1.1 یک سیستم جامع برای کنترل رفتار Cache معرفی کرد. این Directive ها میتوانند توسط هر دو طرف - Server و Client - فرستاده شوند.
Directive های Request (Client به Cache)
| Directive | توضیح |
|---|---|
no-cache | محتوا را از Cache نده - اول با سرور Revalidate کن |
no-store | هیچ نسخهای از این Response را ذخیره نکن |
max-age=<s> | محتوایی قبول دارم که کمتر از s ثانیه پیر باشد |
max-stale=<s> | حتی محتوای منقضیشده را قبول دارم، اما حداکثر تا s ثانیه بعد از انقضا |
min-fresh=<s> | محتوایی میخواهم که حداقل s ثانیه دیگر تازه باشد |
only-if-cached | فقط از Cache پاسخ بده - اگر ندارد 504 Gateway Timeout بده |
no-transform | محتوا را تغییر نده (مثلاً تصاویر را فشرده نکن) |
Directive های Response (Server به Cache)
| Directive | توضیح |
|---|---|
public | این Response را میتوان Cache کرد حتی اگر Authenticated باشد |
private | این Response فقط برای یک کاربر خاص است - Shared Cache نباید آن را ذخیره کند |
no-cache | بدون Revalidation با سرور، این محتوا را به Client نده |
no-store | این Response را اصلاً ذخیره نکن |
no-transform | محتوا را تغییر نده |
must-revalidate | قبل از استفاده از نسخه منقضیشده، حتماً Revalidate کن |
proxy-revalidate | مثل must-revalidate اما فقط برای Shared Cache ها |
max-age=<s> | محتوا تا s ثانیه تازه است |
s-maxage=<s> | مثل max-age اما فقط برای Shared Cache ها |
Controlling Cachability - چه کسی کنترل میکند؟
کتاب سه لایه کنترل Caching را معرفی میکند:
لایه اول: Server کنترل میکند
روش اول - Cache-Control Header:
1
2
3
Cache-Control: no-store
Cache-Control: no-cache
Cache-Control: must-revalidate, max-age=3600
روش دوم - Expires Header:
1
Expires: Thu, 01 Dec 2024 16:00:00 GMT
روش سوم - هیچ Expiration نگذاشتن: اگر Server هیچ Freshness Header نفرستد، Cache میتواند از Heuristic Expiration استفاده کند.
Heuristic Expiration - تخمین Freshness
وقتی سرور هیچ اطلاعاتی درباره Freshness نمیدهد، Cache خودش تخمین میزند. رایجترین الگوریتم:
1
Freshness Lifetime = (Date - Last-Modified) × 0.1
یعنی اگر آخرین تغییر فایل ۱۰ روز پیش بوده، Cache آن را برای ۱ روز (۱۰٪ از ۱۰ روز) تازه در نظر میگیرد.
هشدار: این فقط یک تخمین است. برای محتوای حساس، همیشه باید صریحاً Cache-Control Header فرستاده شود.
لایه دوم: Client کنترل میکند
Client میتواند Cache را دور بزند:
1
2
Cache-Control: no-cache
Pragma: no-cache
وقتی کاربر در مرورگر Ctrl+F5 میزند، مرورگر این Header ها را ارسال میکند.
لایه سوم: مدیر Cache کنترل میکند
مدیر سرور میتواند قوانین Caching را در تنظیمات Cache Proxy تعریف کند - مستقل از آنچه Server یا Client میگویند.
Cache و تبلیغات آنلاین - یک تنش واقعی
نویسندگان یک تضاد جالب را مطرح میکنند: شرکتهای تبلیغاتی میخواهند بدانند هر بنر تبلیغاتی دقیقاً چند بار دیده شده تا پول دریافت کنند. اما Cache این شمارش را خراب میکند - اگر بنر از Cache تحویل داده شود، Server اصلی خبر ندارد.
راهحلهایی که کتاب ذکر میکند:
- استفاده از
no-cacheبرای تبلیغات تا همیشه از Server اصلی بارگذاری شوند - استفاده از URL های منحصربهفرد برای هر Request تا Cache نتواند آنها را یکسان ببیند
- استفاده از Cookie برای ردیابی بدون دور زدن Cache
Vary Header - Cache بر اساس بیشتر از URL
گاهی یک URL میتواند محتوای متفاوتی برای کاربران مختلف داشته باشد - مثلاً بر اساس زبان یا نوع دستگاه. Cache باید این تفاوت را در نظر بگیرد.
1
Vary: Accept-Language
این Header به Cache میگوید: «برای این URL، نسخههای مختلف را بر اساس Accept-Language جداگانه Cache کن.»
1
2
URL: /index.html + Accept-Language: fa → نسخه فارسی Cache میشود
URL: /index.html + Accept-Language: en → نسخه انگلیسی Cache میشود
فصل هشتم - بخش اول: Gateways و یکپارچهسازی با پروتکلهای دیگر
Gateway چیست؟
نویسندگان با یک تعریف دقیق شروع میکنند: Gateway یک واسط است که یک طرف از HTTP صحبت میکند و طرف دیگر از پروتکل متفاوتی.
تفاوت اصلی با Proxy: Proxy هر دو طرف از HTTP استفاده میکنند. Gateway یک مترجم پروتکل است.
1
Client ──── HTTP ────▶ [Gateway] ──── پروتکل دیگر ────▶ Server
Gateway به HTTP اجازه میدهد با دنیای خارج از HTTP ارتباط برقرار کند - پایگاه داده، سرویسهای FTP، برنامههای Legacy و هر سیستم دیگری.
نامگذاری Gateway ها
کتاب یک فرمت نامگذاری برای Gateway ها معرفی میکند:
1
<پروتکل طرف Client> / <پروتکل طرف Server>
| نام | توضیح |
|---|---|
HTTP/FTP | از Client درخواست HTTP میگیرد، از FTP Server فایل میگیرد |
HTTP/HTTPS | HTTP را به HTTPS تبدیل میکند |
HTTPS/HTTP | Connection امن را Terminate میکند و HTTP ساده به سرور میفرستد |
HTTP/NNTP | به Usenet Newsgroup ها دسترسی میدهد |
Protocol Gateways - انواع مهم
HTTP/FTP Gateway
رایجترین نوع Protocol Gateway. Client یک Request HTTP معمولی میفرستد، Gateway آن را به دستورات FTP تبدیل میکند:
1
2
3
4
5
Client ──── GET ftp://ftp.joes-hardware.com/pub/files/file.txt HTTP/1.0 ────▶ [HTTP/FTP Gateway]
│
FTP RETR file.txt
│
FTP Server
Gateway باید این کارها را انجام دهد:
- یک FTP Connection برقرار کند
- Login کند (از User و Password در URL یا Anonymous)
- دستور
TYPE Iبرای Binary Transfer بفرستد - دستور
PASVبرای Passive Mode بفرستد - دستور
RETRبرای دانلود فایل بفرستد
HTTPS/HTTP Gateway - SSL Termination
در این معماری رایج، یک Gateway در لبه شبکه SSL را Terminate میکند و HTTP ساده به سرورهای داخلی میفرستد:
1
Internet ──── HTTPS ────▶ [SSL Termination Gateway] ──── HTTP ────▶ [سرورهای داخلی]
مزایا:
- سرورهای داخلی نیازی به مدیریت SSL ندارند
- بار رمزنگاری روی یک نقطه متمرکز است
- مدیریت Certificate ها سادهتر است
معایب:
- داده بین Gateway و سرورهای داخلی رمزنگاری نشده است - اگر شبکه داخلی امن نباشد، مشکلساز است
Resource Gateways - CGI و Application Server ها
مهمترین نوع Gateway از دیدگاه توسعهدهنده: Gateway هایی که HTTP را به اجرای کد تبدیل میکنند.
CGI - Common Gateway Interface
اولین و سادهترین استاندارد برای اجرای برنامههای سمت Server.
وقتی یک Request به URL یک CGI Script میرسد:
1
2
3
4
5
۱. Web Server یک Process جدید میسازد
۲. متغیرهای محیطی (Environment Variables) را از HTTP Request پر میکند
۳. Script اجرا میشود
۴. خروجی Script بهعنوان HTTP Response به Client برمیگردد
۵. Process بسته میشود
مشکل اصلی CGI: برای هر Request یک Process جدید ساخته میشود. در ترافیک بالا این بسیار سنگین است - هزاران Process همزمان روی سرور.
FastCGI - حل مشکل CGI
FastCGI یک Process دائمی نگه میدارد. بهجای ساختن Process جدید برای هر Request، درخواستها از طریق یک Connection دائمی به Process همیشهزنده فرستاده میشوند.
1
2
3
4
5
6
7
CGI: [Request 1] → Process → Close
[Request 2] → Process → Close
[Request 3] → Process → Close
FastCGI: [Request 1] ─┐
[Request 2] ──┤──▶ [یک Process دائمی]
[Request 3] ─┘
Server Extension API ها
Web Server های مدرن API هایی ارائه میدهند که به توسعهدهنده اجازه میدهند کد را مستقیم داخل Web Server اجرا کنند - بدون Process جداگانه:
- ISAPI در IIS (مرتبط با .NET)
- Apache Modules در Apache
- Nginx Modules در Nginx
این روش از CGI بسیار سریعتر است چون Overhead ساختن Process وجود ندارد.
Application Interfaces و Web Services
نویسندگان در این بخش به آینده نگاه میکنند و پیشبینی میکنند که HTTP به یک زبان مشترک برای ارتباط بین برنامهها تبدیل خواهد شد.
دو استاندارد مهم که در زمان نوشتن کتاب (۲۰۰۲) در حال ظهور بودند:
SOAP (Simple Object Access Protocol): پیامهای XML را از طریق HTTP منتقل میکند تا برنامهها بتوانند با هم صحبت کنند - صرفنظر از اینکه روی چه پلتفرمی یا به چه زبانی نوشته شدهاند.
XML-RPC: فراخوانی توابع از راه دور (Remote Procedure Call) از طریق HTTP و XML.
دیدگاه انتقادی: نویسندگان صادقانه اشاره میکنند که این استانداردها هنوز در حال تکامل هستند و مشخص نیست کدامیک جا خواهد افتاد. از منظر امروز میدانیم که REST API ها جایگزین SOAP شدند و JSON جایگزین XML شد - اما اصل ایده کاملاً درست بود: HTTP به زبان مشترک Web Services تبدیل شد.
Tunnels - انتقال کور داده
Tunnel یک مکانیزم HTTP است که اجازه میدهد دادههای غیر HTTP از طریق یک HTTP Connection منتقل شوند - بدون اینکه Tunnel محتوا را بخواند یا تغییر دهد.
CONNECT Method - ایجاد Tunnel
رایجترین کاربرد Tunnel: عبور دادن SSL Traffic از میان یک Proxy که فقط HTTP میفهمد.
1
2
3
4
5
6
7
Client ──── CONNECT home.netscape.com:443 HTTP/1.0 ────▶ [Proxy]
[Proxy] ──── 200 Connection Established ────▶ Client
(اکنون یک Tunnel کور داریم)
Client ══════════════ SSL Data ══════════════ Server
(Proxy فقط Byte ها را منتقل میکند)
مراحل دقیق:
- Client یک
CONNECTRequest به Proxy میفرستد با Hostname و Port مقصد - Proxy یک TCP Connection به آن Host و Port برقرار میکند
- اگر موفق شد،
200 Connection Establishedبه Client میفرستد - از این لحظه، Proxy فقط Byte ها را بدون بررسی بین Client و Server منتقل میکند
نکته امنیتی:
CONNECTMethod میتواند خطرناک باشد. اگر Proxy به هر Host و Port اجازه Tunnel بدهد، کاربران میتوانند از آن برای دور زدن فیلترها استفاده کنند. Proxy های هوشمند فقط به Port 443 اجازهCONNECTمیدهند.
Relays - سادهترین نوع واسط
Relay سادهترین نوع HTTP Intermediary است. فقط Connection را برقرار میکند و داده را بدون هیچ پردازشی منتقل میکند.
تفاوت با Tunnel: Relay از HTTP آگاه است اما فقط Start Line و بعضی Header ها را پردازش میکند - نه محتوا.
مشکل اصلی Relay: همان مشکل Blind Relay که در فصل Proxy دیدیم. اگر Relay Connection: keep-alive را بدون پردازش Forward کند، میتواند Deadlock ایجاد کند.
فصل هشتم - بخش اول: Gateways و یکپارچهسازی با پروتکلهای دیگر
Gateway چیست؟
نویسندگان با یک تعریف دقیق شروع میکنند: Gateway یک واسط است که یک طرف از HTTP صحبت میکند و طرف دیگر از پروتکل متفاوتی.
تفاوت اصلی با Proxy: Proxy هر دو طرف از HTTP استفاده میکنند. Gateway یک مترجم پروتکل است.
1
Client ──── HTTP ────▶ [Gateway] ──── پروتکل دیگر ────▶ Server
Gateway به HTTP اجازه میدهد با دنیای خارج از HTTP ارتباط برقرار کند - پایگاه داده، سرویسهای FTP، برنامههای Legacy و هر سیستم دیگری.
نامگذاری Gateway ها
کتاب یک فرمت نامگذاری برای Gateway ها معرفی میکند:
1
<پروتکل طرف Client> / <پروتکل طرف Server>
| نام | توضیح |
|---|---|
HTTP/FTP | از Client درخواست HTTP میگیرد، از FTP Server فایل میگیرد |
HTTP/HTTPS | HTTP را به HTTPS تبدیل میکند |
HTTPS/HTTP | Connection امن را Terminate میکند و HTTP ساده به سرور میفرستد |
HTTP/NNTP | به Usenet Newsgroup ها دسترسی میدهد |
Protocol Gateways - انواع مهم
HTTP/FTP Gateway
رایجترین نوع Protocol Gateway. Client یک Request HTTP معمولی میفرستد، Gateway آن را به دستورات FTP تبدیل میکند:
1
2
3
4
5
Client ──── GET ftp://ftp.joes-hardware.com/pub/files/file.txt HTTP/1.0 ────▶ [HTTP/FTP Gateway]
│
FTP RETR file.txt
│
FTP Server
Gateway باید این کارها را انجام دهد:
- یک FTP Connection برقرار کند
- Login کند (از User و Password در URL یا Anonymous)
- دستور
TYPE Iبرای Binary Transfer بفرستد - دستور
PASVبرای Passive Mode بفرستد - دستور
RETRبرای دانلود فایل بفرستد
HTTPS/HTTP Gateway - SSL Termination
در این معماری رایج، یک Gateway در لبه شبکه SSL را Terminate میکند و HTTP ساده به سرورهای داخلی میفرستد:
1
Internet ──── HTTPS ────▶ [SSL Termination Gateway] ──── HTTP ────▶ [سرورهای داخلی]
مزایا:
- سرورهای داخلی نیازی به مدیریت SSL ندارند
- بار رمزنگاری روی یک نقطه متمرکز است
- مدیریت Certificate ها سادهتر است
معایب:
- داده بین Gateway و سرورهای داخلی رمزنگاری نشده است - اگر شبکه داخلی امن نباشد، مشکلساز است
Resource Gateways - CGI و Application Server ها
مهمترین نوع Gateway از دیدگاه توسعهدهنده: Gateway هایی که HTTP را به اجرای کد تبدیل میکنند.
CGI - Common Gateway Interface
اولین و سادهترین استاندارد برای اجرای برنامههای سمت Server.
وقتی یک Request به URL یک CGI Script میرسد:
1
2
3
4
5
۱. Web Server یک Process جدید میسازد
۲. متغیرهای محیطی (Environment Variables) را از HTTP Request پر میکند
۳. Script اجرا میشود
۴. خروجی Script بهعنوان HTTP Response به Client برمیگردد
۵. Process بسته میشود
مشکل اصلی CGI: برای هر Request یک Process جدید ساخته میشود. در ترافیک بالا این بسیار سنگین است - هزاران Process همزمان روی سرور.
FastCGI - حل مشکل CGI
FastCGI یک Process دائمی نگه میدارد. بهجای ساختن Process جدید برای هر Request، درخواستها از طریق یک Connection دائمی به Process همیشهزنده فرستاده میشوند.
1
2
3
4
5
6
7
CGI: [Request 1] → Process → Close
[Request 2] → Process → Close
[Request 3] → Process → Close
FastCGI: [Request 1] ─┐
[Request 2] ──┤──▶ [یک Process دائمی]
[Request 3] ─┘
Server Extension API ها
Web Server های مدرن API هایی ارائه میدهند که به توسعهدهنده اجازه میدهند کد را مستقیم داخل Web Server اجرا کنند - بدون Process جداگانه:
- ISAPI در IIS (مرتبط با .NET)
- Apache Modules در Apache
- Nginx Modules در Nginx
این روش از CGI بسیار سریعتر است چون Overhead ساختن Process وجود ندارد.
Application Interfaces و Web Services
نویسندگان در این بخش به آینده نگاه میکنند و پیشبینی میکنند که HTTP به یک زبان مشترک برای ارتباط بین برنامهها تبدیل خواهد شد.
دو استاندارد مهم که در زمان نوشتن کتاب (۲۰۰۲) در حال ظهور بودند:
SOAP (Simple Object Access Protocol): پیامهای XML را از طریق HTTP منتقل میکند تا برنامهها بتوانند با هم صحبت کنند - صرفنظر از اینکه روی چه پلتفرمی یا به چه زبانی نوشته شدهاند.
XML-RPC: فراخوانی توابع از راه دور (Remote Procedure Call) از طریق HTTP و XML.
دیدگاه انتقادی: نویسندگان صادقانه اشاره میکنند که این استانداردها هنوز در حال تکامل هستند و مشخص نیست کدامیک جا خواهد افتاد. از منظر امروز میدانیم که REST API ها جایگزین SOAP شدند و JSON جایگزین XML شد - اما اصل ایده کاملاً درست بود: HTTP به زبان مشترک Web Services تبدیل شد.
Tunnels - انتقال کور داده
Tunnel یک مکانیزم HTTP است که اجازه میدهد دادههای غیر HTTP از طریق یک HTTP Connection منتقل شوند - بدون اینکه Tunnel محتوا را بخواند یا تغییر دهد.
CONNECT Method - ایجاد Tunnel
رایجترین کاربرد Tunnel: عبور دادن SSL Traffic از میان یک Proxy که فقط HTTP میفهمد.
1
2
3
4
5
6
7
Client ──── CONNECT home.netscape.com:443 HTTP/1.0 ────▶ [Proxy]
[Proxy] ──── 200 Connection Established ────▶ Client
(اکنون یک Tunnel کور داریم)
Client ══════════════ SSL Data ══════════════ Server
(Proxy فقط Byte ها را منتقل میکند)
مراحل دقیق:
- Client یک
CONNECTRequest به Proxy میفرستد با Hostname و Port مقصد - Proxy یک TCP Connection به آن Host و Port برقرار میکند
- اگر موفق شد،
200 Connection Establishedبه Client میفرستد - از این لحظه، Proxy فقط Byte ها را بدون بررسی بین Client و Server منتقل میکند
نکته امنیتی:
CONNECTMethod میتواند خطرناک باشد. اگر Proxy به هر Host و Port اجازه Tunnel بدهد، کاربران میتوانند از آن برای دور زدن فیلترها استفاده کنند. Proxy های هوشمند فقط به Port 443 اجازهCONNECTمیدهند.
Relays - سادهترین نوع واسط
Relay سادهترین نوع HTTP Intermediary است. فقط Connection را برقرار میکند و داده را بدون هیچ پردازشی منتقل میکند.
تفاوت با Tunnel: Relay از HTTP آگاه است اما فقط Start Line و بعضی Header ها را پردازش میکند - نه محتوا.
مشکل اصلی Relay: همان مشکل Blind Relay که در فصل Proxy دیدیم. اگر Relay Connection: keep-alive را بدون پردازش Forward کند، میتواند Deadlock ایجاد کند.
فصل نهم - بخش اول: Web Robots و Crawlers
Web Robot چیست؟
نویسندگان تعریف دقیقی ارائه میدهند: Web Robot برنامهای است که HTTP Transaction های خودکار انجام میدهد - بدون هیچ تعامل انسانی در حین اجرا.
Robot ها انواع مختلفی دارند:
| نوع | توضیح |
|---|---|
| Crawler / Spider | وب را میگردد و لینکها را دنبال میکند |
| Web Wanderer | اندازه و ساختار وب را اندازهگیری میکند |
| Indexer | محتوا را برای موتور جستجو ایندکس میکند |
| Harvester | اطلاعات خاصی (مثل آدرس ایمیل) جمعآوری میکند |
| Checker | لینکهای شکسته را پیدا میکند |
| Mirror Maker | نسخه کامل یک سایت را کپی میکند |
Crawling - چطور وب را میگردند؟
شروع از Seed URL ها
هر Crawler از یک یا چند Seed URL شروع میکند. این URL ها نقطه آغازین هستند. Crawler صفحه را دانلود میکند، تمام لینکهای داخل آن را استخراج میکند و آنها را به صف اضافه میکند.
1
2
3
4
5
6
7
8
9
10
11
Seed URLs
│
▼
[صف URL ها]
│
▼
دانلود صفحه
│
├── استخراج لینکهای جدید ──▶ [صف URL ها]
│
└── پردازش محتوا (ایندکس، ذخیره، ...)
مشکل Loop - دور باطل
اگر Crawler مراقب نباشد، میتواند در یک حلقه بینهایت گیر کند:
1
صفحه A ──▶ صفحه B ──▶ صفحه A ──▶ صفحه B ──▶ ...
راهحل: Crawler باید یک ساختار داده برای URL های بازدیدشده نگه دارد. رایجترین روشها:
- Hash Table: جستجوی سریع O(1) - مناسب برای Crawler های کوچک
- Checksum: بهجای ذخیره URL کامل، Checksum آن را ذخیره میکند - فضای کمتر
- Bloom Filter: یک ساختار داده Probabilistic که فضای بسیار کمتری مصرف میکند اما ممکن است False Positive داشته باشد
URL Normalization
URL های مختلف ممکن است به یک Resource اشاره کنند:
1
2
3
4
http://www.joes-hardware.com/index.html
http://www.joes-hardware.com/index.html#section1
HTTP://WWW.JOES-HARDWARE.COM/index.html
http://www.joes-hardware.com:80/index.html
Crawler باید این URL ها را نرمالیزه کند تا از بازدید تکراری جلوگیری کند.
Robotic HTTP - رفتار صحیح HTTP در Robot ها
شناسایی خود - User-Agent Header
هر Robot باید خودش را با User-Agent Header معرفی کند:
1
User-Agent: Slurp/2.0 ([email protected]; http://www.inktomi.com/slurp.html)
این اطلاعات به مدیر سایت کمک میکند بفهمد چه Robot هایی سایتش را بازدید کردهاند و اگر مشکلی باشد با آنها تماس بگیرد.
Virtual Hosting - Host Header
اگر یک سرور چندین Virtual Host داشته باشد، Robot باید Host Header را حتماً بفرستد، وگرنه سرور نمیداند به کدام سایت میخواهد دسترسی داشته باشد.
1
2
3
GET /index.html HTTP/1.1
Host: www.joes-hardware.com
User-Agent: MyRobot/1.0
Conditional GET - احترام به Cache
Robot های خوب از Conditional GET استفاده میکنند تا در صورت عدم تغییر محتوا، آن را دوباره دانلود نکنند:
1
2
GET /page.html HTTP/1.1
If-Modified-Since: Sat, 22 Jun 2002 12:00:00 GMT
اگر صفحه تغییر نکرده باشد، سرور 304 Not Modified برمیگرداند و Robot از دانلود مجدد جلوگیری میکند.
Misbehaving Robots - Robot های بدرفتار
نویسندگان صادقانه از مشکلاتی که Robot ها میتوانند ایجاد کنند صحبت میکنند:
Looping - دور باطل
Robot بدون تشخیص Loop، مدام همان صفحات را بازدید میکند و سرور را زیر درخواستهای تکراری دفن میکند.
Overloading - بار اضافه
بعضی Robot ها Request ها را بدون هیچ تأخیری میفرستند - مثل یک DDoS ناخواسته. یک سرور کوچک ممکن است تحت این فشار از کار بیفتد.
Harvesting - جمعآوری مخرب
Robot هایی که آدرسهای ایمیل را برای Spam جمع میکنند، یا قیمتهای رقبا را برای کپی کردن میخوانند.
Excluding Robots - پروتکل robots.txt
برای حل مشکل Robot های ناخواسته، یک استاندارد غیررسمی اما پذیرفتهشده وجود دارد: Robots Exclusion Protocol یا همان فایل robots.txt.
قوانین استفاده از robots.txt
هر Robot قبل از هر چیز باید این فایل را بخواند:
1
2
GET /robots.txt HTTP/1.1
Host: www.joes-hardware.com
اگر سرور 404 Not Found برگرداند، Robot میتواند همه جای سایت برود. اگر فایل وجود داشت، باید قوانین آن را رعایت کند.
ساختار فایل robots.txt
1
2
3
4
5
6
7
8
9
10
11
User-agent: *
Disallow: /tmp/
Disallow: /logs/
Disallow: /admin/
User-agent: Googlebot
Disallow: /private/
Allow: /public/
User-agent: BadBot
Disallow: /
قوانین ساختار:
User-agent: *- برای همه Robot ها اعمال میشودUser-agent: Googlebot- فقط برای Googlebot اعمال میشودDisallow:- این مسیر ممنوع استAllow:- این مسیر مجاز است (برای Override کردن یک Disallow کلیتر)Disallow:خالی - یعنی هیچ محدودیتی وجود ندارد
نکته مهم درباره robots.txt
کتاب تأکید میکند: robots.txt یک قرارداد اجتماعی است، نه یک مکانیزم امنیتی.
یک Robot بدخواه میتواند کاملاً این فایل را نادیده بگیرد. اگر محتوایی واقعاً محرمانه است، باید با احراز هویت از آن محافظت شود - نه فقط با robots.txt.
Meta Tag - کنترل Crawling در سطح صفحه
علاوه بر robots.txt که در سطح سرور کار میکند، HTML یک Meta Tag برای کنترل Crawling در سطح صفحه دارد:
1
2
3
4
<meta name="robots" content="noindex">
<meta name="robots" content="nofollow">
<meta name="robots" content="noindex, nofollow">
<meta name="robots" content="all">
| مقدار | توضیح |
|---|---|
noindex | این صفحه را ایندکس نکن |
nofollow | لینکهای این صفحه را دنبال نکن |
noindex, nofollow | هیچکدام از این دو کار را نکن |
all | هر دو کار مجاز است (پیشفرض) |
Search Engines - موتورهای جستجو
نویسندگان توضیح میدهند که موتورهای جستجو از چند جزء اصلی تشکیل شدهاند:
1
2
3
[Crawler] ──▶ [Repository] ──▶ [Indexer] ──▶ [Search Index]
│
[Query Engine] ◀── کاربر
- Crawler: وب را میگردد و صفحات را جمعآوری میکند
- Repository: صفحات جمعآوریشده را ذخیره میکند
- Indexer: کلمات کلیدی و لینکها را استخراج و ایندکس میکند
- Query Engine: جستجوی کاربر را در ایندکس اجرا میکند
فصل یازدهم - بخش اول: Client Identification و روشهای شناسایی کاربر
چرا شناسایی کاربر مهم است؟
HTTP یک پروتکل Stateless است - هر Request کاملاً مستقل از Request های قبلی است. سرور بهطور پیشفرض هیچ حافظهای از تعاملات قبلی ندارد.
اما اپلیکیشنهای واقعی نیاز دارند کاربر را بشناسند:
- فروشگاه آنلاین باید سبد خرید را برای هر کاربر جداگانه نگه دارد
- سایت خبری باید ترجیحات کاربر را به خاطر بسپارد
- سیستم بانکی باید مطمئن شود فقط کاربر مجاز به حساب دسترسی دارد
این تضاد بین Stateless بودن HTTP و نیاز اپلیکیشن به State چالش اصلی این فصل است.
روش اول: HTTP Headers
بعضی Header ها اطلاعاتی درباره کاربر حمل میکنند:
| Header | توضیح | محدودیت |
|---|---|---|
From | آدرس ایمیل کاربر | مرورگرها آن را برای حفظ حریم خصوصی ارسال نمیکنند |
User-Agent | نوع و نسخه مرورگر | همه کاربران یک مرورگر را شناسایی نمیکند |
Referer | URL صفحهای که از آن آمده | فقط رفتار کاربر را نشان میدهد، هویت نه |
این Header ها برای آمار و تحلیل مفید هستند اما برای شناسایی یکتای کاربر کافی نیستند.
روش دوم: Client IP Address
سادهترین روش: استفاده از IP Address کاربر.
مشکلات جدی این روش:
- NAT: چندین کاربر پشت یک Router یک IP مشترک دارند - همه آنها یکسان به نظر میرسند
- DHCP: IP Address کاربر هر بار ممکن است تغییر کند
- Proxy: اگر کاربر از Proxy استفاده کند، سرور IP Proxy را میبیند نه IP کاربر
- حریم خصوصی: ردیابی کاربر از طریق IP مشکلات حقوقی ایجاد میکند
نتیجه: IP Address برای شناسایی کاربر غیرقابلاعتماد است.
روش سوم: User Login - احراز هویت صریح
اگر سرور نیاز به شناسایی داشته باشد، میتواند از کاربر بخواهد Login کند.
1
2
3
4
5
6
7
8
9
Client ──── GET /private/page.html HTTP/1.1 ────▶ Server
Server ◀──── 401 Unauthorized ────────────────── Server
WWW-Authenticate: Basic realm="My Site"
Client ──── GET /private/page.html HTTP/1.1 ────▶ Server
Authorization: Basic dXNlcjpwYXNz
Server ◀──── 200 OK ───────────────────────────── Server
وقتی کاربر یکبار Login کند، مرورگر بهصورت خودکار Authorization Header را با هر Request بعدی به همان سرور میفرستد.
مشکلات:
- هر سایت جداگانه Username و Password میخواهد
- کاربر باید برای هر سایت ثبتنام کند
- مدیریت این همه اعتبارنامه برای کاربر دشوار است
روش چهارم: Fat URLs
یک روش خلاقانه اما مشکلدار: اطلاعات شناسایی کاربر را داخل URL جاسازی کنید.
1
2
3
http://www.joes-hardware.com/storefront?user_id=XYZ987
http://www.joes-hardware.com/tools.html?user_id=XYZ987
http://www.joes-hardware.com/checkout?user_id=XYZ987
مشکلات جدی:
- زشتی URL: URL های طولانی و ناخوانا برای کاربر
- نشت اطلاعات: اگر کاربر URL را برای دیگری بفرستد، Session اشتراکگذاری میشود
- Cache شکست: هر کاربر URL منحصربهفرد دارد - Cache نمیتواند آنها را با هم Cache کند
- از دست دادن Session: اگر کاربر URL را تایپ کند بدون User ID، Session از دست میرود
روش پنجم: Cookies - بهترین راهحل
Cookie مکانیزمی است که به سرور اجازه میدهد اطلاعاتی را روی مرورگر کاربر ذخیره کند و در Request های بعدی آنها را بازیابی کند.
ساختار Cookie
1
Set-Cookie: user_id=XYZ987; domain=.joes-hardware.com; path=/; expires=Wed, 09-Jun-2025 10:18:14 GMT
| بخش | توضیح |
|---|---|
user_id=XYZ987 | نام و مقدار Cookie |
domain=.joes-hardware.com | این Cookie فقط برای این Domain فرستاده شود |
path=/ | این Cookie برای همه مسیرهای سایت فرستاده شود |
expires=... | تاریخ انقضا - بعد از این تاریخ Cookie حذف میشود |
چرخه کامل Cookie
اولین بازدید - کاربر ناشناس:
1
2
3
4
5
6
Client ──── GET /index.html HTTP/1.1 ────────────────────────▶ Server
(هیچ Cookie ای نیست)
Client ◀─── 200 OK ────────────────────────────────────────── Server
Set-Cookie: id=XYZ987; domain=joes-hardware.com
(سرور یک شناسه به کاربر میدهد)
بازدیدهای بعدی:
1
2
3
4
5
6
Client ──── GET /tools.html HTTP/1.1 ────────────────────────▶ Server
Cookie: id=XYZ987
(مرورگر Cookie را خودکار میفرستد)
Client ◀─── 200 OK ────────────────────────────────────────── Server
(سرور کاربر را میشناسد)
دو نوع Cookie
Session Cookie: موقتی است. وقتی مرورگر بسته شود، حذف میشود. تاریخ انقضا ندارد.
Persistent Cookie: روی دیسک ذخیره میشود و بعد از بستن مرورگر هم باقی میماند. با expires یا max-age تعریف میشود.
Cookie و امنیت
Secure Flag
اگر Secure Flag روی Cookie باشد، مرورگر آن را فقط از طریق HTTPS میفرستد:
1
Set-Cookie: session_id=ABC123; Secure
HttpOnly Flag
با این Flag، JavaScript نمیتواند به Cookie دسترسی داشته باشد - از XSS (Cross-Site Scripting) جلوگیری میکند:
1
Set-Cookie: session_id=ABC123; HttpOnly
Domain و Path - محدوده Cookie
Cookie ها فقط به Domain و Path مشخصشده فرستاده میشوند:
1
Set-Cookie: pref=dark; domain=.joes-hardware.com; path=/tools
این Cookie فقط به سابدامینهای joes-hardware.com و فقط برای مسیر /tools فرستاده میشود.
Cookie و حریم خصوصی
نویسندگان یک بحث انتقادی مهم مطرح میکنند: Cookie ها میتوانند برای ردیابی رفتار کاربر در سطح گسترده استفاده شوند.
Third-Party Cookie: اگر یک صفحه از سرور دیگری (مثلاً یک شبکه تبلیغاتی) محتوا بارگذاری کند، آن سرور هم میتواند Cookie تنظیم کند. این Cookie در سایتهای مختلف فرستاده میشود و رفتار کاربر را در سراسر وب ردیابی میکند.
فصل دوازدهم و سیزدهم - Authentication: Basic و Digest
Authentication چیست؟
نویسندگان بین دو مفهوم تمایز میکشند:
- Authentication (احراز هویت): تأیید اینکه «تو کی هستی»
- Authorization (مجوزدهی): تأیید اینکه «آیا اجازه داری این کار را بکنی»
HTTP دو مکانیزم استاندارد برای Authentication دارد: Basic و Digest. هر دو از یک چرخه چهار مرحلهای استفاده میکنند.
چرخه Authentication
1
2
3
4
5
6
7
8
9
10
11
12
13
Client ──── Request ────────────────────────────────────────▶ Server
(بدون اعتبارنامه)
Client ◀─── 401 Unauthorized ──────────────────────────────── Server
WWW-Authenticate: Basic realm="Family"
(سرور میگوید: احراز هویت لازم است)
Client ──── Request ────────────────────────────────────────▶ Server
Authorization: Basic [اعتبارنامه]
(کاربر Username و Password را میفرستد)
Client ◀─── 200 OK ─────────────────────────────────────────── Server
(دسترسی مجاز است)
Basic Authentication - ساده اما ناامن
نحوه کارکرد
سرور ابتدا یک Realm مشخص میکند - یک ناحیه حفاظتشده با نام:
1
WWW-Authenticate: Basic realm="Corporate Financials"
Client اعتبارنامه را به این شکل میسازد:
1
2
3
4
۱. ترکیب: username:password → "joe:joepasswd"
۲. Base64 Encode: → "am9lOmpvZXBhc3N3ZA=="
۳. ارسال:
Authorization: Basic am9lOmpvZXBhc3N3ZA==
نکته مهم: Base64 یک Encoding است، نه Encryption. هر کسی میتواند آن را Decode کند. این یعنی Basic Authentication اعتبارنامه را بهصورت Plain Text روی شبکه میفرستد.
مشکلات امنیتی Basic Authentication
کتاب چهار مشکل جدی را صریح بیان میکند:
اول - رمزنگاری ضعیف: Base64 هیچ امنیتی ندارد. هر کسی که ترافیک شبکه را ببیند میتواند فوری Username و Password را استخراج کند.
دوم - نبود محافظت در برابر Replay Attack: اگر مهاجم یک Request را ضبط کند، میتواند دقیقاً همان Request را دوباره بفرستد و دسترسی پیدا کند.
سوم - نبود محافظت از محتوا: Basic Authentication فقط هویت را تأیید میکند. بعد از تأیید، محتوای Request و Response هنوز Plain Text است.
چهارم - Proxy و Intermediary: هر Proxy در مسیر میتواند اعتبارنامه را ببیند.
نتیجه نویسندگان: Basic Authentication فقط در ترکیب با HTTPS/TLS قابل استفاده است. تنها راه امن کردن آن این است که کل Connection رمزنگاری شود.
Digest Authentication - نسخه امنتر
ایده اصلی
Digest Authentication یک اصل ساده دارد: هرگز Password را روی شبکه نفرست. بهجای آن، یک Digest (خلاصه) از Password فرستاده میشود.
Nonce - کلید ضد Replay Attack
سرور یک مقدار تصادفی به نام Nonce میسازد و به Client میفرستد. Client این Nonce را در محاسبه Digest استفاده میکند:
1
2
3
4
Server ──── 401 Unauthorized ────────────────────────────────▶ Client
WWW-Authenticate: Digest
realm="[email protected]"
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093"
نحوه محاسبه Digest
Client با این الگوریتم Digest را محاسبه میکند:
1
2
3
HA1 = MD5(username:realm:password)
HA2 = MD5(method:digestURI)
Response = MD5(HA1:nonce:HA2)
مثال عملی:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
username = "Mufasa"
password = "Circle Of Life"
realm = "[email protected]"
nonce = "dcd98b7102dd2f0e8b11d0f600bfb0c093"
URI = "/dir/index.html"
method = "GET"
HA1 = MD5("Mufasa:[email protected]:Circle Of Life")
= "939e7578ed9e3c518a452acee763bce9"
HA2 = MD5("GET:/dir/index.html")
= "39aff3a2bab80126081ab5c0a1f5a3b8"
Response = MD5("939e7578...:dcd98b71...:39aff3a2...")
= "6629fae49393a05397450978507c4ef1"
Request نهایی:
1
2
3
4
5
6
GET /dir/index.html HTTP/1.1
Authorization: Digest username="Mufasa",
realm="[email protected]",
nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",
uri="/dir/index.html",
response="6629fae49393a05397450978507c4ef1"
Quality of Protection - qop
HTTP/1.1 یک لایه اضافه به Digest اضافه کرد به نام qop (Quality of Protection):
qop=auth
فقط احراز هویت - همان محاسبه پایه که بالا دیدیم.
qop=auth-int
علاوه بر احراز هویت، یکپارچگی پیام هم تأیید میشود. HA2 شامل Body پیام هم میشود:
1
HA2 = MD5(method:digestURI:MD5(entityBody))
این تضمین میکند که محتوای Request در مسیر تغییر نکرده.
Nonce Count - ضد Replay Attack
با qop، Client یک Nonce Count (nc) میفرستد که نشان میدهد این Nonce چندمین بار استفاده میشود:
1
nc=00000001 ← اولین استفاده از این Nonce
سرور میتواند تشخیص دهد اگر همان nc دوباره دیده شود، یک Replay Attack رخ داده.
مقایسه Basic و Digest
| ویژگی | Basic | Digest |
|---|---|---|
| ارسال Password | Base64 (قابل Decode) | هرگز - فقط Hash |
| Replay Attack | آسیبپذیر | محافظتشده با Nonce |
| یکپارچگی پیام | ندارد | با qop=auth-int |
| پیچیدگی پیادهسازی | بسیار ساده | متوسط |
| امنیت بدون HTTPS | هیچ | نسبی |
| امنیت با HTTPS | قابل قبول | خوب |
محدودیتهای Digest Authentication
نویسندگان صادقانه بیان میکنند که Digest هم بینقص نیست:
اول - Man-in-the-Middle: اگر مهاجم بتواند ترافیک را Intercept کند، میتواند سرور جعلی بسازد و اعتبارنامه را بدزدد.
دوم - MD5 قدیمی است: MD5 در زمان نوشتن کتاب (2002) قابل قبول بود. امروز MD5 کاملاً شکسته شده - برای هر کاربرد امنیتی باید از SHA-256 یا بالاتر استفاده شود.
سوم - پذیرش محدود: در عمل Digest Authentication بهطور گسترده پیادهسازی نشد. اکثر سایتها بهجای آن از Form-Based Authentication + HTTPS + Session Cookie استفاده کردند.
دیدگاه امروزی: در سال 2026، هیچکدام از این دو مکانیزم برای اپلیکیشنهای مدرن کافی نیستند. استاندارد فعلی OAuth 2.0 / OpenID Connect است که روی HTTPS و Token های JWT کار میکند.
فصل چهاردهم - بخش اول: رمزنگاری دیجیتال و مبانی HTTPS
چرا HTTP ناامن است؟
نویسندگان با یک واقعیت تلخ شروع میکنند: HTTP داده را بهصورت Plain Text منتقل میکند. هر کسی در مسیر شبکه - ISP، Proxy، مهاجم - میتواند:
- محتوای کامل Request و Response را بخواند
- اطلاعات حساس (Password، شماره کارت اعتباری) را بدزدد
- محتوا را تغییر دهد بدون اینکه Client یا Server متوجه شوند
- هویت Server را جعل کند
HTTPS این مشکلات را با اضافه کردن یک لایه SSL/TLS زیر HTTP حل میکند.
سه هدف اصلی رمزنگاری
کتاب رمزنگاری را برای رسیدن به سه هدف معرفی میکند:
| هدف | توضیح | سوال |
|---|---|---|
| Confidentiality (محرمانگی) | فقط گیرنده مجاز محتوا را بخواند | چه کسی میتواند بخواند؟ |
| Integrity (یکپارچگی) | محتوا در مسیر تغییر نکرده باشد | آیا تغییر کرده؟ |
| Authentication (احراز هویت) | طرف مقابل واقعاً همان کسی است که ادعا میکند | با چه کسی صحبت میکنم؟ |
رمزنگاری متقارن - Symmetric-Key Cryptography
مفهوم پایه
فرستنده و گیرنده از یک کلید مشترک برای رمزنگاری و رمزگشایی استفاده میکنند:
1
2
Plain Text ──[Key]──▶ Cipher Text ──[Key]──▶ Plain Text
رمزنگاری رمزگشایی
الگوریتمهای رایج: DES، 3DES، AES، RC4
مشکل اصلی - توزیع کلید
اگر Alice و Bob میخواهند ارتباط امن داشته باشند، باید ابتدا کلید را با هم به اشتراک بگذارند. اما چطور؟ اگر کانال ارتباطی امن نیست، کلید هم در خطر است.
این مشکل به نام Key Distribution Problem شناخته میشود و یکی از چالشهای بنیادی رمزنگاری است.
رمزنگاری نامتقارن - Public-Key Cryptography
ایده انقلابی
بهجای یک کلید مشترک، هر طرف دو کلید دارد:
- Public Key: عمومی است - هر کسی میتواند آن را داشته باشد
- Private Key: کاملاً محرمانه است - فقط صاحبش میداند
رابطه بین آنها: چیزی که با Public Key رمزنگاری شده، فقط با Private Key متناظر رمزگشایی میشود - و بالعکس.
1
2
3
4
5
Alice میخواهد به Bob پیام امن بفرستد:
۱. Alice Public Key بابرا دریافت میکند (عمومی است، مشکلی نیست)
۲. Alice پیام را با Public Key باب رمزنگاری میکند
۳. فقط باب با Private Key خودش میتواند آن را رمزگشایی کند
الگوریتم RSA
رایجترین الگوریتم Public-Key. امنیت آن بر اساس سختی تجزیه اعداد بزرگ به عوامل اول است.
مشکل Performance
رمزنگاری نامتقارن از نظر محاسباتی بسیار کندتر از متقارن است - تا 1000 برابر کندتر.
راهحل عملی SSL/TLS: از Public-Key فقط برای تبادل کلید استفاده میشود. بعد از اینکه کلید متقارن بهصورت امن تبادل شد، ادامه ارتباط با رمزنگاری متقارن انجام میشود.
Digital Signatures - امضای دیجیتال
مفهوم
امضای دیجیتال ثابت میکند که یک پیام واقعاً از طرف مشخصی آمده و تغییر نکرده.
نحوه کارکرد
1
2
3
4
5
6
7
8
9
امضا کردن (توسط فرستنده):
۱. محاسبه Hash از پیام → "abc123"
۲. رمزنگاری Hash با Private Key → [امضا]
۳. ارسال: پیام + امضا
تأیید (توسط گیرنده):
۱. رمزگشایی امضا با Public Key → "abc123"
۲. محاسبه Hash از پیام دریافتی → "abc123"
۳. مقایسه دو Hash → یکسان = پیام معتبر است
اگر پیام در مسیر تغییر کرده باشد، Hash محاسبهشده با Hash رمزگشاییشده یکسان نخواهد بود.
Digital Certificates - گواهی دیجیتال
مشکل - چطور Public Key را تأیید کنیم؟
اگر مهاجم بتواند Public Key جعلی ارائه دهد، میتواند هویت سرور را جعل کند. نیاز به یک مرجع قابلاعتماد داریم.
Certificate Authority - CA
CA یک سازمان مورداعتماد است که هویت سرورها را تأیید میکند. CA یک Digital Certificate صادر میکند که شامل:
- نام سرور (Common Name)
- Public Key سرور
- تاریخ انقضا
- امضای دیجیتال CA
1
2
3
4
5
[Server] ──── ارسال اطلاعات هویت ────▶ [CA]
(اسناد، مدارک شرکت)
[Server] ◀─── Certificate ────────────── [CA]
(CA هویت را تأیید و امضا کرد)
زنجیره اعتماد - Chain of Trust
1
2
3
4
5
│
└── امضا کرده ──▶ [Intermediate CA]
│
└── امضا کرده ──▶ [Certificate سرور]
مرورگر Root CA های مورداعتماد را از قبل میشناسد. وقتی Certificate سرور را میبیند، زنجیره را تا Root CA بررسی میکند.
ساختار یک Certificate
1
2
3
4
5
6
7
8
9
10
11
12
Certificate:
Version: 3
Serial Number: 1234567890
Issuer: CN=VeriSign Class 3 CA
Validity:
Not Before: Jan 1 00:00:00 2002
Not After: Dec 31 23:59:59 2003
Subject: CN=www.joes-hardware.com
O=Joe's Hardware, Inc.
C=US
Public Key: RSA (2048 bit)
Signature: [امضای CA]
HTTPS - HTTP روی SSL/TLS
تفاوت ظاهری
1
2
HTTP: http://www.joes-hardware.com/index.html (Port 80)
HTTPS: https://www.joes-hardware.com/index.html (Port 443)
SSL Handshake - برقراری اتصال امن
قبل از اینکه یک Byte از داده HTTP منتقل شود، باید SSL Handshake انجام شود:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Client Server
│ │
│──── ClientHello ──────────────────────────────▶│
│ (نسخه SSL، Cipher Suite های پشتیبانیشده،│
│ یک عدد تصادفی) │
│ │
│◀─── ServerHello ──────────────────────────────│
│ (Cipher Suite انتخابشده، عدد تصادفی) │
│ │
│◀─── Certificate ──────────────────────────────│
│ (گواهی دیجیتال سرور) │
│ │
│ [Client Certificate سرور را تأیید میکند] │
│ │
│──── ClientKeyExchange ─────────────────────────▶│
│ (Pre-Master Secret رمزنگاریشده با │
│ Public Key سرور) │
│ │
│ [هر دو Session Key متقارن را میسازند] │
│ │
│──── ChangeCipherSpec + Finished ───────────────▶│
│◀─── ChangeCipherSpec + Finished ───────────────│
│ │
│══════════ داده HTTP رمزنگاریشده ══════════════│
Session Key - کلید موقت
بعد از Handshake، هر دو طرف یک Session Key مشترک دارند که:
- برای همین Session است - در Session بعدی متفاوت خواهد بود
- با الگوریتم متقارن (مثل AES) داده را رمزنگاری میکند
- بسیار سریعتر از RSA است
Tunneling HTTPS از طریق Proxy
وقتی Client از طریق Proxy به یک HTTPS سرور وصل میشود، یک مشکل وجود دارد: Proxy نمیتواند داده رمزنگاریشده را بخواند.
راهحل: CONNECT Method که در فصل هشتم دیدیم:
1
2
3
4
5
6
7
8
Client ──── CONNECT www.joes-hardware.com:443 HTTP/1.0 ────▶ [Proxy]
[Proxy] اتصال TCP به سرور برقرار میکند
[Proxy] ──── 200 Connection Established ────▶ Client
Client ════════ SSL Handshake و داده رمزنگاریشده ════════ Server
(Proxy فقط Byte ها را منتقل میکند)
فصل پانزدهم - بخش اول: Entities و Encodings
پیام در مقابل Entity - تمایز مهم
نویسندگان از همان ابتدا یک تمایز مفهومی مهم میکشند:
- HTTP Message: ظرف حملونقل است - Start Line، Headers و Body
- HTTP Entity: محتوای واقعی است - چیزی که حمل میشود
رابطه آنها: پیام مثل جعبه است، Entity مثل بار داخل جعبه.
1
2
3
4
5
6
7
8
HTTP Message
┌─────────────────────────────────┐
│ HTTP/1.1 200 OK │ ← Start Line
│ Content-Type: text/html │ ← Entity Headers
│ Content-Length: 348 │ ← Entity Headers
│ │ ← Blank Line
│ <html>...</html> │ ← Entity Body
└─────────────────────────────────┘
Entity Headers - توصیف محتوا
Entity Headers اطلاعاتی درباره محتوای Body ارائه میدهند:
| Header | توضیح |
|---|---|
Content-Type | نوع MIME محتوا |
Content-Length | طول Body به Byte |
Content-Language | زبان محتوا |
Content-Encoding | Encoding اعمالشده (مثل gzip) |
Content-Location | آدرس جایگزین برای این Resource |
Content-Range | محدوده Byte در Partial Response |
Content-MD5 | Checksum MD5 برای تأیید صحت |
Last-Modified | آخرین زمان تغییر |
Expires | زمان انقضای محتوا |
Allow | Method های مجاز |
ETag | شناسه یکتا برای این نسخه |
Content-Length - طول دقیق Body
چرا Content-Length مهم است؟
TCP یک جریان پیوسته از Byte هاست. بدون Content-Length، گیرنده نمیداند Body کجا تمام میشود و پیام بعدی کجا شروع میشود.
این بهخصوص در Persistent Connection ها حیاتی است - چون چندین پیام پشت سر هم روی یک Connection میآیند.
استثناها - کِی Content-Length اجباری نیست؟
کتاب سه حالت را ذکر میکند:
- Response به HEAD: Body ندارد، پس Content-Length لازم نیست
- Status Code 1xx، 204، 304: این Response ها Body ندارند
- Transfer-Encoding: chunked: طول به شکل دیگری مشخص میشود
Content-Length و Truncation
اگر Entity Body کوتاهتر از مقدار Content-Length باشد، Client باید خطا گزارش دهد. اگر بلندتر باشد، Client اضافی را نادیده میگیرد.
Content-Type - نوع محتوا
Charset
برای محتوای متنی، Content-Type باید Charset هم داشته باشد:
1
2
Content-Type: text/html; charset=utf-8
Content-Type: text/plain; charset=iso-8859-1
اگر Charset مشخص نشود، گیرنده باید خودش Charset را حدس بزند - که میتواند اشتباه باشد.
Multipart - چند بخش در یک Body
گاهی یک Entity Body شامل چند بخش جداگانه است. برای مثال در Form Upload:
1
2
3
4
5
6
7
8
9
10
11
12
Content-Type: multipart/form-data; boundary=AaBb01
--AaBb01
Content-Disposition: form-data; name="username"
Joe
--AaBb01
Content-Disposition: form-data; name="file"; filename="report.pdf"
Content-Type: application/pdf
[PDF Binary Data]
--AaBb01--
boundary یک رشته یکتاست که بخشهای مختلف را از هم جدا میکند.
Content Encoding - فشردهسازی محتوا
چرا Encoding مهم است؟
قبل از ارسال، محتوا میتواند تبدیل شود - معمولاً فشردهسازی برای کاهش حجم.
1
[محتوای اصلی] ──[Encode]──▶ [محتوای فشرده] ──▶ شبکه ──▶ [Decode] ──▶ [محتوای اصلی]
انواع Content Encoding
| Encoding | توضیح |
|---|---|
gzip | رایجترین - معمولاً ۶۰-۸۰٪ حجم HTML را کاهش میدهد |
deflate | مبتنی بر الگوریتم zlib |
compress | قدیمی - کمتر استفاده میشود |
identity | هیچ تبدیلی نشده |
مذاکره Encoding با Accept-Encoding
Client به سرور میگوید چه Encoding هایی پشتیبانی میکند:
1
2
GET /index.html HTTP/1.1
Accept-Encoding: gzip, deflate;q=0.8, identity;q=0.5
سرور بهترین Encoding را انتخاب میکند و در Header اعلام میکند:
1
2
HTTP/1.1 200 OK
Content-Encoding: gzip
Transfer-Encoding و Chunked Encoding
تفاوت با Content-Encoding
| Content-Encoding | Transfer-Encoding | |
|---|---|---|
| سطح | روی محتوا (Entity) | روی انتقال (Transport) |
| ماندگاری | دائمی - Cache هم فشرده نگه میدارد | موقت - فقط برای این Transfer |
| هدف | کاهش حجم | مدیریت ارسال |
مشکلی که Chunked Encoding حل میکند
گاهی سرور نمیداند محتوا چقدر بزرگ است - مثلاً وقتی محتوا بهصورت Dynamic تولید میشود. در این حالت نمیتوان Content-Length را از قبل مشخص کرد.
Chunked Encoding راهحل است: محتوا به Chunk های کوچک تقسیم میشود و هر Chunk با اندازهاش ارسال میشود.
ساختار Chunked Encoding
1
2
3
4
5
6
7
8
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/html
19\r\n ← اندازه Chunk به هگزادسیمال (25 byte)
I'm a chunked message\r\n ← محتوای Chunk
0\r\n ← Chunk با اندازه صفر = پایان
\r\n
یک مثال واقعی با چند Chunk:
1
2
3
4
5
6
7
8
4\r\n
Wiki\r\n
6\r\n
pedia \r\n
E\r\n
in\r\n\r\nchunks.\r\n
0\r\n
\r\n
نتیجه: Wikipedia in\r\n\r\nchunks.
Range Requests - درخواست بخشی از محتوا
کاربرد
گاهی Client فقط بخشی از یک Resource را میخواهد:
- ادامه دانلود ناتمام: اگر دانلود قطع شود، فقط بخش باقیمانده درخواست شود
- Streaming: بارگذاری تدریجی یک فایل ویدیویی بزرگ
- Random Access: خواندن بخش خاصی از یک فایل بزرگ
درخواست Range
1
2
GET /bigfile.zip HTTP/1.1
Range: bytes=4000-8000
انواع Range:
1
2
3
4
5
Range: bytes=0-499 ← اولین ۵۰۰ Byte
Range: bytes=500-999 ← Byte های ۵۰۰ تا ۹۹۹
Range: bytes=-500 ← آخرین ۵۰۰ Byte
Range: bytes=500- ← از Byte 500 تا انتها
Range: bytes=0-0,-1 ← اولین و آخرین Byte
پاسخ سرور
اگر سرور از Range پشتیبانی کند:
1
2
3
4
5
HTTP/1.1 206 Partial Content
Content-Range: bytes 4000-8000/65535
Content-Length: 4001
[داده درخواستشده]
اگر سرور از Range پشتیبانی نکند، کل فایل را با 200 OK برمیگرداند.
Entity Digests - تأیید یکپارچگی
Content-MD5
سرور میتواند یک MD5 Checksum از Body محاسبه کند و در Header بگذارد:
1
Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Client بعد از دریافت، همین محاسبه را تکرار میکند. اگر نتایج یکسان بود، محتوا در مسیر تغییر نکرده.
محدودیت: Content-MD5 در Header قرار دارد. اگر مهاجم محتوا را تغییر دهد، میتواند MD5 را هم تغییر دهد. برای امنیت واقعی باید از HTTPS استفاده شود.
فصل شانزدهم - بخش اول: Internationalization و پشتیبانی HTTP از محتوای چندزبانه
چرا Internationalization مهم است؟
وب یک رسانه جهانی است. کاربران در ایران، ژاپن، روسیه و آلمان همگی از همان HTTP استفاده میکنند اما زبان، خط و Character Set کاملاً متفاوتی دارند.
HTTP باید بتواند:
- محتوای متنی به هر زبانی را منتقل کند
- به Client بگوید محتوا به چه زبان و Encoding ای است
- به Client اجازه دهد زبان مورد نظرش را اعلام کند
Character Set چیست؟
Character Set یک نگاشت بین کاراکترهای قابل نمایش و اعداد دیجیتال است.
مثال ساده:
1
2
3
4
در ASCII:
'A' → 65
'B' → 66
'a' → 97
اما ASCII فقط ۱۲۸ کاراکتر دارد - برای انگلیسی کافی است اما برای فارسی، عربی، چینی یا ژاپنی کاملاً ناکافی است.
تکامل Character Set ها
ASCII - نقطه شروع
اولین استاندارد. ۷ بیت، ۱۲۸ کاراکتر. فقط حروف لاتین، اعداد و نشانههای رایج.
ISO-8859 - خانواده Latin
برای حل محدودیت ASCII، مجموعهای از استانداردهای ۸ بیتی ساخته شد:
| استاندارد | پوشش |
|---|---|
ISO-8859-1 (Latin-1) | اروپای غربی |
ISO-8859-2 | اروپای مرکزی |
ISO-8859-6 | عربی |
ISO-8859-8 | عبری |
مشکل اصلی: هر استاندارد فقط یک زبان را پوشش میدهد. نمیتوان در یک سند هم عربی و هم ژاپنی داشت.
Unicode - راهحل جهانی
Unicode یک Character Set جهانی است که هدفش پوشش همه زبانهای دنیا در یک استاندارد واحد است.
1
2
3
4
5
'A' → U+0041
'ا' → U+0627
'あ' → U+3042
'中' → U+4E2D
'😀' → U+1F600
فعلاً بیش از 140,000 کاراکتر از بیش از 150 خط را پوشش میدهد.
Encoding - چطور Unicode را ذخیره کنیم؟
Unicode یک Character Set است - میگوید هر کاراکتر چه عددی دارد. اما Encoding میگوید آن عدد چطور به Byte تبدیل شود.
UTF-8 - رایجترین Encoding
UTF-8 یک Encoding متغیر طول است:
1
2
3
4
کاراکترهای ASCII: 1 Byte (سازگار با ASCII)
کاراکترهای اروپایی: 2 Byte
کاراکترهای آسیایی: 3 Byte
Emoji و موارد خاص: 4 Byte
مثال:
1
2
3
4
'A' → 0x41 (1 Byte)
'é' → 0xC3 0xA9 (2 Byte)
'ا' → 0xD8 0xA7 (2 Byte)
'あ' → 0xE3 0x81 0x82 (3 Byte)
مزیت اصلی UTF-8: کاملاً با ASCII سازگار است. هر فایل ASCII معتبر، یک فایل UTF-8 معتبر هم هست.
UTF-16 - برای زبانهای آسیایی بهینهتر
از ۲ یا ۴ Byte برای هر کاراکتر استفاده میکند. برای زبانهایی مثل چینی و ژاپنی که اکثر کاراکترهایشان در UTF-8 سه Byte نیاز دارند، کارآمدتر است.
Content-Type و Charset در HTTP
سرور باید هم نوع محتوا و هم Encoding آن را اعلام کند:
1
2
3
Content-Type: text/html; charset=utf-8
Content-Type: text/plain; charset=iso-8859-6
Content-Type: application/json; charset=utf-8
اگر Charset مشخص نباشد؟
HTTP/1.1 یک پیشفرض تعریف کرده: اگر Charset مشخص نشود، ISO-8859-1 فرض میشود.
هشدار: این پیشفرض برای توسعهدهندگان فارسیزبان خطرناک است. اگر سرور Charset را مشخص نکند و محتوا UTF-8 باشد، مرورگر ممکن است متن فارسی را بهدرستی نمایش ندهد. همیشه Charset را صریحاً مشخص کنید.
Accept-Charset - ترجیح Client
Client میتواند Charset های مورد پشتیبانی خود را اعلام کند:
1
Accept-Charset: iso-8859-1, utf-8;q=0.9, *;q=0.1
iso-8859-1با اولویت ۱.۰ (پیشفرض)utf-8با اولویت ۰.۹- هر Charset دیگری با اولویت ۰.۱
Language Tags - برچسب زبان
Content-Language Header
سرور زبان محتوا را اعلام میکند:
1
2
3
4
Content-Language: fa
Content-Language: en-US
Content-Language: zh-CN
Content-Language: ar-SA
ساختار Language Tag
Language Tag از بخشهای جداشده با - تشکیل میشود:
1
2
3
4
5
6
fa ← فارسی (زبان اصلی)
fa-IR ← فارسی ایران (زبان + منطقه)
en-US ← انگلیسی آمریکا
en-GB ← انگلیسی بریتانیا
zh-CN ← چینی سادهشده (چین)
zh-TW ← چینی سنتی (تایوان)
Accept-Language Header
Client زبانهای ترجیحی خود را اعلام میکند:
1
Accept-Language: fa, en;q=0.9, fr;q=0.5
سرور میتواند بر اساس این اطلاعات محتوای مناسب را انتخاب کند.
Internationalized URIs
مشکل
URI ها از ASCII طراحی شدهاند. اما URL هایی به فارسی، عربی یا چینی چطور؟
راهحل - Percent Encoding
کاراکترهای غیر ASCII ابتدا به UTF-8 تبدیل میشوند و سپس هر Byte با %XX نمایش داده میشود:
1
2
3
4
5
6
7
8
9
10
فارسی: "کتاب"
UTF-8 Bytes:
ک → 0xDA 0xA9
ت → 0xD8 0xAA
ا → 0xD8 0xA7
ب → 0xD8 0xA8
Encoded URL:
%DA%A9%D8%AA%D8%A7%D8%A8
IDN - Internationalized Domain Names
یک مشکل مشابه برای Domain Name ها وجود داشت. IDN (Internationalized Domain Names) استانداردی است که اجازه میدهد Domain Name به زبانهای غیر لاتین تعریف شود.
از طریق Punycode کاراکترهای غیر ASCII به یک فرمت ASCII قابل استفاده در DNS تبدیل میشوند:
1
"مثال.إختبار" → "xn--mgbh0fb.xn--kgbechtv"
Content Negotiation - انتخاب بهترین نسخه
HTTP یک مکانیزم برای مذاکره محتوا دارد. سرور میتواند چندین نسخه از یک Resource داشته باشد و بهترین را بر اساس ترجیحات Client انتخاب کند.
1
2
3
4
5
6
7
8
9
10
Client:
GET /index.html HTTP/1.1
Accept-Language: fa, en;q=0.8
Accept-Charset: utf-8
Server:
دارای: index.fa.html (فارسی، UTF-8)
index.en.html (انگلیسی، ISO-8859-1)
انتخاب: index.fa.html ← بهترین تطابق با ترجیح Client
سرور در Response توضیح میدهد چه انتخابی کرده:
1
2
3
4
HTTP/1.1 200 OK
Content-Language: fa
Content-Type: text/html; charset=utf-8
Vary: Accept-Language, Accept-Charset
Vary Header به Cache میگوید: «این Response برای همه کاربران یکسان نیست - بر اساس Accept-Language و Accept-Charset ممکن است متفاوت باشد.»
فصل هفدهم - Content Negotiation و Transcoding
مشکلی که Content Negotiation حل میکند
یک URL واحد ممکن است برای کاربران مختلف باید محتوای متفاوتی برگرداند:
- کاربر فرانسوی → صفحه به فرانسه
- کاربر با مرورگر موبایل → صفحه سبکتر و سادهتر
- کاربر با اتصال کند → تصاویر با کیفیت پایینتر
Content Negotiation مکانیزمی است که به سرور اجازه میدهد بهترین نسخه را برای هر Client انتخاب کند - بدون اینکه URL تغییر کند.
سه روش Content Negotiation
روش اول: Server-Driven Negotiation
Client ترجیحاتش را از طریق Accept Header ها اعلام میکند و سرور تصمیم میگیرد:
1
2
3
4
5
GET /index.html HTTP/1.1
Accept: text/html, application/xml;q=0.9, */*;q=0.8
Accept-Language: fa, en;q=0.7
Accept-Charset: utf-8, iso-8859-1;q=0.5
Accept-Encoding: gzip, deflate
مزایا:
- Client نیازی به دانستن URL های مختلف ندارد
- منطق انتخاب متمرکز در سرور است
معایب:
- سرور باید Header های زیادی بررسی کند
- Cache باید نسخههای مختلف را جداگانه Cache کند
- سرور نمیتواند همه ترجیحات Client را بداند - مثلاً اندازه صفحه نمایش
روش دوم: Client-Driven Negotiation (Agent-Driven)
سرور یک لیست از گزینههای موجود میفرستد و Client انتخاب میکند:
1
2
3
4
5
6
7
8
9
10
11
Client ──── GET /index.html ────────────────────────────▶ Server
Server ◀─── 300 Multiple Choices ──────────────────────── Server
Links:
- /index.fr.html (فرانسه)
- /index.en.html (انگلیسی)
- /index.fa.html (فارسی)
Client ──── GET /index.fa.html ─────────────────────────▶ Server
Server ◀─── 200 OK ─────────────────────────────────────── Server
مزایا:
- Client اطلاعات بیشتری دارد - میداند دقیقاً چه میخواهد
- Cache سادهتر است - هر URL یک نسخه مشخص دارد
معایب:
- یک Round-Trip اضافه - Latency بیشتر
- اتوماسیون سختتر است
روش سوم: Transparent Negotiation
یک Proxy هوشمند در مسیر، هم Accept Header های Client را میداند و هم گزینههای سرور را. خودش بهترین انتخاب را میکند - بدون دخالت Client یا Server.
1
Client ──── Request + Accept Headers ────▶ [Proxy هوشمند] ──── بهترین URL ────▶ Server
مزیت: هیچ Round-Trip اضافهای نیست و Cache بهینه است.
q-Value - اولویتبندی ترجیحات
در Accept Header ها، q (Quality Value) اولویت هر گزینه را مشخص میکند. مقدار بین 0.0 (کمترین اولویت) تا 1.0 (بیشترین اولویت) است:
1
Accept-Language: fa, en;q=0.9, fr;q=0.6, *;q=0.1
ترتیب اولویت:
fa- اولویت 1.0 (پیشفرض)en- اولویت 0.9fr- اولویت 0.6- هر زبان دیگری - اولویت 0.1
Vary Header و Cache
وقتی سرور Content Negotiation انجام میدهد، باید به Cache اطلاع دهد که این Response برای همه کاربران یکسان نیست. این کار از طریق Vary Header انجام میشود:
1
2
3
4
HTTP/1.1 200 OK
Content-Language: fa
Content-Type: text/html; charset=utf-8
Vary: Accept-Language, Accept-Encoding
این Vary Header به Cache میگوید: «اگر میخواهی این Response را Cache کنی، آن را جداگانه برای هر ترکیب Accept-Language و Accept-Encoding Cache کن.»
تأثیر Vary روی Cache Hit Rate
1
2
3
4
Request 1: Accept-Language: fa → Cache با کلید (URL + fa)
Request 2: Accept-Language: en → Cache با کلید (URL + en)
Request 3: Accept-Language: fa → Cache Hit!
Request 4: Accept-Language: fr → Cache Miss - باید از سرور بگیرد
Transcoding - تبدیل محتوا
Transcoding یک قدم فراتر از Content Negotiation است. بهجای انتخاب از بین نسخههای از پیش آماده، محتوا در لحظه تبدیل میشود.
Format Conversion
یک Proxy میتواند فرمت محتوا را تغییر دهد:
1
2
3
GIF → JPEG (برای کاهش حجم)
HTML → WML (برای دستگاههای موبایل قدیمی)
High-res → Low-res (برای اتصالات کند)
Encoding Conversion
محتوا از یک Encoding به Encoding دیگر تبدیل میشود:
1
ISO-8859-1 → UTF-8
Language Translation
نویسندگان اشاره میکنند که ترجمه خودکار محتوا از طریق Transcoding ممکن است - اما در سال ۲۰۰۲ هنوز در مرحله تحقیق بود.
دیدگاه امروزی: امروزه با وجود API های ترجمه مثل Google Translate API، این ایده کاملاً قابل پیادهسازی است.
Transcoding در دستگاههای موبایل
یکی از کاربردهای مهم Transcoding: تطبیق محتوا برای دستگاههای مختلف.
1
2
3
4
5
6
7
8
9
Origin Server
│
│ HTML کامل با تصاویر بزرگ
▼
[Transcoding Proxy]
│
├──▶ Desktop Browser → HTML کامل
├──▶ Mobile Browser → HTML سادهشده + تصاویر فشرده
└──▶ دستگاه قدیمی → متن ساده
Proxy بر اساس User-Agent Header نوع دستگاه را تشخیص میدهد و محتوا را مناسب آن دستگاه تبدیل میکند.
Feature Negotiation - فراتر از Content
نویسندگان یک مفهوم پیشرفتهتر را مطرح میکنند: Feature Negotiation - مذاکره درباره قابلیتهای Client، نه فقط فرمت محتوا.
مثال: اگر Client از JavaScript، Flash یا فونتهای خاص پشتیبانی میکند، سرور میتواند نسخه غنیتری از صفحه بفرستد.
این ایده در زمان نوشتن کتاب هنوز در حال استانداردسازی بود.
دیدگاه امروزی: در دنیای مدرن این مشکل با Responsive Design و Progressive Enhancement در سمت Client حل شده - بهجای اینکه سرور تصمیم بگیرد، CSS و JavaScript در مرورگر محتوا را تطبیق میدهند.
فصل هجدهم - Web Hosting و مدیریت ترافیک
Virtual Hosting - چند سایت روی یک سرور
مشکل
اگر هر سایت به یک سرور اختصاصی نیاز داشت، هزینهها بسیار بالا میرفت. Virtual Hosting اجازه میدهد چندین سایت روی یک سرور فیزیکی اجرا شوند.
چطور سرور میفهمد کدام سایت را بسرویسدهد؟
در HTTP/1.0 مشکلی وجود داشت: هر دو سایت یک IP داشتند و Request فقط شامل Path بود - نه Hostname کامل:
1
GET /index.html HTTP/1.0
سرور نمیدانست این Request برای کدام سایت است.
راهحل HTTP/1.1 - Host Header:
1
2
GET /index.html HTTP/1.1
Host: www.joes-hardware.com
HTTP/1.1 این Header را اجباری کرد. سرور از آن استفاده میکند تا بفهمد Request برای کدام Virtual Host است.
چهار روش پیادهسازی Virtual Hosting
روش اول - Virtual Hosting با Host Header (HTTP/1.1):
سادهترین و رایجترین روش. همه سایتها یک IP دارند و از Host Header برای تمایز استفاده میشود.
1
2
3
IP: 192.168.1.1
├── Host: www.joes-hardware.com → /docs/joe/
└── Host: www.marys-antiques.com → /docs/mary/
روش دوم - Virtual Hosting با IP های مختلف:
هر سایت IP جداگانه دارد. گرانتر (IP Address محدود است) اما با HTTP/1.0 هم کار میکند.
1
2
192.168.1.1 → www.joes-hardware.com
192.168.1.2 → www.marys-antiques.com
روش سوم - Virtual Hosting با Port های مختلف:
هر سایت روی Port متفاوتی اجرا میشود. مشکل: کاربر باید Port را در URL بنویسد - ناراحتکننده است.
1
2
192.168.1.1:80 → www.joes-hardware.com
192.168.1.1:8080 → www.marys-antiques.com
روش چهارم - ترکیب:
در عمل، سرورهای مدرن از ترکیب این روشها استفاده میکنند.
Making Web Sites Reliable - پایداری سرویس
Mirror Sites - آینهسازی
برای محتوای پرتقاضا، چندین سرور یکسان در مکانهای جغرافیایی مختلف قرار میگیرند:
1
2
3
کاربر ایران → سرور آسیا
کاربر اروپا → سرور اروپا
کاربر آمریکا → سرور آمریکا
Client به نزدیکترین سرور هدایت میشود - Latency کمتر، پهنای باند بهتر.
HTTP Redirects - هدایت به سرور مناسب
سادهترین روش: سرور اصلی Client را به Mirror مناسب Redirect میکند:
1
2
3
4
5
6
Client ──── GET /bigfile.zip ────────────▶ Master Server
Master Server ──── 302 Found ────────────▶ Client
Location: http://asia.joes-hardware.com/bigfile.zip
Client ──── GET /bigfile.zip ────────────▶ Asia Mirror
مشکل: یک Round-Trip اضافه - Client باید ابتدا به Master Server برود.
DNS-Based Load Balancing
DNS یک نام را به چندین IP نگاشت میکند. هر بار که یک DNS Query انجام میشود، یک IP متفاوت برمیگردد (Round-Robin):
1
2
3
4
www.joes-hardware.com → DNS
├── 192.168.1.1 (Request اول)
├── 192.168.1.2 (Request دوم)
└── 192.168.1.3 (Request سوم)
مشکل: DNS نمیداند کدام سرور سالم است. اگر یک سرور از کار بیفتد، DNS هنوز IP آن را برمیگرداند.
Web Traffic Management - مدیریت ترافیک
HTTP Load Balancer
یک Load Balancer جلوی چندین سرور قرار میگیرد و درخواستها را بین آنها توزیع میکند:
1
2
3
┌──▶ Server 1
Client ──▶ [LB] ───┼──▶ Server 2
└──▶ Server 3
الگوریتمهای رایج توزیع بار:
| الگوریتم | توضیح |
|---|---|
| Round-Robin | به نوبت به هر سرور |
| Least Connections | به سروری که کمترین Connection دارد |
| Weighted | بر اساس ظرفیت هر سرور |
| IP Hash | Client های یکسان همیشه به سرور یکسان |
Sticky Sessions - ماندن روی یک سرور
بعضی اپلیکیشنها نیاز دارند تمام Request های یک کاربر به همان سرور بروند - مثلاً وقتی Session دادهها روی حافظه سرور نگه داشته میشوند.
Load Balancer از Cookie یا IP Address برای تشخیص کاربر و هدایت به سرور مناسب استفاده میکند.
Surrogate Servers و Content Distribution
Surrogate (Reverse Proxy)
یک سرور که جلوی Origin Server قرار میگیرد. از دیدگاه Client، Surrogate همان Origin Server است.
1
2
3
4
Client ──── GET /index.html ────▶ [Surrogate]
│ Cache Miss
▼
[Origin Server]
تفاوت با Forward Proxy: Forward Proxy از طرف Client کار میکند. Surrogate از طرف Server کار میکند.
CDN - Content Delivery Network
CDN یک شبکه گسترده از Surrogate ها در سراسر دنیاست. محتوا در نزدیکترین Node به کاربر Cache میشود:
1
2
3
4
5
Origin Server (ایران)
│
├──▶ CDN Node آسیا ◀── کاربر ژاپن
├──▶ CDN Node اروپا ◀── کاربر آلمان
└──▶ CDN Node آمریکا ◀── کاربر برزیل
مزایا:
- محتوا از نزدیکترین نقطه تحویل داده میشود - Latency کمتر
- Origin Server از بار مستقیم کاربران محافظت میشود
- در برابر ترافیک ناگهانی (Flash Crowd) مقاوم است
Server Tracking - شناسایی سرور درست
IP Anycast
یک IP Address به چندین سرور در مکانهای مختلف تخصیص داده میشود. شبکه بهصورت خودکار ترافیک را به نزدیکترین سرور هدایت میکند.
1
2
3
4
همه سرورها IP یکسان دارند: 1.2.3.4
کاربر آسیا → Routing Table → سرور آسیا (1.2.3.4)
کاربر اروپا → Routing Table → سرور اروپا (1.2.3.4)
این روش امروز در DNS Root Server ها و CDN های بزرگ (مثل Cloudflare) استفاده میشود.
خلاصه معماری یک سایت پرترافیک
کتاب در پایان فصل معماری کاملی از یک سایت واقعی ترسیم میکند:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
کاربر
│
▼
[DNS با Round-Robin]
│
▼
[Load Balancer]
│
├── [Surrogate / Cache Layer]
│ │ Cache Miss
│ ▼
│ [Application Servers]
│ │
│ ▼
│ [Database Cluster]
│
└── [Static Content Servers]
(تصاویر، CSS، JS)
هر لایه یک هدف مشخص دارد:
- DNS: توزیع اولیه ترافیک بین Data Center ها
- Load Balancer: توزیع ترافیک بین سرورهای یک Data Center
- Surrogate: کاهش بار روی Application Server ها
- Application Server: پردازش منطق کسبوکار
- Database: ذخیره دادههای پایدار
فصل نوزدهم - WebDAV: نوشتن روی وب
WebDAV چیست؟
WebDAV (Web-based Distributed Authoring and Versioning) یک توسعه روی HTTP/1.1 است که اجازه میدهد کاربران از راه دور محتوا را روی Web Server ایجاد، ویرایش، حذف و مدیریت کنند - نه فقط بخوانند.
HTTP اصلی فقط برای خواندن طراحی شده بود:
GET- بخوانPOST- فرم بفرست
WebDAV متدهای جدیدی اضافه کرد که وب را به یک سیستم فایل توزیعشده تبدیل میکند.
متدهای جدید WebDAV
مدیریت محتوا
| متد | توضیح |
|---|---|
PUT | یک فایل جدید ایجاد یا یک فایل موجود را جایگزین کن |
DELETE | یک فایل یا Directory را حذف کن |
COPY | یک Resource را از یک URL به URL دیگر کپی کن |
MOVE | یک Resource را از یک URL به URL دیگر منتقل کن |
MKCOL | یک Collection (Directory) جدید بساز |
مدیریت Properties
| متد | توضیح |
|---|---|
PROPFIND | Properties یک Resource را بخوان |
PROPPATCH | Properties یک Resource را تغییر بده |
Locking - قفل کردن
| متد | توضیح |
|---|---|
LOCK | یک Resource را قفل کن تا دیگران نتوانند تغییر دهند |
UNLOCK | قفل را بردار |
Properties - ویژگیهای Resource
WebDAV مفهوم Properties را معرفی میکند - متادیتای قابل خواندن و نوشتن که به هر Resource متصل میشود.
Live Properties
Properties ای که توسط سرور مدیریت میشوند و بهصورت خودکار بهروز میشوند:
1
2
3
4
<DAV:getcontentlength> ← اندازه فایل
<DAV:getlastmodified> ← آخرین زمان تغییر
<DAV:getcontenttype> ← نوع MIME
<DAV:displayname> ← نام نمایشی
Dead Properties
Properties ای که توسط کاربر تنظیم میشوند - سرور فقط آنها را ذخیره میکند:
1
2
<author>Mohammad Hossein Karami</author>
<category>Technical Documentation</category>
PROPFIND - خواندن Properties
1
2
3
4
5
6
7
8
9
PROPFIND /files/report.html HTTP/1.1
Host: www.joes-hardware.com
Content-Type: application/xml
Depth: 0
<?xml version="1.0" encoding="utf-8" ?>
<D:propfind xmlns:D="DAV:">
<D:allprop/>
</D:propfind>
پاسخ سرور:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
HTTP/1.1 207 Multi-Status
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:">
<D:response>
<D:href>/files/report.html</D:href>
<D:propstat>
<D:prop>
<D:getcontentlength>4525</D:getcontentlength>
<D:getlastmodified>Mon, 12 Jan 2025 09:25:00 GMT</D:getlastmodified>
<D:getcontenttype>text/html</D:getcontenttype>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
</D:multistatus>
Status Code 207: یک Status Code جدید که WebDAV اضافه کرده - Multi-Status. چون یک Request ممکن است روی چندین Resource اعمال شود و هر کدام نتیجه متفاوتی داشته باشند.
Collections - مجموعهها
در WebDAV، Collection معادل Directory است - یک Resource که میتواند شامل Resource های دیگر باشد.
MKCOL - ساختن Collection
1
2
MKCOL /files/new-project/ HTTP/1.1
Host: www.joes-hardware.com
پاسخ:
1
HTTP/1.1 201 Created
Depth Header - عمق عملیات
بسیاری از WebDAV Method ها یک Depth Header دارند که مشخص میکند عملیات چقدر عمیق اعمال شود:
1
2
3
Depth: 0 ← فقط روی Resource خودش
Depth: 1 ← Resource + فرزندان مستقیم
Depth: infinity ← Resource + تمام زیرمجموعهها
مثال: PROPFIND با Depth: infinity برای خواندن Properties همه فایلهای داخل یک Directory و زیرDirectory های آن.
Locking - جلوگیری از ویرایش همزمان
یکی از مشکلات اصلی ویرایش توزیعشده: اگر دو نفر همزمان یک فایل را ویرایش کنند، یکی از تغییرات از دست میرود. WebDAV این مشکل را با Locking حل میکند.
انواع Lock
Exclusive Lock: فقط یک نفر میتواند Lock داشته باشد - دیگران نمیتوانند تغییر دهند:
1
2
3
4
5
6
7
8
9
10
11
LOCK /files/report.html HTTP/1.1
Host: www.joes-hardware.com
Timeout: Second-3600
Content-Type: application/xml
<?xml version="1.0" encoding="utf-8" ?>
<D:lockinfo xmlns:D="DAV:">
<D:lockscope><D:exclusive/></D:lockscope>
<D:locktype><D:write/></D:locktype>
<D:owner>Mohammad Hossein</D:owner>
</D:lockinfo>
پاسخ سرور شامل یک Lock Token است:
1
2
HTTP/1.1 200 OK
Lock-Token: <opaquelocktoken:e71d4fae-5dec-11d9-b0fc>
Shared Lock: چند نفر میتوانند همزمان Lock داشته باشند - برای خواندن مشترک.
Lock Token - کلید قفل
برای هر عملیاتی که روی Resource قفلشده انجام میشود، باید Lock Token فرستاده شود:
1
2
PUT /files/report.html HTTP/1.1
If: (<opaquelocktoken:e71d4fae-5dec-11d9-b0fc>)
اگر Token اشتباه باشد یا Lock منقضی شده باشد، سرور 423 Locked برمیگرداند.
COPY و MOVE
COPY - کپی کردن Resource
1
2
3
4
COPY /files/report.html HTTP/1.1
Destination: http://www.joes-hardware.com/files/report-backup.html
Depth: infinity
Overwrite: T
Destination:آدرس مقصدDepth: infinityبرای کپی کامل یک Collection با تمام محتوایشOverwrite: Tاگر مقصد وجود دارد، جایگزین شود
MOVE - انتقال Resource
1
2
MOVE /files/old-report.html HTTP/1.1
Destination: http://www.joes-hardware.com/archive/old-report.html
تفاوت با COPY: بعد از انتقال، Resource اصلی حذف میشود.
Versioning - نسخهبندی (DeltaV)
WebDAV یک Extension به نام DeltaV دارد که نسخهبندی فایلها را اضافه میکند - مثل Git اما روی HTTP.
مفاهیم اصلی:
1
2
3
4
5
Version History
│
├── Version 1 ← نسخه اولیه
├── Version 2 ← بعد از ویرایش اول
└── Version 3 ← بعد از ویرایش دوم (نسخه فعلی)
با DeltaV میتوان:
- به نسخههای قبلی برگشت
- تفاوت بین نسخهها را دید
- تاریخچه تغییرات را ردیابی کرد
WebDAV در دنیای واقعی
نویسندگان کاربردهای عملی WebDAV را ذکر میکنند:
- Microsoft Office: ذخیره مستقیم اسناد روی WebDAV Server
- macOS: اتصال به WebDAV Server مثل یک درایو شبکه
- Content Management Systems: پایه بسیاری از CMS های اولیه
- Subversion (SVN): سیستم کنترل نسخه که روی WebDAV ساخته شده
دیدگاه امروزی: WebDAV در دنیای مدرن جای خود را تا حدودی به REST API ها و سرویسهای Cloud Storage (مثل Google Drive API یا OneDrive API) داده. اما هنوز در بسیاری از سیستمهای Enterprise و ابزارهای مدیریت فایل مثل Nextcloud استفاده میشود.
جمعبندی کل کتاب
این کتاب یک سفر کامل از پایهترین مفاهیم تا پیچیدهترین جزئیات HTTP بود:
بخش اول - مبانی: HTTP Message ها، URL ها، Connection های TCP و معماری Web Server ها
بخش دوم - معماری شبکه: Proxy ها، Cache ها، Gateway ها، Tunnel ها و Web Robots
بخش سوم - امنیت و هویت: Cookie ها، Basic/Digest Authentication و HTTPS/TLS
بخش چهارم - محتوا: Encoding ها، Internationalization، Content Negotiation و Transcoding
بخش پنجم - توسعه وب: Virtual Hosting، Load Balancing، CDN و WebDAV
این کتاب در سال ۲۰۰۲ نوشته شده اما اصول بنیادین آن هنوز پایه HTTP/2 و HTTP/3 هستند. اگر میخواهی گام بعدی را بردار، پیشنهاد میکنم کتاب «High Performance Browser Networking» نوشته Ilya Grigorik را بخوانی - که مکمل مستقیم این کتاب است و HTTP/2، QUIC و بهینهسازیهای مدرن شبکه را پوشش میدهد.
