PHP
Python

Trang chủ

Cách triển khai CGI trong Python để xử lý yêu cầu web

Ngôn ngữ Python là một ngôn ngữ lập trình đa mục đích, nổi tiếng với cú pháp dễ đọc, dễ học và tính ứng dụng cao. Trong lĩnh vực phát triển web, Python thường được sử dụng thông qua các framework như Django và Flask để xây dựng các ứng dụng web mạnh mẽ, bảo mật và dễ mở rộng. Trong chuyên mục này, Vietnix không chỉ cung cấp kiến thức nền tảng về ngôn ngữ Python mà còn hướng dẫn chi tiết cách xây dựng các ứng dụng web thực tế, sử dụng các framework phổ biến và áp dụng các kỹ thuật tiên tiến. Vietnix cam kết liên tục cập nhật những bài viết mới nhất về các tính năng mới của Python, các thư viện hỗ trợ hữu ích và những phương pháp tốt nhất, giúp bạn khai thác tối đa sức mạnh của Python và hoàn thiện kỹ năng lập trình web của mình.
html
CSS
javascript
sql
python
php
c
c++
bootstrap
react
mysql
reactjs
vuejs
Javascript Tutorials
25/03/2025
30 phút đọc
Theo dõi Vietnix trên

Cách triển khai CGI trong Python để xử lý yêu cầu web

CGI trong Python là một giao thức tiêu chuẩn cho phép các ứng dụng web tương tác với máy chủ để xử lý yêu cầu từ người dùng. Việc triển khai CGI trong Python giúp tạo ra các ứng dụng web linh hoạt, dễ dàng tương tác với cơ sở dữ liệu và thực hiện các tác vụ phức tạp, mang lại hiệu suất và khả năng mở rộng cao. Bài viết này sẽ hướng dẫn bạn cách triển khai CGI trong Python để xử lý yêu cầu web, từ đó tối ưu hóa quá trình phát triển ứng dụng web.

Những điểm chính

  • Khái niệm: Hiểu về CGI (Common Gateway Interface) là gì và vai trò của nó trong việc xử lý dữ liệu từ trình duyệt web đến máy chủ.
  • Quá trình duyệt web và hỗ trợ máy chủ: Nắm được cách trình duyệt gửi yêu cầu, máy chủ phản hồi và cách cấu hình để hỗ trợ CGI.
  • Xây dựng chương trình CGI đầu tiên: Hướng dẫn cách viết và chạy một chương trình CGI cơ bản trong Python.
  • Các thành phần quan trọng trong CGI: Tìm hiểu HTTP Header, biến Environment CGI và phương thức truyền dữ liệu như GET, POST.
  • Tương tác với biểu mẫu HTML trong CGI: Biết cách xử lý dữ liệu từ các thành phần như Checkbox, Radio Button, Text Area và Drop Down Box.
  • Quản lý Cookie trong CGI: Cách thiết lập, lưu trữ và lấy lại Cookie để duy trì trạng thái người dùng.
  • Xử lý tệp trong CGI: Hướng dẫn cách thực hiện file upload và mở hộp thoại file download thông qua CGI.
  • Biết thêm Vietnix là nhà cung cấp dịch vụ lưu trữ chất lượng cao với hạ tầng mạnh mẽ và dịch vụ hỗ trợ chuyên nghiệp.
  • Câu hỏi thường gặp: Giải đáp các thắc mắc phổ biến khi làm việc với CGI trong Python.

CGI trong Python là gì?

Common Gateway Interface (CGI) trong Python là một tập hợp các tiêu chuẩn quy định cách thông tin được trao đổi giữa máy chủ web và các tập lệnh tùy chỉnh. CGI cho phép máy chủ HTTP giao tiếp với các chương trình bên ngoài, giúp xử lý dữ liệu và phản hồi yêu cầu từ trình duyệt một cách linh hoạt.

Common Gateway Interface (CGI) trong Python là một tập hợp các tiêu chuẩn quy định cách thông tin
Common Gateway Interface (CGI) trong Python là một tập hợp các tiêu chuẩn quy định cách thông tin

Hiện tại, phiên bản phổ biến của CGI là CGI/1.1, trong khi CGI/1.2 vẫn đang trong quá trình phát triển. Mặc dù CGI không còn là công nghệ mới, nhưng nó vẫn được sử dụng trong nhiều ứng dụng web yêu cầu xử lý dữ liệu động mà không cần đến các framework phức tạp.

Tìm hiểu về quá trình duyệt web

Khi bạn nhấp vào một liên kết hoặc nhập URL vào thanh địa chỉ trình duyệt, trình duyệt sẽ gửi yêu cầu đến máy chủ web thông qua giao thức HTTP. Yêu cầu này chứa thông tin về tệp cần truy cập, chẳng hạn như trang HTML hoặc tài nguyên liên quan. Máy chủ web tiếp nhận yêu cầu, phân tích URL để tìm tệp tương ứng. Nếu tệp tồn tại, máy chủ sẽ gửi nội dung của tệp về trình duyệt. Nếu không tìm thấy, máy chủ sẽ phản hồi bằng mã lỗi, chẳng hạn như lỗi 404 Not Found.

