Python - Lập trình CGI: Hướng dẫn cho Người Mới Bắt Đầu

Xin chào các bạn, những phù thủy Python tương lai! Tôi rất vui được làm hướng dẫn cho các bạn trong hành trình thú vị vào thế giới lập trình CGI với Python. Như một người đã dạy khoa học máy tính trong nhiều năm, tôi có thể kể cho các bạn biết rằng CGI giống như sốt nguyệt sáng làm cho ứng dụng web của bạn sống động. Hãy cùng nhau gấp vai và bơi sâu vào điều này!

Python - CGI Programming

CGI là gì?

CGI đại diện cho Common Gateway Interface. Tôi biết điều này có vẻ như một cụm từ khó nhẹn, nhưng hãy suy nghĩ rằng nó là một dịch giả giữa máy chủ web của bạn và các script Python. Nó như có một người dịch viên thân thiện giúp máy chủ và mã của bạn giao tiếp một cách suôn sẻ.

CGI cho phép chúng ta tạo ra các trang web động có thể phản hồi vào đầu vào của người dùng. Hãy tưởng tượng một trang web chào bạn bằng tên của bạn hoặc hiển thị nội dung cá nhân hóa - đó chính là ma thuật của CGI đang hoạt động!

Trình duyệt Web

Trước khi chúng ta bước vào chi tiết của CGI, hãy nhanh chóng xem qua cách trình duyệt web hoạt động. Khi bạn gõ một URL vào trình duyệt, điều này sẽ xảy ra:

  1. Trình duyệt của bạn gửi một yêu cầu đến máy chủ web.
  2. Máy chủ web xử lý yêu cầu.
  3. Máy chủ gửi lại phản hồi, thường là dưới dạng một trang HTML.
  4. Trình duyệt của bạn hiển thị HTML này, hiển thị trang web bạn thấy.

CGI vào cuộc khi chúng ta muốn tạo ra nội dung động trong bước 3.

Sơ đồ Kiến trúc CGI

Dưới đây là một sơ đồ đơn giản để trực quan hóa cách CGI phù hợp vào kiến trúc web:

+-------------+    HTTP Request    +-------------+
|   Trình      | -----------------> |  Máy chủ    |
|   duyệt      | <----------------- |   Web       |
+-------------+    HTTP Response   +-------------+
|
| CGI
v
+-------------+
| Script CGI  |
| (Python)    |
+-------------+

Hỗ trợ và Cấu hình Máy chủ

Hầu hết các máy chủ web hỗ trợ CGI, bao gồm Apache và Nginx. Để sử dụng CGI với Python, bạn cần cấu hình máy chủ của mình để thực thi các script Python. Điều này thường liên quan đến việc thiết lập một thư mục đặc biệt cho các script CGI và cho máy chủ biết xem các tệp trong thư mục này là có thể thực thi.

Ví dụ, trong Apache, bạn có thể thêm một điều gì đó như thế này vào cấu hình của bạn:

<Directory /var/www/cgi-bin>
Options ExecCGI
AddHandler cgi-script .py
</Directory>

Điều này cho Apache biết để thực thi các tệp .py trong thư mục /var/www/cgi-bin như là các script CGI.

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

Hãy viết chương trình CGI đầu tiên của chúng ta! Chúng ta sẽ bắt đầu với ví dụ "Hello, World!" cổ điển. Tạo một tệp có tên hello.py trong thư mục CGI của bạn:

#!/usr/bin/env python3
print("Content-Type: text/html")
print()
print("<html>")
print("<head>")
print("<title>Hello World - First CGI Program</title>")
print("</head>")
print("<body>")
print("<h2>Hello World! This is my first CGI program</h2>")
print("</body>")
print("</html>")

Hãy phân tích điều này:

  1. Dòng đầu tiên cho máy chủ biết sử dụng Python để thực thi script này.
  2. Content-Type: text/html là một header HTTP cho biết trình duyệt chúng ta đang gửi HTML.
  3. Dòng trống print() phân cách các header từ nội dung phản hồi.
  4. Phần còn lại chỉ là HTML mà chúng ta đang tạo ra động.

Khi bạn truy cập script này thông qua trình duyệt web của bạn, bạn sẽ thấy một trang có nội dung "Hello World! This is my first CGI program".

HTTP Header

Trong lập trình CGI, việc gửi các header HTTP chính xác trước nội dung của bạn là rất quan trọng. Header phổ biến nhất là Content-Type, cho biết trình duyệt loại dữ liệu bạn đang gửi. Dưới đây là một số ví dụ:

Content Type Mô tả
text/html Nội dung HTML
text/plain Văn bản đơn
image/jpeg Ảnh JPEG
application/json Dữ liệu JSON

Luôn nhớ để gửi header Content-Type chính xác trước nội dung của bạn!

Các Biến Môi trường CGI

Các script CGI có quyền truy cập vào các biến môi trường khác nhau cung cấp thông tin về yêu cầu. Dưới đây là script hiển thị một số của các biến này:

#!/usr/bin/env python3
import os

print("Content-Type: text/html")
print()

print("<html><body>")
print("<h2>Environment Variables:</h2>")
for param in os.environ.keys():
print(f"<b>{param:20}</b>: {os.environ[param]}<br>")
print("</body></html>")

Script này sẽ hiển thị tất cả các biến môi trường có sẵn cho script CGI của bạn, bao gồm như loại trình duyệt của người dùng, tên máy chủ, và nhiều hơn nữa.

Phương thức GET và POST

Có hai phương thức chính để gửi dữ liệu đến script CGI: GET và POST. Hãy xem xét cả hai:

Phương thức GET

Phương thức GET gửi dữ liệu như một phần của URL. Dưới đây là một ví dụ đơn giản:

#!/usr/bin/env python3
import cgi

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
name = form.getvalue('name', 'World')

print("<html><body>")
print(f"<h2>Hello, {name}!</h2>")
print("</body></html>")

Bạn có thể truy cập script này với một URL như http://yourserver.com/cgi-bin/hello.py?name=Alice, và nó sẽ hiển thị "Hello, Alice!".

Phương thức POST

Phương thức POST gửi dữ liệu trong phần thân của yêu cầu HTTP. Nó thường được sử dụng cho các biểu mẫu. Dưới đây là một ví dụ:

#!/usr/bin/env python3
import cgi

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
name = form.getvalue('name', 'World')
email = form.getvalue('email', 'Not provided')

print("<html><body>")
print(f"<h2>Hello, {name}!</h2>")
print(f"<p>Your email is: {email}</p>")
print("</body></html>")

Script này có thể được sử dụng với một biểu mẫu HTML sử dụng phương thức POST.

Xử lý Các Element Biểu mẫu Khác nhau

CGI có thể xử lý nhiều loại element biểu mẫu khác nhau. Hãy xem một số ví dụ:

Checkboxes

#!/usr/bin/env python3
import cgi

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
hobbies = form.getlist('hobby')

print("<html><body>")
print("<h2>Your hobbies:</h2>")
for hobby in hobbies:
print(f"<p>{hobby}</p>")
print("</body></html>")

Radio Buttons

#!/usr/bin/env python3
import cgi

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
gender = form.getvalue('gender', 'Not specified')

print("<html><body>")
print(f"<h2>Your gender: {gender}</h2>")
print("</body></html>")

Text Area

#!/usr/bin/env python3
import cgi

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
message = form.getvalue('message', 'No message provided')

print("<html><body>")
print("<h2>Your message:</h2>")
print(f"<p>{message}</p>")
print("</body></html>")

Drop Down Box

#!/usr/bin/env python3
import cgi

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()
country = form.getvalue('country', 'Not selected')

print("<html><body>")
print(f"<h2>Your country: {country}</h2>")
print("</body></html>")

Sử dụng Cookies trong CGI

Cookies là cách để lưu trữ các mảnh dữ liệu nhỏ trên phía client. Chúng rất hữu ích để ghi nhớ các tùy chọn người dùng hoặc duy trì thông tin phiên. Dưới đây là cách bạn có thể làm việc với cookies trong CGI:

Đặt Cookies

#!/usr/bin/env python3
import cgi
from http import cookies
import datetime

# Tạo một cookie
c = cookies.SimpleCookie()
c['lastvisit'] = str(datetime.datetime.now())
c['lastvisit']['expires'] = 365 * 24 * 60 * 60  # hết hạn trong một năm

print(c)  # Điều này in ra header Set-Cookie
print("Content-Type: text/html")
print()

print("<html><body>")
print("<h2>Cookie set!</h2>")
print("</body></html>")

Truy xuất Cookies

#!/usr/bin/env python3
import os
from http import cookies

print("Content-Type: text/html")
print()

if 'HTTP_COOKIE' in os.environ:
cookie_string = os.environ.get('HTTP_COOKIE')
c = cookies.SimpleCookie()
c.load(cookie_string)
lastvisit = c.get('lastvisit')
if lastvisit:
print(f"<h2>Your last visit was: {lastvisit.value}</h2>")
else:
print("<h2>This is your first visit!</h2>")
else:
print("<h2>This is your first visit!</h2>")

Ví dụ Tải lên Tệp

Xử lý việc tải lên tệp là một chút phức tạp hơn, nhưng dưới đây là một ví dụ đơn giản:

#!/usr/bin/env python3
import cgi, os
import cgitb; cgitb.enable()

print("Content-Type: text/html")
print()

form = cgi.FieldStorage()

# Lấy tên tệp ở đây.
fileitem = form['filename']

# Kiểm tra xem tệp đã được tải lên hay chưa
if fileitem.filename:
# Loại bỏ đường dẫn dẵn trước tên tệp để tránh các cuộc tấn công truy cập thư mục
fn = os.path.basename(fileitem.filename)
open('/tmp/' + fn, 'wb').write(fileitem.file.read())
message = f'The file "{fn}" was uploaded successfully'
else:
message = 'No file was uploaded'

print(f"""\
<html>
<body>
<p>{message}</p>
</body>
</html>
""")

Làm thế nào để Mở hộp thoại "Tải xuống tệp"?

Để khởi động hộp thoại "Tải xuống tệp", bạn cần thiết lập các header phù hợp:

#!/usr/bin/env python3
import os

filename = "example.txt"  # Đây sẽ là tên tệp của bạn
filepath = "/path/to/your/file"  # Đây sẽ là đường dẫn đến tệp của bạn

print("Content-Type: application/octet-stream")
print(f"Content-Disposition: attachment; filename={filename}")
print()  # Dòng trống, kết thúc các header

# Bây giờ gửi nội dung tệp
with open(os.path.join(filepath, filename), 'rb') as f:
print(f.read())

Script này thiết lập Content-Type thành application/octet-stream, cho biết trình duyệt để tải xuống tệp thay vì hiển thị nó. Header Content-Disposition đề xuất một tên tệp cho tải xuống.

Và thế là đã xong, các bạn! Chúng ta đã bắt đầu với các khái niệm cơ bản của lập trình CGI với Python. Hãy nhớ rằng thực hành là chìa khóa để thành thạo, vì vậy đừng ngần ngại thử nghiệm với các ví dụ này và tạo ra những thứ của riêng bạn. Chúc mừng mã nguồn, và may các script CGI của bạn luôn chạy mượt mà!

Credits: Image by storyset