Những mẫu ghi chép vụn trong lúc đọc quyển HTTP Succinctly, quyển này chưa tới 60 trang nhưng cung cấp cho những người mới (cũng như những người cũ muốn ôn lại cũng như hệ thống hóa, bài bản hóa) kiến thức khá chi tiết và đầy đủ về dịch vụ HTTP - Từ Resources - URL, Request và Response, Connections, Web Architecture, State và Security…
Chapter 1 - Resources
Mọi thứ trên Internet (Các Trang Web, Hình ảnh, tập tin, File CSS, File Javascript…) đều được gọi là một Resource (tài nguyên), chúng được định danh bằng một địa chỉ gọi là URL (Uniform Resource Locator). Cấu trúc chung của một URL là:
<schema>://<host>:<port>/<path>?<query>#<fragment>
trong đó
-
schema: giao thức mà Server sử dụng, nó chỉ chúng ta làm thế nào để truy cập được vào tài nguyên đó. ví dụ: http, https, ftp, mailto
-
host: tên miền của máy tính đang giữ tài nguyên đó. (Thực chất là trình duyệt sẽ nhờ vào DNS để phân giải tên host thành IP nhờ vào đó các máy tính để có thể giao tiếp và nhìn thấy nhau trên mạng), ví dụ: food.com
-
port: nếu bạn không chỉ thị một con số cụ thể thì trình duyệt sẽ hiểu là 80 (đối với http) và 443 (đối với https).
-
path: đường dẫn cụ thể đến tài nguyên đó trên host. ví dụ: /recipe/grilled-cauliflower-19710/ (Có thể đó không phải là đường dẫn đến một tập tin thực sự mà một ứng dụng trên Web Server (ASP.NET, PHP, Ruby On Rails) sẽ xử lý đường dẫn này và trả về cho bạn thứ bạn muốn).
-
query: Tham số được truyền thêm vào để Server đích có thể sử dụng và có thể hiểu. các giá trị được truyền vào thêm dạng key-value và cách nhau bằng dấu &. ví dụ: first_name=Scott&last_name=Allen
-
fragment: Những thứ đằng sau dấu # được gọi là fragment. Ngược lại với Query, Server đích không đọc được fragment, nó chỉ được sử dụng ở phía client và thường được dùng để chỉ ra phần cụ thể của một tài nguyên. Ví dụ, bạn có thể hình dung mình có một trang html, trong đó có thẻ
<div id="feedback">...<div>
, khi chúng ta thêm #feedback vào url của trang thì trình duyệt sẽ tự động lăn đến thẻdiv
đó. Fragment còn được dùng nhiều trong các framework trên front-end như AngularJs.
URL Encoding
Trong URL có một số ký tự đặc biệt (unsafe characters) và để đưa các ký tự này vào URL thì chúng ta phải qua một bước mã hóa nó bằng percent-encoded (còn gọi là URL Encoded). Ví dụ “^my resume.txt” sẽ được mã hóa thành “%5my%20resume.txt”, trong đó ^ là %5 và khoảng trắng bị mã hóa thành %20. (Các con số này chính là giá trị trong hệ thập lục phân của ký tự đó trong bảng mã ASCII - Đọc thêm https://vi.wikipedia.org/wiki/ASCII)
Content-Type
Khi chúng ta request đến một URL, làm sao trình duyệt nhận biết được kết quả trả về là một tài nguyên gì? (Web, âm thanh, hình ảnh…) để có cách trình bày hoặc xử lý phù hợp. Đó là do khi Server response về kết quả, sẽ đính kèm thông tin content type trong đó. Content type sẽ theo chuẩn của MIME (Multipurpose Internet Mail Extensions), ví dụ như “text/html” sẽ cho biết tài nguyên này là định dạng html, “image/jpeg”, “image/png”, “image/gif”, “application/json”, “application/octet-stream”… Đọc thêm ở đây - https://en.wikipedia.org/wiki/Internet_media_type
Trình duyệt Web sẽ không sử dụng extension của tập tin để xác định nội dung đó vì File Extension thường là các chỉ dẫn lạc lối. Không có gì bảo đảm một file có đuôi là jpeg thì đích thực nó là định dạng jpeg cả. Do đó, trình duyệt Web sẽ dựa vào nội dung content type mà Server trả về, nếu không có thông tin đó thì nó sẽ đọc 200 bytes đầu tiên của file để đoán được content-type. Trường hợp bất đắc dĩ, trình duyệt mới nhờ đến File Extension để xác định định dạng của tài nguyên được trả về.
Bởi sẽ có trường hợp một URL nhưng có thể có đến vài định dạng tài nguyên khác nhau (ví dụ html, json, xml…) nên khi gửi request, client có thể thêm vào thông tin loại nội dung mà mình mong muốn được nhận. Server sẽ cố gắng trả về đúng loại nội dung đó cho client nếu có thể (Nếu không có loại nội dung client yêu cầu thì Server vẫn trả về loại nội dung mặc định). Đây gọi là Content Type Negetiation.
Chapter 2 - Messages
HTTP hoạt động theo mô hình client-server nên mọi tương tác (được gọi là phiên giao dịch http transaction) đều bao gồm 2 thông điệp là http request và http response. Mình đã có bài viết khá chi tiết về chủ đề này - http://notes.viphat.work/tong-quan-ve-tcp-ip-va-http/#toc7 nhưng cũng xin cóp nhặt một số kiến thức quan trọng từ sách để ôn lại
HTTP Request Methods
GET là một Safe Method, bởi vì (thông thường) Get Method chỉ dùng để lấy một tài nguyên từ Server chứ không làm thay đổi nó. còn POST thì ngược lại, do đó làm thay đổi tài nguyên nên mỗi khi mình refresh một trang được trả về bởi một POST request, trình duyệt web sẽ cảnh báo chúng ta bằng một hộp thoại như thế này:
Do vậy, một Pattern hay được Web Developer sử dụng là POST/Redirect/GET: Khi một POST Request gửi đến Server, Server sẽ xử lý và cập nhật lại Resource, sau đó redirect đến một trang GET khác để hiển thị kết quả.
HTTP Request Header
Một Request đầy đủ sẽ trông như thế này:
HTTP Response
Một số Response Code thông dụng:
Code | Reason | Description |
---|---|---|
200 | OK | The Status Code Everyone wants to see. A 200 code in the response means everything worked! |
301 | Moved Permanently | The resource has moved to the URL specified in the Location header and the client never needs to check this URL again. |
302 | Moved Temporarily | The resource has moved to the URL specified in the Location header. In the future, the client can still request the URL because it's a temporary move. This type of response code is typically used after a POST operation to move a client a resource it can retrieve with GET (The POST/Redirect/GET pattern). |
304 | Not modified | This is the server telling the client that the resource hasn't changed since the last time the client retrieved the resource, so it can just use a locally cached copy. |
400 | Bad Request | The server could not understand the request. The request probably used incorrect syntax. |
403 | Forbidden | The server refused access to the resource. |
404 | Not Found | A popular code meaning the resource was not found. |
500 | Internet Server Error | The server encountered an error in processing the request. Commonly happens because of programming errors in web application. |
503 | Service unavailable | The server will currrently not service the request. This status code can appear when a server is throttling requests because it is under heavy load. |
Cũng cần phải nhớ rằng HTTP status code chỉ trạng thái của những gì đang diễn ra ở mức HTTP. Nó không nhất thiết phải phản ánh đúng những gì đang diễn ra bên trong ứng dụng Web của bạn. Điều này nghĩa là khi người dùng cập nhật một Resource không thành công bởi vì Input của người dùng đưa vào có vấn đề thì Server nên trả về HTTP Status Code là 200 kèm theo một thông điệp lỗi chứ không nên là HTTP Status Code 4xx bởi vì đó không phải là lỗi ở mức HTTP.
Chapter 3 - Connections
Parallel Connections
Những năm gần đây, cùng với sự tiến bộ của công nghệ lập trình Web và tốc độ đường truyền Internet ngày càng được cải thiện, số lượng resources trung bình mà một trang web cần tải về trước khi render hoàn toàn sẽ ngày càng tăng. Và dĩ nhiên, chúng ta không thể kết nối đến Server theo kiểu one-by-one tuần tự như ngày trước nữa. Hiện nay, các Web Browser sẽ mở ra nhiều Parallel Connections (kết nối song song) đến Server để đồng thời tải nhiều resources về cùng một lúc.
Số lượng Parallel connection trên mỗi Host này tùy thuộc vào cấu hình của trình duyệt Web cũng như giới hạn của Host. Nếu tạo quá nhiều parallel connection sẽ dễ gây tắc nghẽn Network và làm quá tải Server bởi mỗi server đều có giới hạn về phần cứng, không thể đáp ứng quá nhiều kết nối cùng lúc. Hiện tại thì số lượng parallel connection giới hạn từ 2-8 (tùy trình duyệt Web).
Một cách để tối ưu Web Performance là chia các resources của trang web ra đặt ở nhiều Host khác nhau để tối đa hóa số lượng kết nối đồng thời và cũng tránh được việc gây quá tải cho một host nhất định.
Persistent Connections (HTTP Keep-Alive)
Ngày trước, mỗi khi trình duyệt web sẽ mở và đóng một connection sau mỗi lần một request riêng đã gửi đến Server. Việc cứ mở và đóng connection cho mỗi một request như vậy làm tăng chi phí xử lý, lưu trữ và làm quá tải Server một cách không cần thiết. Do vậy từ HTTP 1.0 và HTTP 1.1 đã cung cấp một loại kết nối mới là Persistent Connection và nó đã trở thành cách kết nối mặc định. Một kết nối Persistent connection vẫn mở sau khi một giao dịch request-response được hoàn thành trong một khoảng thời gian nhất định (được quy định trong Keep-Alive Timeout) để giao dịch request-response mới có thể sử dụng tiếp cho đến khi không còn một phiên giao dịch nào khác. Tuy nhiên, như đã nhắc ở phần trên, Một máy chủ chỉ phục vụ được hữu hạn số lượng kết nối cùng lúc nên nếu thiết lập thời gian giữ kết nối - Keep-Alive Timeout quá cao sẽ rất phí phạm khi Web Browser đã hoàn thành tất cả các Request-Response cần thiết để hiển thị trang nhưng các kết nối thì chưa được đóng lại.
Pipelined Connections
Ngoài Parallel connections và Persistent connections được sử dụng rộng rãi và được hỗ trợ bởi hầu hết clients cũng như servers. (Dĩ nhiên là trình duyệt web và web server đều phải hỗ trợ thì mới thiết lập được kết nối đó). HTTP còn hỗ trợ một dạng kết nối mới hơn là Pipelined Connections (Kết nối dạng đường ống), chúng sẽ thiết lập một “đường ống” kết nối giữa client và server, cho phép đóng gói nhiều request và truyền vào “đường ống” này cùng một lúc, việc này giúp làm giảm độ trễ và tăng tốc độ tải trang web. Tuy nhiên, do Pipelined Connections không được phổ biến và hỗ trợ rộng rãi bởi các Web Server cũng như trình duyệt Web nên gây ra nhiều vấn đề nhức nhối về tính tương thích. (Hầu hết Trình duyệt Web đã tắt chế độ Pipelined Connections này để tránh gây lỗi với Web Server đời cũ như IIS). Đọc thêm về Pipelined Connections - https://en.wikipedia.org/wiki/HTTP_pipelining
Chapter 4 - Web Architecture
Proxies
Mình đã có bài viết cụ thể về Proxy, Forward Proxy và Reverse Proxy. Trong HTTP Succinctly thì Khái niệm Proxy được phân loại tùy vào chức năng cụ thể của nó như:
-
Load Balancing Proxies can take a message and forward it to one of several web servers on a round-robin basis, or by knowing which server is currently processing the fewest number of requests.
-
SSL Acceleration Proxies can encrypt and decrypt HTTP messages, taking the encryption load off a web server.
-
Caching Proxies can store copies of frequently accessed resources and respond to messages requesting those resources directly.
Proxies can provide an additional layer of security by filtering out potentially dangerous HTTP messages. Specifically, messages that look like they might to trying to find a cross-site scripting (XSS) vulnerability or launch a SQL injection attack.
Caching
Caching is an optimization made to improve performance and scalability. When there are multiple requests for the same resource representation, a server can send the same bytes over the network time and time again for each request. Or, a proxy server or a client can cache the representation locally and reduce the amount of time and bandwidth required for a full retrieval. Caching can reduce latency, help prevent bottlenecks and allow a web application to survive when every user shows up at once to buy the newest product or see the latest press release. Caching is also a great example of how the metadata in the HTTP message headers facilitates additional layers and services.
Có 2 loại caches:
- Public cache là một cache chia sẻ giữa nhiều người dùng với nhau. Public cache thường ở trong một Proxy server. Một Public cache nằm trên một forward proxy thường sẽ caching các tài nguyên phổ dụng thuộc nhiều ứng dụng web khác nhau trong cộng đồng những người sử dụng chung forward proxy đó. Public cache nằm trên một reverse proxy thường dùng để caching các tài nguyên phổ dụng của một ứng dụng web cụ thể. Ví dụ như CSS, JS, hình ảnh hay Logo của Website.
- Private cache thuộc về từng user đơn lẻ. Trình duyệt Web luôn giữ private cache của các tài nguyên mà bạn đã truy cập trước đó vào ổ cứng của bạn (Thư mục Temporary Internet Files của các trình duyệt). Chúng sẽ được tái sử dụng nhằm tăng tốc quá trình truy cập lại các tài nguyên đó lần nữa.
- Trong HTTP 1.1, Response với Status là 200 của một HTTP GET request thì mặc định là có thể cache được. Ứng dụng Web có thể thay đổi đều này bằng cách sử dụng header thích hợp (Cache-Control) trong HTTP Response để cho phép hoặc không cho phép Resource đó được cache. Cache-Control chấp nhận giá trị là public, private hay no-cache và no-store (message chứa thông tin nhạy cảm và không được tồn tại, cần phải xóa khỏi bộ nhớ càng sớm càng tốt).
- HTTP 1.1 sử dụng chỉ thị Last-Modified và Expires trong HTTP Response để báo cho hệ thống caching biết là khi nào tài nguyên đã cached bị thay đổi hoặc hết hạn và cần phải thay mới chúng. Trong HTTP Request, chỉ thị If-Modified-Since để cho Server biết rằng client chỉ cần server trả về tài nguyên nếu tài nguyên đó đã bị thay đổi so với thời gian đề cập trong If-Modified-Since. Nếu không có gì thay đổi thì Server chỉ cần trả về thông điệp với status code là 304 - Not modified. Ngoài ra, còn một cách khác để làm được những việc này là thông qua chỉ thị ETag, nếu ETag của tài nguyên không khớp thì đã đến lúc hệ thống caching cần tải mới tài nguyên.
Chapter 5 - State and Security
The Stateless (Yet Stateful) Web
Một trong những đặc điểm khiến HTTP trở nên phổ dụng là vì bản thân nó mang tính Stateless. Do các phiên giao dịch request-response hoàn toàn độc lập khỏi các phiên giao dịch trong quá khứ cũng như tương lai nên giao thức HTTP không yêu cầu server giữ lại thông tin về mỗi HTTP request. Bản thân mỗi request đã mang đủ thông tin mà Server cần để tạo ra response. Do đặc điểm này mà nhờ đó hệ thống caching có thể hoạt động, và nếu không có Caching, thì có thể nói Hệ thống Mạng Internet đã không thể tồn tại nổi.
Nhưng nhu cầu thiết yếu của ứng dụng Web là chúng ta cần lưu lại các trạng thái của người dùng, vậy với đặc trưng “phi trạng thái” của giao thức HTTP thì phải làm như thế nào?
Cookies
Để khắc phục đặc điểm Stateless của HTTP, Cookies xuất hiện như một vị cứu tinh, nó được mệnh danh là “HTTP State Management Mechanism”. Khi người dùng lần đầu truy cập vào một website, site này sẽ đưa cho trình duyệt web của user một file cookie. Trình duyệt Web sau đó sẽ biết phải đính kèm cookie này vào trong Header mỗi khi gửi một Request đến Server. Nhờ vào Cookie mà chúng ta có thể lưu lại các trạng thái trước đó của người dùng và phân biệt được giữa ngườ dùng này và người dùng kia.
Session cũng hoạt động dựa trên Cookie, Session được tạo và lưu trữ trên Server còn Cookie sẽ ghi lại địa chỉ tham chiếu đến Session đó trên Server.
Có hai loại Cookie là Session Cookies và Persistent Cookies: Session Cookies chỉ tồn tại trong một phiên người dùng và sẽ bị xóa khi người dùng đóng trình duyệt Web. Còn Persistent Cookies được lưu thành file vào ổ cứng máy tính để rồi dù bạn có tắt máy đi chăng nữa thì khi bật máy lại, Cookie đó vẫn tồn tại và Trạng thái của bạn được bảo toàn. Điểm phân biệt giữa Session Cookies và Persistent Cookies là Persistent Cookies có thời hạn Expire cụ thể.
==Lưu ý về Domain trong Cookie, để thiết lập một Cookie có thể hoạt động khắp các Sub-Domain thì phải khai báo như thế nào? Nếu muốn thiết lập Cookie chỉ có hiệu lực ở một đường dẫn (path) cụ thể thì làm như thế nào?==
Third-party cookies (thường là cookies đến từ các trang quảng cáo hoặc các dịch vụ như google analytics) là cookie được thiết lập bởi các website với tên miền ngoài tên miền mà bạn đang truy cập. Third-party cookies có thể bị lợi dụng để theo dõi hành động của bạn trên Internet. Để bảo đảm tính riêng tư thì bạn có thể disallow third-party cookies của trình duyệt web.
Tuy nhiên Cookie cũng gặp phải nhiều vấn đề liên quan đến việc bảo mật và mạo danh.
Authentication
Để định danh người dùng Web, HTTP thường sử dụng một trong các giao thức xác thực sau:
-
Basic Authentication: Hình thức xác thực cơ bản nhất, và kém bảo mật nhất do bất kỳ ai bắt được gói tin đều có thể giải mã thông tin được truyền trong đó do chỉ mã hóa bằng base64 encoding.
-
Digest Authentication: Là giao thức cải tiến hơn so với Basic Authentication nhưng còn xa mới đạt được sự hoàn hảo. Chúng vẫn bị đánh lừa bởi phương pháp tấn công giả mạo “man-in-the-middle”. Nguyên tắc của Digest Authentication như sau: The server gives the client a one-time use string (a nonce) that it combines with the username, realm, password and the URI request. The client runs all of those fields through an MD5 hashing method to produce a hash key.It sends this hash key to the server along with the username and the realm to attempt to authenticate. On the Server-side, the same method is used to generate a hashkey, It looks up the stored password (in DB) for this username, runs in through the same algorithm and compares it to what the client sent. If they match: access is granted. Đọc thêm tại https://en.wikipedia.org/wiki/Digest_access_authentication
-
Windows Authentication: dùng cho máy chủ IIS và thường thấy trong Intranet Website. Không được dùng phổ biến trên Internet.
-
Forms-based Authentication: Đây là dạng xác thực thường gặp nhất, xuất hiện trong hầu hết các ứng dụng Web (cần định danh người dùng). Cũng như Basic Authentication, chúng không được bảo mật do thông tin được truyền đi dưới dạng plain-text nếu không sử dụng HTTPS. Nguyên tắc cơ bản là người dùng sẽ đăng nhập trên một form trong trang web và gửi thông tin username + mật khẩu đến Server, Server sẽ xác nhận và thiết lập cookie để chỉ ra rằng User đó đã được xác thực.
-
OAuth: OAuth cho phép sử dụng tài khoản của ứng dụng Web này để đăng nhập vào một ứng dụng Web khác.
-
OpenID: OpenID cho phép một định danh người dùng có thể được sử dụng ở nhiều ứng dụng Website khác nhau. OpenID hiện không còn được các Website sử dụng rộng rãi khi không được người dùng đón nhận.
Để phân biệt OAuth và OpenID, mới bạn đọc thêm bài viết dưới đây: http://softwareas.com/oauth-openid-youre-barking-up-the-wrong-tree-if-you-think-theyre-the-same-thing/
Secure HTTP
HTTPS đã được đề cập cụ thể trong bài viết Phân biệt HTTP và HTTPS, nên ở đây mình chỉ ghi lại một số thông tin cần lưu ý:
- All traffic over HTTPS is encrypted in the request and the response.
- The server is authenticated to the client thanks to the server certificate.
- HTTPS does not authenticate the client.