Ngoài việc chỉ gửi tệp tĩnh, máy chủ web có thể được cấu hình để thực thi các chương trình khi nhận được yêu cầu. Thay vì trả về một tệp có sẵn, máy chủ chạy chương trình và gửi kết quả đầu ra của nó về trình duyệt. Cơ chế này gọi là Common Gateway Interface (CGI), cho phép máy chủ xử lý các yêu cầu động. Các chương trình CGI có thể được viết bằng Python, Perl, Shell Script, C hoặc C++.

Tìm hiểu về quá trình duyệt web
Tìm hiểu về quá trình duyệt web

Hỗ trợ và cấu hình máy chủ web

Trước khi lập trình CGI trong Python, bạn cần đảm bảo rằng máy chủ web hỗ trợ CGI và đã được cấu hình để xử lý các chương trình CGI. Các chương trình CGI cần được đặt trong một thư mục được cấu hình sẵn, gọi là CGI Directory, theo mặc định thường là /var/www/cgi-bin. Các tập tin CGI thường có phần mở rộng .cgi, nhưng bạn cũng có thể sử dụng phần mở rộng .py để chạy các tập tin Python.

Trên các máy chủ Linux sử dụng Apache, mặc định chỉ các tập tin trong thư mục cgi-bin mới có thể chạy dưới dạng CGI. Nếu bạn muốn chạy các tập tin CGI từ một thư mục khác, bạn cần chỉnh sửa tập tin cấu hình httpd.conf bằng cách tìm và chỉnh sửa đoạn code sau:

<Directory "/var/www/cgi-bin">
AllowOverride None
Options ExecCGI
Order allow,deny
Allow from all
</Directory>

Bạn cũng có thể bật tất cả các tùy chọn trong thư mục cgi-bin bằng cách sửa lại như sau:

<Directory "/var/www/cgi-bin">
Options All
</Directory>

Ngoài ra, để Apache có thể nhận diện các tập tin .py như một script CGI, bạn cần thêm dòng sau vào cấu hình:

AddHandler cgi-script .py

Chương trình CGI đầu tiên

Để bắt đầu với CGI trong Python, bạn sẽ viết một chương trình đơn giản để hiển thị nội dung HTML trên trình duyệt. Chương trình này sẽ giúp bạn hiểu cách thức hoạt động của CGI cũng như cách máy chủ xử lý và phản hồi yêu cầu từ trình duyệt.

Trước tiên, bạn hãy tạo một tệp Python có tên hello.py trong thư mục /var/www/cgi-bin (đối với Linux) hoặc thư mục CGI được cấu hình trên máy chủ web. Nội dung của tệp như sau:

#!/usr/bin/python3
print("Content-type:text/html\r\n\r\n")
print("<html>")
print("<head>")
print("<title>Chương trình CGI đầu tiên</title>")
print("</head>")
print("<body>")
print("<h2>Chào mừng bạn đến với CGI trong Python!</h2>")
print("</body>")
print("</html>")

Giải thích đoạn code:

  • Dòng đầu tiên (#!/usr/bin/python3): Đây là shebang line, cho biết trình thông dịch Python sẽ được sử dụng để chạy tập tin này. Nếu sử dụng Windows, đường dẫn có thể là #!c:/python311/python.exe.

  • Dòng Content-type:text/html\r\n\r\n: Đây là tiêu đề HTTP (HTTP Header) bắt buộc, giúp trình duyệt hiểu rằng nội dung phản hồi là HTML.

  • Các dòng tiếp theo: Xuất code HTML ra trình duyệt để hiển thị nội dung.

Trước khi chạy chương trình, bạn cần cấp quyền thực thi cho tệp bằng lệnh sau trên Linux:

chmod 755 /var/www/cgi-bin/hello.py

Sau khi thiết lập đúng, bạn có thể chạy chương trình bằng cách nhập URL sau vào trình duyệt:

http://localhost/cgi-bin/hello.py

Nếu mọi thứ được thiết lập chính xác, bạn sẽ thấy thông báo:

Chào mừng bạn đến với CGI trong Python!

HTTP Header

HTTP Header là phần thông tin quan trọng được gửi từ máy chủ đến trình duyệt để xác định cách xử lý nội dung. Dòng Content-type:text/html\r\n\r\n là một phần của HTTP Header, giúp trình duyệt hiểu rằng nội dung trả về có định dạng HTML. Tất cả các HTTP Header đều có dạng chung như sau:

Tên Trường HTTP: Nội Dung Trường

Dưới đây là một số HTTP Header quan trọng thường được sử dụng trong lập trình CGI:

Số thứ tựHeaderMô tả
1Content-typeXác định định dạng MIME của nội dung trả về. Ví dụ: Content-type:text/html để báo trình duyệt xử lý nội dung dưới dạng HTML.
2Expires: DateXác định thời điểm thông tin trở nên không hợp lệ. Trình duyệt sử dụng thông tin này để quyết định khi nào cần tải lại trang. Ví dụ: Expires: Mon, 01 Jan 2025 12:00:00 GMT.
3Location: URLChuyển hướng yêu cầu đến một URL khác thay vì URL ban đầu. Điều này hữu ích khi cần điều hướng người dùng đến một trang thông báo hoặc một dịch vụ khác.
4Last-modified: DateChỉ ra thời điểm nội dung được chỉnh sửa lần cuối. Trình duyệt có thể sử dụng thông tin này để tối ưu bộ nhớ đệm.
5Content-length: NXác định độ dài dữ liệu (tính bằng byte) được gửi đến trình duyệt. Điều này giúp trình duyệt ước tính thời gian tải về nội dung.
6Set-Cookie: StringThiết lập cookie cho trình duyệt, hỗ trợ lưu trữ thông tin phiên làm việc của người dùng.

Biến Environment CGI

Trong lập trình CGI, các biến Environment đóng vai trò quan trọng trong việc xử lý yêu cầu từ phía máy khách và cung cấp thông tin về môi trường thực thi của script. Dưới đây là một số biến Environment phổ biến mà CGI sử dụng:

STTTên biếnMô tả
1CONTENT_TYPEXác định kiểu dữ liệu của nội dung được gửi từ máy khách, thường được sử dụng khi tải tệp lên máy chủ.
2CONTENT_LENGTHĐộ dài của dữ liệu được gửi qua phương thức POST.
3HTTP_COOKIEChứa thông tin cookie do trình duyệt gửi lên dưới dạng cặp key-value, giúp xác định phiên làm việc của người dùng.
4HTTP_USER_AGENTThông tin về trình duyệt hoặc ứng dụng gửi yêu cầu, thường được sử dụng để tối ưu hiển thị hoặc kiểm tra tương thích.
5PATH_INFOĐường dẫn đến script CGI được gọi.
6QUERY_STRINGChuỗi truy vấn được gửi kèm theo yêu cầu GET, giúp truyền dữ liệu qua URL.
7REMOTE_ADDRĐịa chỉ IP của máy khách gửi yêu cầu, thường được sử dụng để ghi log hoặc xác thực quyền truy cập.
8REMOTE_HOSTTên miền đầy đủ của máy khách, nếu có. Nếu không, có thể sử dụng REMOTE_ADDR để lấy địa chỉ IP.
9REQUEST_METHODPhương thức yêu cầu, thường là GET hoặc POST.
10SCRIPT_FILENAMEĐường dẫn đầy đủ đến script CGI đang chạy.
11SCRIPT_NAMETên của script CGI.
12SERVER_NAMETên hoặc địa chỉ IP của máy chủ xử lý yêu cầu.
13SERVER_SOFTWARETên và phiên bản phần mềm máy chủ web đang chạy.

Khi triển khai CGI trên một máy chủ web, các biến Environment này giúp lập trình viên lấy thông tin cần thiết để xử lý yêu cầu một cách chính xác và bảo mật hơn. Giả sử, bạn cần ghi log lại IP của người dùng truy cập vào website để kiểm soát truy cập. Bạn có thể sử dụng REMOTE_ADDR như sau:

import os
user_ip = os.environ.get('REMOTE_ADDR', 'Không xác định')
print("Content-type: text/html\r\n\r\n")
print(f"<p>Địa chỉ IP của bạn: {user_ip}</p>")

Phương thức GET và POST

Trong quá trình phát triển web, có nhiều tình huống cần truyền dữ liệu từ trình duyệt đến máy chủ web và sau đó đến chương trình CGI để xử lý. Hai phương thức phổ biến nhất để thực hiện điều này là GETPOST.

  • Phương thức GET: Dữ liệu được gửi dưới dạng chuỗi truy vấn (query string) gắn vào URL. Điều này giúp dễ dàng chia sẻ hoặc đánh dấu trang (bookmark), nhưng dữ liệu có giới hạn về độ dài và không an toàn khi truyền thông tin nhạy cảm.
  • Phương thức POST: Dữ liệu được gửi ẩn trong phần thân của yêu cầu HTTP, không hiển thị trên URL. Điều này giúp bảo mật hơn và cho phép truyền lượng lớn dữ liệu, thích hợp với biểu mẫu đăng nhập, đăng ký hoặc gửi thông tin quan trọng.

Truyền thông tin bằng phương thức GET

Phương thức GET truyền thông tin từ trình duyệt đến máy chủ web bằng cách mã hóa dữ liệu vào URL của yêu cầu. Dữ liệu và URL được phân tách bằng dấu ?, ví dụ:

http://www.vietnix.vn/cgi-bin/hello.py?name=NguyenVanA&service=hosting

Trong đó:

  • hello.py là tập tin xử lý yêu cầu trên máy chủ.

  • name=NguyenVanA&service=hosting là các cặp key-value được gửi đến máy chủ.

Phương thức GET là cách mặc định để truyền thông tin từ trình duyệt đến máy chủ web. Khi sử dụng phương thức này, dữ liệu được gắn trực tiếp vào URL và hiển thị trên thanh địa chỉ của trình duyệt.

Khi sử dụng GET cần:

  • Truy xuất dữ liệu từ CGI: Máy chủ có thể lấy dữ liệu từ yêu cầu GET thông qua biến môi trường QUERY_STRING.
  • Không nên sử dụng GET để truyền thông tin nhạy cảm, như mật khẩu hoặc dữ liệu cá nhân, vì nội dung yêu cầu hiển thị công khai trên URL.
  • Giới hạn độ dài dữ liệu: Một yêu cầu GET chỉ có thể chứa tối đa 1024 ký tự.

Dưới đây là một URL truyền hai tham số đến chương trình CGI hello_get.py bằng phương thức GET:

/cgi-bin/hello_get.py?first_name=Nguyen&last_name=VanA

Chương trình hello_get.py sẽ lấy dữ liệu từ URL và hiển thị kết quả:

#!/usr/bin/python3
# Import các module cần thiết
import cgi
# Tạo instance của FieldStorage
form = cgi.FieldStorage()
# Lấy dữ liệu từ các trường
first_name = form.getvalue('first_name')
last_name = form.getvalue('last_name')
# Xuất nội dung HTML
print("Content-type:text/html\r\n\r\n")
print("<html>")
print("<head>")
print("<title>Chương trình CGI đầu tiên</title>")
print("</head>")
print("<body>")
print("<h2>Xin chào, %s %s!</h2>" % (first_name, last_name))
print("</body>")
print("</html>")

Khi người dùng truy cập URL trên, máy chủ sẽ phản hồi:

Xin chào, Nguyen VanA!

Dưới đây là một biểu mẫu HTML cho phép người dùng nhập họ tên và gửi dữ liệu bằng phương thức GET:

<form action="/cgi-bin/hello_get.py" method="get">
   Họ: <input type="text" name="first_name"> <br>
   Tên: <input type="text" name="last_name"> <br>
   <input type="submit" value="Gửi">
</form>

Sau khi nhập thông tin và nhấn Gửi, trình duyệt sẽ chuyển hướng đến:

/cgi-bin/hello_get.py?first_name=Nguyen&last_name=VanA

Chương trình CGI sẽ hiển thị thông tin người dùng vừa nhập. Phương thức GET rất hữu ích trong các trường hợp cần truyền dữ liệu đơn giản mà không yêu cầu bảo mật cao.

Truyền thông tin bằng phương pháp POST

Phương pháp POST là một cách đáng tin cậy hơn để truyền dữ liệu đến chương trình CGI. Thay vì gửi dữ liệu dưới dạng chuỗi văn bản sau dấu ? trong URL như phương pháp GET, phương pháp POST đóng gói thông tin và gửi như một thông điệp riêng biệt. Thông điệp này được chương trình CGI nhận thông qua standard input (stdin), giúp tránh được các giới hạn về độ dài của URL và bảo mật thông tin tốt hơn.

Giả sử, người dùng muốn đăng ký một dịch vụ tại Vietnix bằng cách nhập họ và tên vào biểu mẫu. Khi nhấn nút gửi, dữ liệu sẽ được truyền đến tập lệnh CGI để xử lý:

  • Tập lệnh CGI (hello_post.py) xử lý yêu cầu:
# Import các module cần thiết
import cgi, cgitb  
# Tạo một instance của FieldStorage
form = cgi.FieldStorage()  
# Lấy dữ liệu từ biểu mẫu
first_name = form.getvalue('first_name')
last_name  = form.getvalue('last_name')
print("Content-type:text/html\r\n\r\n")
print("<html>")
print("<head>")
print("<title>Đăng ký thành công</title>")
print("</head>")
print("<body>")
print("<h2>Chào mừng %s %s!</h2>" % (first_name, last_name))
print("<p>Cảm ơn bạn đã đăng ký dịch vụ tại Vietnix.</p>")
print("</body>")
print("</html>")
  • Biểu mẫu HTML gửi dữ liệu qua phương thức POST:
<form action="/cgi-bin/hello_post.py" method="post">
  Họ: <input type="text" name="first_name"><br />
  Tên: <input type="text" name="last_name"><br />
  <input type="submit" value="Đăng ký">
</form>

Khi người dùng nhập họ và tên rồi nhấn “Đăng ký”, tập lệnh CGI sẽ nhận thông tin và phản hồi một trang HTML hiển thị lời chào mừng kèm theo thông báo xác nhận. Phương pháp POST phù hợp với các tình huống yêu cầu bảo mật cao hơn, chẳng hạn như gửi thông tin đăng ký, dữ liệu biểu mẫu hoặc thông tin đăng nhập.

Truyền dữ liệu Checkbox cho chương trình CGI

Checkbox là một thành phần HTML cho phép người dùng chọn nhiều tùy chọn cùng lúc. Khi gửi dữ liệu từ biểu mẫu HTML đến chương trình CGI, các giá trị của checkbox sẽ được xử lý để xác định trạng thái của chúng. Dưới đây là một ví dụ về biểu mẫu HTML chứa checkbox cho phép người dùng lựa chọn các dịch vụ:

<form action="/cgi-bin/checkbox.cgi" method="POST" target="_blank">
   <input type="checkbox" name="hosting" value="on" /> Web Hosting  
   <input type="checkbox" name="vps" value="on" /> VPS  
   <input type="checkbox" name="domain" value="on" /> Domain  
   <input type="submit" value="Chọn dịch vụ" />
</form>

Khi người dùng chọn một hoặc nhiều dịch vụ và nhấn nút gửi, dữ liệu sẽ được chuyển đến tập lệnh CGI để xử lý. Dưới đây là code Python để xử lý dữ liệu checkbox từ biểu mẫu trên:

#!/usr/bin/python3
# Import các module cần thiết
import cgi
# Tạo thể hiện của FieldStorage
form = cgi.FieldStorage()
# Lấy dữ liệu từ các checkbox
hosting_flag = "Đã chọn" if form.getvalue('hosting') else "Chưa chọn"
vps_flag = "Đã chọn" if form.getvalue('vps') else "Chưa chọn"
domain_flag = "Đã chọn" if form.getvalue('domain') else "Chưa chọn"
# Xuất nội dung HTML
print("Content-type:text/html\r\n\r\n")
print("<html>")
print("<head><title>Kết quả chọn dịch vụ</title></head>")
print("<body>")
print("<h2>Web Hosting: {}</h2>".format(hosting_flag))
print("<h2>VPS: {}</h2>".format(vps_flag))
print("<h2>Domain: {}</h2>".format(domain_flag))
print("</body></html>")

Khi chương trình CGI xử lý yêu cầu, nó sẽ kiểm tra từng checkbox xem người dùng có chọn hay không và hiển thị kết quả tương ứng. Cách tiếp cận này giúp bạn dễ dàng thu thập dữ liệu đầu vào từ người dùng và xử lý chúng theo nhu cầu thực tế.

Truyền dữ liệu Radio Button cho chương trình CGI

Radio Button được sử dụng khi người dùng chỉ có thể chọn một trong nhiều tùy chọn có sẵn. Trong CGI, dữ liệu từ Radio Button có thể được truyền đến máy chủ thông qua phương thức POST hoặc GET, giúp xử lý và phản hồi thông tin một cách linh hoạt. Dưới đây là ví dụ minh họa cách sử dụng Radio Button để người dùng chọn loại dịch vụ họ quan tâm trên trang web của Vietnix:

<form action="/cgi-bin/radiobutton.py" method="post" target="_blank">
   <input type="radio" name="service" value="hosting"> Web Hosting
   <input type="radio" name="service" value="vps"> VPS
   <input type="radio" name="service" value="server"> Thuê Máy Chủ  
   <input type="submit" value="Chọn Dịch Vụ">
</form>

Code Python xử lý dữ liệu từ Radio Button:

#!/usr/bin/python3
# Import thư viện CGI
import cgi, cgitb 
# Tạo thể hiện FieldStorage
form = cgi.FieldStorage() 
# Lấy giá trị được chọn
service = form.getvalue('service', 'Chưa chọn')
# Xuất nội dung HTML phản hồi
print("Content-type:text/html\r\n\r\n")
print("<html>")
print("<head>")
print("<title>Chọn Dịch Vụ - CGI Program</title>")
print("</head>")
print("<body>")
print(f"<h2>Bạn đã chọn dịch vụ: {service}</h2>")
print("</body>")
print("</html>")

Code Python trên sẽ lấy giá trị service mà người dùng chọn từ biểu mẫu và hiển thị thông tin phản hồi trên trình duyệt. Nếu không có lựa chọn nào, hệ thống sẽ thông báo “Chưa chọn”. Bằng cách sử dụng Radio Button trong CGI, người dùng có thể dễ dàng tương tác với hệ thống và gửi dữ liệu theo cách trực quan và tiện lợi.

Truyền dữ liệu Text Area cho chương trình CGI

Trong lập trình CGI với Python, thẻ <TEXTAREA> được sử dụng khi cần truyền nội dung văn bản nhiều dòng từ biểu mẫu HTML đến chương trình xử lý trên máy chủ. Điều này đặc biệt hữu ích trong các tình huống như thu thập phản hồi của người dùng, ghi chú, hoặc nhập nội dung dài hơn so với ô nhập liệu thông thường (<input type="text">).

Dưới đây là một ví dụ về cách tạo biểu mẫu HTML chứa TEXTAREA, giúp người dùng nhập nội dung và gửi đến chương trình CGI xử lý:

<form action="/cgi-bin/textarea.py" method="post" target="_blank">
   <textarea name="textcontent" cols="40" rows="4">Nhập nội dung của bạn...</textarea>
   <input type="submit" value="Gửi" />
</form>

Chương trình CGI nhận dữ liệu từ biểu mẫu này có thể được viết bằng Python như sau:

# Import module xử lý CGI
import cgi, cgitb  
# Tạo đối tượng lấy dữ liệu từ biểu mẫu
form = cgi.FieldStorage()  
# Lấy nội dung từ TEXTAREA
text_content = form.getvalue('textcontent', 'Không có nội dung được nhập')
# Xuất kết quả
print("Content-type:text/html\r\n\r\n")
print("<html>")
print("<head><title>Kết quả nhập liệu</title></head>")
print("<body>")
print(f"<h2>Nội dung đã nhập: {text_content}</h2>")
print("</body></html>")

Chương trình trên sẽ lấy nội dung nhập từ TEXTAREA và hiển thị lại trên trình duyệt sau khi gửi. Điều này có thể áp dụng để xử lý dữ liệu phản hồi từ khách hàng, lưu trữ nội dung bài viết, hoặc thu thập yêu cầu hỗ trợ trên trang web của bạn.

Truyền dữ liệu Drop Down Box cho chương trình CGI

Drop Down Box được sử dụng khi có nhiều tùy chọn nhưng chỉ một hoặc một vài giá trị có thể được chọn. Trong CGI, dữ liệu từ Drop Down Box được gửi đến máy chủ thông qua phương thức GET hoặc POST, sau đó được xử lý bằng script CGI để hiển thị hoặc lưu trữ thông tin.

Dưới đây là một ví dụ về biểu mẫu HTML sử dụng Drop Down Box để cho phép người dùng chọn một loại dịch vụ lưu trữ:

<form action="/cgi-bin/dropdown.py" method="post" target="_blank">
   <select name="dropdown">
      <option value="Shared Hosting" selected>Shared Hosting</option>
      <option value="VPS Hosting">VPS Hosting</option>
      <option value="Dedicated Server">Dedicated Server</option>
   </select>
   <input type="submit" value="Submit"/>
</form>

Khi người dùng chọn một tùy chọn và nhấn “Submit“, dữ liệu sẽ được gửi đến script dropdown.py để xử lý. Dưới đây là đoạn code Python sử dụng CGI để đọc và hiển thị giá trị đã chọn:

# Import modules for CGI handling
import cgi, cgitb 
# Create instance of FieldStorage
form = cgi.FieldStorage() 
# Get data from fields
if form.getvalue('dropdown'):
    service = form.getvalue('dropdown')
else:
    service = "Chưa chọn"
print("Content-type:text/html\r\n\r\n")
print("<html>")
print("<head>")
print("<title>Dropdown Box - CGI Example</title>")
print("</head>")
print("<body>")
print("<h2>Dịch vụ bạn đã chọn: %s</h2>" % service)
print("</body>")
print("</html>")

Khi thực thi script này, trang web sẽ hiển thị dịch vụ mà người dùng đã chọn từ danh sách Drop Down Box. Đây là cách hiệu quả để thu thập thông tin từ người dùng trong các biểu mẫu web và xử lý dữ liệu bằng CGI trong Python.

Giao thức HTTP là một giao thức không trạng thái (stateless), nghĩa là mỗi yêu cầu từ trình duyệt đến máy chủ đều được xử lý độc lập mà không lưu lại thông tin từ yêu cầu trước đó. Tuy nhiên, với các trang web thương mại hoặc hệ thống yêu cầu duy trì thông tin giữa nhiều trang, như quá trình đăng ký tài khoản hoặc theo dõi giỏ hàng, cần có cơ chế để lưu lại dữ liệu của người dùng trong suốt phiên làm việc.

Sử dụng Cookie trong CGI
Sử dụng Cookie trong CGI

Cookies là một trong những phương pháp hiệu quả nhất để ghi nhớ và theo dõi thông tin người dùng, bao gồm sở thích cá nhân, hành vi mua sắm hoặc dữ liệu phân tích trang web. Máy chủ gửi một đoạn dữ liệu đến trình duyệt của người dùng dưới dạng cookie. Nếu trình duyệt chấp nhận, cookie sẽ được lưu trữ dưới dạng tệp văn bản trên thiết bị của người dùng. Khi người dùng điều hướng sang các trang khác trên cùng một website, cookie có thể được truy xuất để phục vụ cho các mục đích như nhận diện người dùng, giữ trạng thái đăng nhập hoặc cá nhân hóa nội dung.

Một cookie thường bao gồm 5 thành phần chính:

  • Name = Value: Dữ liệu được lưu dưới dạng cặp khóa – giá trị.
  • Expires: Thời gian hết hạn của cookie. Nếu không có giá trị này, cookie sẽ bị xóa khi trình duyệt đóng.
  • Domain: Tên miền của website đặt cookie.
  • Path: Đường dẫn đến trang hoặc thư mục có thể truy xuất cookie.
  • Secure: Nếu có giá trị “secure”, cookie chỉ có thể được gửi qua kết nối HTTPS.

Giả sử, Vietnix muốn cá nhân hóa trải nghiệm người dùng trên trang quản lý hosting của mình. Khi khách hàng đăng nhập, hệ thống có thể sử dụng cookie để ghi nhớ trạng thái đăng nhập và hiển thị các gợi ý dịch vụ phù hợp.

Một đoạn code Python sử dụng CGI để đặt cookie có thể như sau:

import http.cookies
import datetime
print("Content-type: text/html")
cookie = http.cookies.SimpleCookie()
# Thiết lập cookie lưu trạng thái đăng nhập
cookie["user"] = "khach_hang_vietnix"
cookie["user"]["expires"] = (datetime.datetime.utcnow() + datetime.timedelta(days=7)).strftime("%a, %d-%b-%Y %H:%M:%S GMT")
print(cookie.output())
print()
print("<html><body>")
print("<h2>Cookie đã được thiết lập!</h2>")
print("</body></html>")

Trong Python, việc thiết lập cookie trên trình duyệt được thực hiện thông qua HTTP Header, cụ thể là sử dụng Set-Cookie. Cookie phải được gửi trước dòng "Content-type:text/html\r\n\r\n", nếu không, trình duyệt sẽ không nhận diện được. Giả sử, bạn cần thiết lập cookie để lưu thông tin đăng nhập của người dùng, có thể làm như sau:

print("Set-Cookie:UserID=ABC123;\r\n")
print("Set-Cookie:SessionToken=XYZ789;\r\n")
print("Set-Cookie:Expires=Fri, 31-Dec-2025 23:59:59 GMT;\r\n")
print("Set-Cookie:Domain=www.example.com;\r\n")
print("Set-Cookie:Path=/;\n")
print("Content-type:text/html\r\n\r\n")
print("<html><body>")
print("<h2>Cookie đã được thiết lập thành công!</h2>")
print("</body></html>")

Giải thích các thuộc tính chính của Cookie:

  • UserID, SessionToken: Các giá trị lưu trữ thông tin đăng nhập hoặc phiên làm việc của người dùng.

  • Expires: Xác định thời gian hết hạn của cookie, nếu không đặt, cookie sẽ bị xóa khi đóng trình duyệt.

  • Domain: Chỉ định tên miền có thể truy cập cookie, giúp kiểm soát phạm vi sử dụng.

  • Path: Xác định đường dẫn trong website có thể sử dụng cookie.

Việc sử dụng cookie đúng cách giúp tối ưu trải nghiệm người dùng, giảm thiểu việc nhập lại thông tin trên trang web. Nếu bạn đang triển khai hệ thống web hosting hoặc ứng dụng web, hãy đảm bảo thiết lập cookie đúng quy chuẩn để tăng cường bảo mật và hiệu suất.

Trong CGI Python, Cookie được lưu trữ trong biến môi trường HTTP_COOKIE. Việc lấy lại Cookie rất đơn giản, bạn chỉ cần truy cập giá trị của biến này và phân tách dữ liệu theo định dạng key=value.

Dưới đây là cách lấy lại Cookie trong một ứng dụng CGI:

# Import các module cần thiết
from os import environ
# Kiểm tra xem Cookie có tồn tại không
if 'HTTP_COOKIE' in environ:
    cookies = environ['HTTP_COOKIE'].split('; ')
    cookie_data = {}
    # Duyệt qua danh sách Cookie và lưu vào dictionary
    for cookie in cookies:
        key, value = cookie.split('=')
        cookie_data[key] = value
    # Lấy thông tin cụ thể từ Cookie
    user_id = cookie_data.get("UserID", "Không có UserID")
    session_token = cookie_data.get("SessionToken", "Không có SessionToken")
    print(f"User ID: {user_id}")
    print(f"Session Token: {session_token}")

Việc lấy lại Cookie giúp xác thực người dùng, duy trì trạng thái đăng nhập và lưu trữ các thông tin phiên làm việc. Trong các hệ thống web hosting, kỹ thuật này thường được sử dụng để nhận diện người dùng khi truy cập vào trang quản lý dịch vụ.

Ví dụ File Upload

Để tải lên tệp bằng CGI trong Python, biểu mẫu HTML cần có thuộc tính enctype được đặt thành multipart/form-data. Thẻ <input> với kiểu file sẽ tạo nút “Chọn tệp“. Dưới đây là một ví dụ về biểu mẫu HTML cho phép người dùng tải tệp lên máy chủ:

<html>
   <body>
      <form enctype="multipart/form-data" action="save_file.py" method="post">
         <p>File: <input type="file" name="filename" /></p>
         <p><input type="submit" value="Upload" /></p>
      </form>
   </body>
</html>

Code trên sẽ hiển thị một biểu mẫu với nút “Chọn tệp” và nút “Upload” để gửi tệp lên máy chủ. Khi người dùng chọn tệp và nhấn “Upload”, dữ liệu tệp sẽ được gửi đến tập lệnh xử lý save_file.py.

Dưới đây là tập lệnh CGI save_file.py để xử lý việc tải tệp lên:

import cgi
import os
import cgitb; cgitb.enable()  # Bật chế độ gỡ lỗi
form = cgi.FieldStorage()
# Lấy tệp tin từ biểu mẫu
fileitem = form['filename']
# Kiểm tra xem có tệp nào được tải lên không
if fileitem.filename:
    # Lấy tên tệp và ngăn chặn tấn công traversal
    fn = os.path.basename(fileitem.filename)
    upload_dir = "/var/www/uploads/"  # Thư mục lưu tệp trên máy chủ
    filepath = os.path.join(upload_dir, fn)
    # Lưu tệp lên máy chủ
    with open(filepath, 'wb') as f:
        f.write(fileitem.file.read())
    message = f'Tệp "{fn}" đã được tải lên thành công!'
else:
    message = "Không có tệp nào được tải lên."
print(f"""\
Content-Type: text/html\n
<html>
   <body>
      <p>{message}</p>
   </body>
</html>
""")

Khi triển khai trên máy chủ thực tế cần:

  • Quyền thư mục: Thư mục lưu trữ tệp phải có quyền ghi để cho phép lưu tệp.
  • Bảo mật: Kiểm tra kỹ tệp được tải lên để tránh các cuộc tấn công như thực thi mã độc.
  • Giới hạn kích thước: Thiết lập giới hạn kích thước tệp tải lên để tránh quá tải máy chủ.

Cách mở hộp thoại File Download

Trong một số trường hợp, bạn có thể muốn cung cấp tùy chọn cho người dùng tải xuống một tệp thay vì hiển thị nội dung trực tiếp trên trình duyệt. Điều này có thể được thực hiện dễ dàng bằng cách sử dụng HTTP Header để báo hiệu rằng tệp sẽ được tải xuống dưới dạng tệp đính kèm.

Để mở hộp thoại tải xuống, bạn cần gửi hai HTTP Header quan trọng:

  1. Content-Type: Xác định loại nội dung của tệp. Để đảm bảo trình duyệt xử lý tệp như một tệp tải xuống, bạn có thể sử dụng application/octet-stream.
  2. Content-Disposition: Chỉ định rằng tệp là một tệp đính kèm và cung cấp tên tệp gợi ý khi tải xuống.

Dưới đây là cách triển khai trong Python bằng CGI:

print("Content-Type: application/octet-stream; name=\"sample.txt\"\r\n")
print("Content-Disposition: attachment; filename=\"sample.txt\"\r\n\n")
# Mở tệp và đọc nội dung
with open("sample.txt", "rb") as fo:
    print(fo.read().decode("utf-8", errors="ignore"))

Các yếu tố quan trọng khi sử dụng:

  • Đảm bảo tệp tồn tại trên máy chủ trước khi thực hiện đọc và gửi dữ liệu.
  • Nếu tệp có dung lượng lớn, nên sử dụng phương pháp đọc và gửi theo từng phần (chunked transfer encoding) để tránh tiêu tốn quá nhiều bộ nhớ.
  • Khi triển khai trên hệ thống thực tế, hãy đảm bảo cấu hình máy chủ web hỗ trợ CGI và xử lý đúng MIME type để tránh lỗi khi tải xuống.

Vietnix – Nhà cung cấp dịch vụ lưu trữ chất lượng cao

Vietnix là một trong những đơn vị hàng đầu tại Việt Nam trong lĩnh vực web hostingVPSthuê máy chủ và domain, cung cấp giải pháp lưu trữ hiệu suất cao, bảo mật vượt trội. Với hạ tầng mạnh mẽ và đội ngũ hỗ trợ 24/7, Vietnix đảm bảo tốc độ truy cập nhanh, ổn định. Hơn 80.000 khách hàng đã tin tưởng sử dụng dịch vụ tại Vietnix. Liên hệ ngay để được tư vấn và trải nghiệm dịch vụ tốt nhất!

Thông tin liên hệ:

  • Website: https://vietnix.vn/
  • Hotline: 18001093
  • Email: sales@vietnix.com.vn 
  • Địa chỉ: 265 Hồng Lạc, Phường 10, Quận Tân Bình, Thành Phố Hồ Chí Minh.

Câu hỏi thường gặp

CGI có thể chạy trên các nền tảng serverless như AWS Lambda không?

Có, nhưng không thực tế. CGI yêu cầu khởi tạo tiến trình mới cho mỗi request, gây độ trễ cao, trong khi AWS Lambda tối ưu hóa việc tái sử dụng môi trường thực thi. Ngoài ra, CGI cần web server để gọi script, trong khi Lambda hoạt động qua API Gateway.
Giải pháp thay thế: Sử dụng Flask/FastAPI trên AWS Lambda hoặc triển khai CGI trên AWS EC2 với Apache/Nginx.

Tại sao CGI lại chậm hơn so với các framework web hiện đại, và có cách nào tối ưu tốc độ cho CGI không?

CGI chậm vì mỗi request tạo một tiến trình mới, không duy trì kết nối, giao tiếp chậm với máy chủ và không hỗ trợ xử lý bất đồng bộ. Điều này làm tăng chi phí tài nguyên, thời gian phản hồi và giảm hiệu suất khi xử lý lượng truy cập lớn.
Cách tối ưu tốc độ cho CGI:
Dùng FastCGI hoặc mod_wsgi để tái sử dụng tiến trình, giảm tải hệ thống.
Sử dụng caching (Redis, Memcached) để giảm truy vấn lặp lại.
Tối ưu mã nguồn bằng cách giảm thao tác nặng nề và tối ưu thuật toán.
Dùng máy chủ web phù hợp (Nginx + FastCGI thay vì Apache + CGI).
Chuyển sang framework hiện đại (Flask, FastAPI, Django) nếu cần hiệu suất cao hơn.

Lời kết

CGI trong Python cung cấp một cách đơn giản để xử lý các yêu cầu web động nhưng có hạn chế về hiệu suất và khả năng mở rộng. Dù không còn phổ biến trong các hệ thống hiện đại, hiểu về CGI vẫn giúp bạn nắm vững cách web server xử lý request và phản hồi, tạo nền tảng cho việc tiếp cận các công nghệ web tiên tiến hơn. Cảm ơn bạn đã theo dõi bài viết!

Mọi người cũng xem:

Cao Lê Viết Tiến

PHP Leader
tại
Vietnix

Kết nối với mình qua

Icon Quote
Icon Quote

Học lập trình online cùng vietnix

Học lập trình online cùng Vietnix

PHPXem thêmThu gọn