Tìm hiểu và hướng dẫn setup web server Nginx : Các biến môi trường và bổ từ của module HTTP trong NGINX
Bài đăng này đã không được cập nhật trong 3 năm
INDEX
1, Tìm hiểu và hướng dẫn setup web server Nginx : Các khái niệm cơ bản và các chỉ thị trong NGINX
MỞ ĐẦU
Trong bài viết trước, chúng ta đã đi tìm hiểu khái quát về module HTTP Core trong Nginx cũng như các thành phần cơ bản của nó và đặc biệt chúng ta đã tìm hiểu phần lớn nhất trong các chỉ thị của nó . Ngày hôm nay, chúng ta tiếp tục tìm hiểu về các biến môi trường và khối location
của chúng. Let start !
Các biến môi trường
Các biến môi trường ? Chúng là gì ấy nhỷ @@ Chắc hẳn với anh em developer thì cụm từ này quá quen thuộc rồi =)) nhưng thật sự để cắt nghĩa nó ra được gì thì mình cũng mất 1 khoảng kha khá thời gian để tìm hiểu (dựa vào hiểu biết của mình và hỏi bác google) thì mình xin đưa ra một khái niệm như sau :
Biến môi trường là những biến (giá trị) do Hệ điều hành (Service bạn sử dụng) cung cấp và sử dụng , vậy nên sự thay đổi của các biến môi trường (khi thay đổi môi trường chạy) sẽ ảnh hưởng đến quá trình thực thi của ứng dụng bạn dùng.
Viết xong đọc lại thấy khó hiểu vãi, cụ thể hơn 1 chút thì trong trường hợp biến môi trường của HTTP Core trong Nginx thì nôm na là chúng là các biến và các biến này có thể được sử dụng như giá trị của các chỉ thị, hoặc có thể được sử dụng trong các xử lý điều kiện của Nginx.
Các biến này được chia thành các nhóm chính sau:
1. Request headers
$http_host
Giá trị của thẻ Host trong phần header của HTTP, 1 chuỗi chỉ rõ hostname mà khách hàng muốn truy cập đến.
$http_user_agent
Giá trị của thẻ User-Agent trong phần header của HTTP, 1 chuỗi chỉ rõ trình duyệt web của khách hàng.
$http_referer
Giá trị của thẻ Referer trong phần header của HTTP, 1 chuỗi chỉ rõ URL của trang trước mà từ đó khách hàng truy cập đến.
$http_via
Giá trị của thẻ Via trong phần header của HTTP, thông báo cho chúng ta biết về các proxy có thể được dùng bởi khách hàng.
$http_x_forwarded_for
Giá trị của thẻ X-Forwarded-For trong phần header của HTTP, hiển thị IP thực sự của khách hàng nếu khách hàng đứng sau 1 proxy.
$http_cookie
Giá trị của thẻ Cookie trong phần header của HTTP, chứa dữ liệu lưu trong cookie được gửi bởi khách hàng.
$http_…
Các header bổ sung được gửi bởi khách hàng có thể thu được bằng việc sử dụng $http_ theo sau là tên thẻ header
viết bằng chữ thường và với dấu gạch ngang (-) thay cho dấu gạch dưới (_).
2. Response headers
$sent_http_content_type
Giá trị của thẻ Content-Type
trong phần header của HTTP, chỉ ra loại MIME của tài nguyên được truyền tải.
$sent_http_content_length
Giá trị của thẻ Content-Length
trong phần header của HTTP, thông báo cho khách hàng biết về chiều dài của dữ liệu phản hồi.
$sent_http_location
Giá trị của thẻ Location
trong phần header của HTTP, chỉ rằng vị trí của tài nguyên được yêu cầu khác với vị trí được chỉ rõ trong yêu cầu.
$sent_http_last_modified
Giá trị của thẻ Last-Modified
trong phần header của HTTP tương ứng với ngày điều chỉnh của tài nguyên được yêu cầu.
$sent_http_connection
Giá trị của thẻ Connection
trong phần header của HTTP, định nghĩa việc kết nối sẽ được duy trì hoặc đóng.
$sent_http_keep_alive
Giá trị của thẻ Keep-Alive
trong phần header của HTTP, định nghĩa lượng thời gian 1 kết nối sẽ được duy trì.
$sent_http_transfer_encoding
Giá trị của thẻ Transfer-Encoding
trong phần header của HTTP, cho thông tin về phương thức mã hóa dữ liệu phản hồi (như là nén, gzip).
$send_http_cache_control
Giá trị của thẻ Cache-Control
trong phần header của HTTP, cho chúng ta biết là trình duyệt web của khách hàng có lưu tài nguyên trong bộ nhớ cache hay không.
$send_http_…
Các thẻ bổ sung trong phần header của HTTP
được gửi đến khách hàng, có thể lấy được bằng việc sử dụng $sent_http_ theo sau là tên của thẻ trong header, viết bằng chữ thường và thay dấu gạch dưới (_) bằng dấu gạch ngang (-).
3. Nginx generated
$arg_XXX
Cho phép chúng ta truy cập chuỗi truy vấn (các thông số GET), với XXX là tên của thông số chúng ta muốn sử dụng.
$args
Tất cả các đối số của chuỗi truy vấn kết hợp với nhau.
$binary_remote_addr
Địa chỉ IP của khách hàng dưới dạng dữ liệu nhị phân (4 byte).
$body_bytes_sent
Số Byte được gửi trong phần thân của phản hồi.
$connection_requests
Số lượng yêu cầu đã phục vụ rồi ở kết nối hiện tại.
$content_length
Tương đương với thẻ Content-Length
.
$content_type
Tương đương với thẻ Content-Type
.
$cookie_XXX
Cho phép chúng ta truy cập dữ liệu trong cookie với XXX là tên của tham số mà chúng ta muốn sử dụng.
$document_root
Trả về giá trị của chỉ thị root cho yêu cầu hiện tại.
$document_uri
Trả về URI hiện tại của kết nối đó. Nó có thể khác với URI của yêu cầu ban đầu nếu các chuyển hướng nội bộ được thực hiện. Nó giống hệt với biến $uri
.
$host
Biến này tương đương với thẻ Host trong phần header của HTTP, tự Nginx cho biến này 1 giá trị cho nhiều trường hợp khi thẻ Host không được cung cấp trong yêu cầu ban đầu.
$hostname
Trả về hostname của máy chủ.
$https
Thiết lập thành on cho các kết nối HTTPS, ngược lại thì để trống.
$is_args
Nếu biến $args được định nghĩa, $is_args tương đương với ?. Nếu biến $args là rỗng, $is_args cũng rỗng. Chúng ta có thể sử dụng biến này cho việc khởi tạo 1 URI tùy chọn đi kèm với 1 chuỗi truy vấn, như là index.php?is_args$args. Nếu có bất kỳ đối số chuỗi truy vấn nào trong yêu cầu, $is_args được thiết lập thành ?, điều này giúp cho URI này hợp lệ.
$limit_rate
Trả về giới hạn tỉ lệ truyền tải trên từng kết nối, được định nghĩa bởi chỉ thị limit_rate. Chúng ta được cho phép để điều chỉnh biến này bằng việc sử dụng set (chỉ thị từ module Rewrite):
set $limit_rate 128k;
$nginx_version
Trả về phiên bản của Nginx đang chạy.
$pid
Trả về Process ID của Nginx.
$query_string
Giống hệt với $args.
$remote_addr
Trả về địa chỉ IP của khách hàng.
$remote_port
Trả về port socket của khách hàng.
$remote_user
Trả về username của khách hàng nếu họ sử dụng chứng thực.
$realpath_root
Trả về gốc tài liệu trong yêu cầu của khách hàng, với các liên kết mềm được xử lý thành các đường dẫn thực sự.
$request_body
Trả về phần thân của yêu cầu từ khách hàng, hoặc là – nếu như phần thân rỗng.
$request_body_file
Nếu phần thân của yêu cầu được lưu lại (chỉ thị client_body_in_file_only), biến này chỉ rõ đường dẫn của tập tin tạm đó.
$request_completion
Trả về OK nếu yêu cầu được hoàn thành, 1 chuỗi rỗng trong trường hợp ngược lại.
$request_filename
Trả về tên tập tin đầy đủ được phục vụ trong yêu cầu hiện tại.
$request_method
Chỉ rõ phương thức HTTP được dùng trong yêu cầu, như là GET hoặc POST.
$request_uri
Tương ứng với URI ban đầu của yêu cầu, giữ không thay đổi trong suốt tiến trình (không giống $document_uri/$uri).
$scheme
Trả về hoặc http hoặc https, dựa trên yêu cầu.
$server_addr
Trả về địa chỉ IP của máy chủ.
$server_name
Chỉ ra giá trị của chỉ thị server_name được dùng trong khi xử lý yêu cầu.
$server_port
Chỉ ra port của socket trên máy chủ nhận dữ liệu yêu cầu.
$server_protocol
Trả về giao thức và phiên bản, thường là HTTP/1.0 hoặc HTTP/1.1
$tcpinfo_rtt, $tcpinfo_rttvar, tcpinfo_snd_cwnd, $tcpinfo_rcv_space
Nếu hệ điều hành của chúng ta hỗ trợ tùy chọn socket TCP_INFO, những biến này sẽ được tạo với thông tin trên kết nối TCP hiện tại của khách hàng.
$time_iso8601, $time_local
Cung cấp thời gian hiện tại theo định dạng ISO 8601 và định dạng cục bộ để sử dụng với chỉ thị access_log.
$uri
Giống với biến $document_uri.
Chúng ta kết thúc việc tìm hiểu về các biến môi trường được cung cấp bởi module HTTP Core tại đây.
Khối location
Như bài trước mình đã nói, Nginx cung cấp cho chúng ta khả năng tinh chỉnh cấu hình xuống 3 cấp – tại cấp giao thức (khối http
), cấp máy chủ (khối server
) và cấp URI (khối location
).
Bây giờ, chúng ta sẽ bắt tay vào tìm hiểu đến thành phần cuối cùng được sử dụng trong việc cấu hình máy chủ HTTP trong Nginx, đó là các khối location
.
Nginx cho phép chúng ta định nghĩa các khối location bằng việc chỉ rõ 1 khuôn mẫu URI sẽ được dùng để đối chiếu với URI của yêu cầu. Ví dụ :
server {
server_name abc.com;
location /admin/ {
#Cấu hình đặt ở đây chỉ áp dụng cho đường dẫn http://abc.com/admin/
}
}
Tuy nhiên, thay vì sử dụng 1 tên thư mục đơn giản, chúng ta có thể sử dụng những khuôn mẫu phức tạp như:
location [=|~|~*|^~|@] pattern {…}
Các ký hiệu =|~|~*|^~|@ trong ví dụ trên được gọi là bộ bổ nghĩa cho location
, chúng định nghĩa cách Nginx đối chiếu 1 mẫu cụ thể với URI.Nào, bắt đầu tìm hiểu chúng nhé
1, BỔ TỪ =
URI phải khớp chính xác với khuôn mẫu được chỉ định. Khuôn mẫu ở đây được giới hạn là chuỗi ký tự bình thường, không được sử dụng biểu thức chính quy.
server {
server_name abc.com;
location = /abcd {
}
}
Ví dụ trên, ta sẽ có kết quả sau :
- Áp dụng cho http://abc.com/abcd (trùng khớp)
- Áp dụng cho http://abc.com/ABCD (phân biệt chữ hoa nếu như hệ điều hành của chúng ta sử dụng filesystem có phân biệt chữ hoa)
- Áp dụng cho http://abc.com/abcd?param1¶m2 (không quan tâm các đối số truy vấn)
- Không áp dụng cho http://abc.com/abcd/ (dư ký hiệu /)
- Không áp dụng cho http://abc.com/abcde
2, TRƯỜNG HỢP KHÔNG SỬ DỤNG BỔ TỪ
URI phải bắt đầu với 1 mẫu được chỉ định. Chúng ta không thể sử dụng biểu thức chính quy:
server {
server_name abc.com;
location /abcd {
}
}
Ví dụ trên, ta sẽ có kết quả sau :
- Áp dụng cho http://abc.com/abcd (trùng khớp)
- Áp dụng cho http://abc.com/ABCD (nếu hệ điều hành không phân biệt chữ hoa, chữ thường)
- Áp dụng cho http://abc.com/abcd?param1¶m2 (không quan tâm đối số chuỗi truy vấn)
- Áp dụng cho http://abc.com/abcd/ (bắt đầu với abcd)
- Áp dụng cho http://abc.com/abcde (bắt đầu với abcd)
3, BỔ TỪ ~
URI được yêu cầu phải khớp (phân biệt chữ hoa, chữ thường) với biểu thức chính quy được chỉ rõ:
server {
server_name abc.com;
location ~ ^/abcd$ {
}
}
Biểu thức chính quy ^/abcd$ => 1 mẫu phải bắt đầu với /, theo sau là abc, và kết thúc là d.
Ví dụ trên, ta sẽ có kết quả sau :
- Áp dụng cho http://abc.com/abcd (trùng khớp)
- Không áp dụng cho http://abc.com/ABCD (chữ hoa)
- Áp dụng cho http://abc.com/abcd?param1¶m2 (không quan tâm đến các đối số trong URI)
- Không áp dụng cho http://abc.com/abcd/ (ký hiệu / không khớp với biểu thức chính quy)
- Không áp dụng cho http://abc.com/abcde (thừa ký tự e)
NOTE_
Với những hệ điều hành như Microsoft Windows, ~ và ~* không phân biệt chữ hoa, chữ thường, vì hệ điều hành này sử dụng filesystem không phân biệt chữ hoa, chữ thường.
4, BỔ TỪ ~*
URI được yêu cầu phải khớp (không phân biệt chữ hoa, chữ thường) với 1 biểu thức chính quy được chỉ rõ.
server {
server_name abc.com;
location ~* ^/abcd$ {
...
}
}
Ví dụ trên, ta sẽ có kết quả sau :
- Áp dụng cho http://abc.com/abcd (trùng khớp)
- Áp dụng cho http://abc.com/ABCD (không phân biệt chữ hoa)
- Áp dụng cho http://abc.com/abcd?param1¶m2 (không quan tâm đối số trong chuỗi truy vấn)
- Không áp dụng cho http://abc.com/abcd/ (dư ký hiệu /)
- Không áp dụng cho http://abc.com/abcde (dư ký tự e)
5, BỔ TỪ ^~
Tương tự với trường hợp không dùng bổ từ, URI phải bắt đầu với 1 mẫu cụ thể. Sự khác nhau là nếu mẫu đó khớp, Nginx ngừng tìm kiếm các mẫu khác.
6, BỔ TỪ @
Định nghĩa 1 khối location được đặt tên. Khách hàng không thể truy cập những khối này, chúng chỉ có thể truy cập bởi các truy cập nội bộ được tạo ra bởi các chỉ thị khác, như là try_files hoặc error_page.
7, THỨ TỰ VÀ ĐỘ ƯU TIÊN KHI TÌM KIẾM CÁC KHỐI LOCATION
server {
server_name abc.com;
location /files/ {
# Khả dụng cho những đường dẫn bắt đầu bằng "/files"
# Ví dụ /files/doc.txt, /files/, /files/temp/
}
location = /files/ {
# Chỉ áp dụng cho đường dẫn "/files/"
}
}
Khi khách hàng truy cập http://abc.com/files/doc.txt
, khối location đầu tiên được sử dụng. Tuy nhiên, khi họ truy cập http://abc.com/files/
, khối location thứ 2 được sử dụng (mặc dù khối 1 cũng khớp) do nó có ưu tiên cao hơn khối thứ 1.
Thứ tự chúng ta đặt các khối location trong tập tin cấu hình không liên quan đến độ ưu tiên này. Nginx sẽ tìm các mẫu khớp theo 1 thứ tự cụ thể:
- Các khối location với bổ từ
=
: nếu chuỗi được chỉ rõ trùng khớp với URI, Nginx giữ lại khối location này. - Các khối location không sử dụng bổ từ: nếu chuỗi được chỉ rõ trùng khớp với URI, Nginx giữ lại khối location này.
- Các khối location sử dụng bổ từ
^~
: Nếu chuỗi chỉ rõ khớp với phần đầu của URI, Nginx giữ lại khối location này. - Các khối location sử dụng bổ từ
~
hoặc~*
: Nếu biểu thức chính quy khớp với URI, Nginx giữ lại khối location này. - Các khối location không sử dụng bổ từ: Nếu chuỗi được chỉ rõ khớp với phần đầu của URI, Nginx giữ lại khối location này.
Để rõ hơn, chúng ta cùng xem qua các ví dụ sau :
VD1:
server {
server_name abc.com;
# Block 1
location /doc {
[...] # đường dẫn bắt đầu với "/doc"
}
# Block 2
location ~* ^/document$ {
[...] #đường dẫn bắt chính xác "/document"
}
}
Khi khách hàng truy cập http://abc.com/document
- Block 1 (URI bắt đầu với
/doc
) => có thứ tự ưu tiên là 5. - Block 2 (URI khớp với biểu thức chính quy
^/document$
) => có thứ tự ưu tiên là 4.
=> Trong trường hợp này, Nginx sử dụng khối location thứ 2 cho truy cập trên.
VD2:
server {
server_name abc.com;
# Block 1
location /document {
[...] # đường dẫn bắt đầu với "/document "
}
# Block 2
location ~* ^/document$ {
[...] #đường dẫn bắt chính xác "/document"
}
}
Khách hàng truy cập http://abc.com/document
- Block 1 (chuỗi được chỉ định trùng khớp với URI) => thứ tự ưu tiên là 2.
- Block 2 (URI khớp với biểu thức chính quy) => thứ tự ưu tiên là 4.
=> Trong trường hợp này, Nginx sử dụng khối thứ 1 cho truy cập trên.
VD3:
server {
server_name abc.com;
# Block 1
location ^~ /doc {
[...] # đường dẫn bắt đầu với "/doc "
}
# Block 2
location ~* ^/document$ {
[...] #đường dẫn bắt chính xác "/document"
}
}
Khách hàng truy cập http://abc.com/document
- Block 1 (chuỗi khớp với phần đầu của URI) => thứ tự ưu tiên là 3.
- Block 2 (biểu thức chính quy khớp với URI) => thứ tự ưu tiên là 4.
=> Trong trường hợp này, Nginx sử dụng khối thứ 1 cho truy cập trên.
Lời cuối bài
OK, đến đây mình xin kết thúc bài tìm hiểu tại đây, do thời gian ít và kinh nghiệm còn thiếu nếu mình chỉ dựa vào vốn hiểu biết của mình và lên góp nhặt trên google (là chính =)) ) để hoàn thành bài viết. Thank you for watching !
Tài liệu tham khảo
https://viblo.asia/hoang.thi.tuan.dung/posts/ZabG912QGzY6
https://en.wikipedia.org/wiki/Nginx
https://www.nginx.com/resources/wiki/start/topics/examples/full/#
https://www.nginx.com/resources/admin-guide/installing-nginx-open-source/
All rights reserved