# Cấu trúc của một HTTP request

## HTTP 1.x

Ở phiên bản này dữ liệu sẽ được xử lý theo dạng text based và gồm 3 phần chính theo thứ tự là:

1. [Request line](#request-line)
2. [Header](#header)
3. [Body](#request-line)

Mỗi phần gồm nhiều dòng mang thông tin và ngăn cách nhau bởi một dấu xuống dòng, quy ước chung là sử dụng **CRLF** - `\r\n`&#x20;

Giữa các phần cũng ngăn cách nhau bởi dấu xuống dòng, chỉ khác ở chỗ `Request line` và `Header` ngăn cách bởi một dấu xuống dòng còn `Header` và `Body` sẽ được ngăn cách bởi hai cái

<figure><img src="https://1733409716-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6ax1S9QFG8wQuzHtBrxS%2Fuploads%2FBuBt0eu2QI2SmS4nG9EB%2Fimage.png?alt=media&#x26;token=edc6d5ed-c63d-4aa8-9dd9-1879cf66baea" alt=""><figcaption></figcaption></figure>

### Request line

Đây là dòng đầu tiên của một request, gồm 3 phần theo thứ tự, cách nhau một dấu cách:

1. **Method** \
   \- Dùng để thông báo với server mục đích của request\
   \- Hai method phổ biến nhất là `GET` và `POST`
2. **Target**\
   \- Là phần `Path`  trong `URL`&#x20;
3. **HTTP Version**\
   **-** Chỉ phiên bản HTTP được sử dụng

### Header

Là phần thứ hai của một request, bao gồm nhiều dòng chứa thông tin bổ sung

Các header phổ biến có thể kể đến là:

* `Cookie`: cookie của người dùng
* `Host`: host và port của server
* `User-Agent`: một vài thông tin cơ bản về thiết bị gửi request
* `Content-Type`: chỉ định dạng mà dữ liệu trong phần `Body` sử dụng
* `Accept`: chỉ định dạng mong đợi của dữ liệu từ phía server trả về

### Body

Phần cuối cùng của một request, là nơi mà dữ liệu chính sẽ được gửi tới server

Thường được sử dụng với `Method` là `POST`, `PATCH` hoặc `PUT`&#x20;

***

## HTTP 2

Phiên bản này sử dụng binary protocol thay vì text based giống HTTP/1.x

Cụ thể, thay vì quét từng dòng của request để lấy thông tin thì ở HTTP 2, bên gửi sẽ gửi đi những tập tin được đóng gói được gọi là `frame`

Mỗi `frame` sẽ được bắt đầu bằng phần header dài 9 octets (1 octet = 8 bit) sau đó là phần dữ liệu thực tế

<figure><img src="https://1733409716-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F6ax1S9QFG8wQuzHtBrxS%2Fuploads%2FZdzFaonsmr8sfB58wNR0%2Fimage.png?alt=media&#x26;token=aa5ef512-58df-428a-9d80-99a1662cd1bd" alt=""><figcaption></figcaption></figure>

Hình trên là mô phỏng cấu trúc của một `frame` trong đó:

* **Length**: Độ dài của `Frame Payload` - chiếm 24 bits
* **Type**: Loại hay mục đích của frame đó - chiếm 8 bits
* **Flags**: Các thuộc tính thuộc về đúng loại `Type` của frame đó - chiếm 8 bits
* **Reserved**: Khi thiết kế họ để 1 bit này vì nghĩ rằng sau này sẽ dùng nhưng thực tế là không, ta có thể bỏ qua
* **Stream ID**: Stream mà frame này thuộc về (sẽ được giải thích ở phần sau)
* **Frame Payload**: Nội dung thực tế của frame, cấu trúc của nó sẽ do `Type` quyết định

Một cuộc trao đổi thông tin hoản chỉnh giữa client và server sẽ gồm nhiều `frame` với các kiểu `Type` khác nhau nhưng hai kiểu `Type` cần chú ý nhất là `HEADERS` (0x01) và `DATA` (0x00)

### HEADERS (0x01)

`Frame` này có vai trò tương tự như `Request line` và `Header` của HTTP / 1.x nhưng sẽ khác ở chỗ là có sự bổ sung của `Pseudo-headers`&#x20;

Có tổng cộng 5 `pseudo-headers`:

1. `:method` - Method được sử dụng, như là `GET` hoặc `POST`
2. `:path` - Phần path của url, tương tự `Target` bên HTTP / 1.x
3. `:authority` - Đóng vai trò gần tương tự như `Host` bên HTTP / 1.x
4. `:scheme` - Giao thức truyền tải dữ liệu được sử dụng, như là `http` và `https` (ở HTTP / 1.x không có cái gì tương tự)
5. `:status` - Status code của response, như là `200` hoặc `404`

Sau `pseudo-headers` sẽ đến các header thông thường như của HTTP / 1.x

> Thực tế các pseudo-headers không có dấu ":" ở đằng trước, đó chỉ là một cách viết để phân biệt với các headers thông thường
>
> Trong khi truyền thực tế, các pseudo-headers sẽ chỉ đơn giản là các bytes thuần

### DATA (0x00)

`Frame` này đóng vai trò tương tự như phần `Body` trong HTTP / 1.x, các dữ liệu thực tế được gửi đi sẽ nằm ở đây

***

Ngoài ra còn ti tỉ thứ khác nữa mà HTTP / 2 tạo ra nhằm mục đích tối ưu hóa đường truyền nhưng mình sẽ không đề cập ở đây, mọi người có thể tham khảo các tài liệu ở phần tiếp theo :duck:
