Cộng đồng chia sẻ tri thức Doc24.vn

Python - Lập trình CGI

Gửi bởi: Phạm Thọ Thái Dương vào ngày 2020-02-20 03:08:36

Mục lục
* * * * *

Giao diện cổng chung, hay CGI, là một bộ tiêu chuẩn xác định cách trao đổi thông tin giữa máy chủ web và tập lệnh tùy chỉnh. Thông số kỹ thuật CGI hiện đang được NCSA duy trì.

CGI là gì?

  1. Giao diện cổng chung, hay CGI, là một tiêu chuẩn cho các chương trình cổng ngoài để giao tiếp với các máy chủ thông tin như máy chủ HTTP.
  2. Phiên bản hiện tại là CGI / 1.1 và CGI / 1.2 đang được tiến hành.

Duyệt web

Để hiểu khái niệm về CGI, chúng ta hãy xem điều gì xảy ra khi chúng ta nhấp vào một siêu liên kết để duyệt một trang web hoặc URL cụ thể.

  1. Trình duyệt của bạn liên hệ với máy chủ web HTTP và yêu cầu URL, tức là tên tệp.
  2. Máy chủ Web phân tích cú pháp URL và tìm tên tệp. Nếu nó tìm thấy tệp đó thì gửi lại cho trình duyệt, nếu không sẽ gửi một thông báo lỗi cho biết rằng bạn đã yêu cầu một tệp sai.
  3. Trình duyệt web nhận phản hồi từ máy chủ web và hiển thị tệp đã nhận hoặc thông báo lỗi.

Tuy nhiên, có thể thiết lập máy chủ HTTP để bất cứ khi nào một tệp trong một thư mục nhất định được yêu cầu thì tệp đó không được gửi lại; thay vào đó, nó được thực thi như một chương trình và bất cứ điều gì mà đầu ra chương trình được gửi lại cho trình duyệt của bạn hiển thị. Chức năng này được gọi là Giao diện cổng chung hoặc CGI và các chương trình được gọi là tập lệnh CGI. Các chương trình CGI này có thể là Python Script, PERL Script, Shell Script, C hoặc C ++, v.v.

Sơ đồ kiến ​​trúc CGI

Cấu hình và hỗ trợ máy chủ Web

Trước khi bạn tiến hành Lập trình CGI, hãy đảm bảo rằng Máy chủ Web của bạn hỗ trợ CGI và nó được cấu hình để xử lý các Chương trình CGI. Tất cả các Chương trình CGI được thực hiện bởi máy chủ HTTP được giữ trong một thư mục được cấu hình sẵn. Thư mục này được gọi là Thư mục CGI và theo quy ước, nó được đặt tên là / var / www / cgi-bin. Theo quy ước, các tệp CGI có phần mở rộng là. cgi, nhưng bạn cũng có thể giữ các tệp của mình với phần mở rộng python .py .

Theo mặc định, máy chủ Linux được cấu hình để chỉ chạy các tập lệnh trong thư mục cgi-bin trong / var / www. Nếu bạn muốn chỉ định bất kỳ thư mục nào khác để chạy các tập lệnh CGI của mình, hãy nhận xét các dòng sau trong tệp httpd.conf -

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

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

Tại đây, chúng tôi giả định rằng bạn có Web Server hoạt động thành công và bạn có thể chạy bất kỳ chương trình CGI nào khác như Perl hoặc Shell, v.v.

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

Đây là một liên kết đơn giản, được liên kết với một tập lệnh CGI được gọi là hello.py . Tập tin này được giữ trong thư mục / var / www / cgi-bin và nó có nội dung như sau. Trước khi chạy chương trình CGI của bạn, hãy đảm bảo bạn có chế độ thay đổi tệp bằng cách sử dụng lệnh chmod 755 hello.py UNIX để thực hiện tệp.

#!/usr/bin/python

print "Content-type:text/html\r\n\r\n"
print '<html>'
print '<head>'
print '<title>Hello Word - First CGI Program</title>'
print '</head>'
print '<body>'
print '<h2>Hello Word! This is my first CGI program</h2>'
print '</body>'
print '</html>'

Nếu bạn nhấp vào hello.py, thì điều này sẽ tạo ra kết quả sau -

Từ xin chào! Đây là chương trình CGI đầu tiên của tôi

Tập lệnh hello.py này là một tập lệnh Python đơn giản, ghi đầu ra của nó trên tệp STDOUT, tức là màn hình. Có một tính năng quan trọng và bổ sung có sẵn, đó là dòng đầu tiên được in Kiểu nội dung: text / html \ r \ n \ r \ n . Dòng này được gửi trở lại trình duyệt và nó chỉ định loại nội dung sẽ được hiển thị trên màn hình trình duyệt.

Đến bây giờ bạn đã hiểu khái niệm cơ bản về CGI và bạn có thể viết nhiều chương trình CGI phức tạp bằng Python. Kịch bản lệnh này có thể tương tác với bất kỳ hệ thống bên ngoài nào khác để trao đổi thông tin như RDBMS.

Tiêu đề HTTP

Dòng Kiểu nội dung: text / html \ r \ n \ r \ n là một phần của tiêu đề HTTP được gửi đến trình duyệt để hiểu nội dung. Tất cả các tiêu đề HTTP sẽ ở dạng sau -

HTTP Field Name: Field Content

For Example
Content-type: text/html\r\n\r\n

Có một vài tiêu đề HTTP quan trọng khác mà bạn sẽ sử dụng thường xuyên trong Lập trình CGI

Biến môi trường CGI

Tất cả các chương trình CGI có quyền truy cập vào các biến môi trường sau đây. Các biến này đóng một vai trò quan trọng trong khi viết bất kỳ chương trình CGI nào.

Đây là chương trình CGI nhỏ để liệt kê tất cả các biến CGI. Nhấp vào liên kết này để xem kết quả Nhận Môi trường

#!/usr/bin/python

import os

print "Content-type: text/html\r\n\r\n";
print "<font size=+1>Environment</font><\br>";
for param in os.environ.keys():
   print "<b>%20s</b>: %s<\br>" % (param, os.environ[param])

Phương thức GET và POST

Bạn phải gặp nhiều tình huống khi bạn cần chuyển một số thông tin từ trình duyệt của mình đến máy chủ web và cuối cùng là Chương trình CGI của bạn. Thông thường nhất, trình duyệt sử dụng hai phương thức hai truyền thông tin này đến máy chủ web. Các phương thức này là Phương thức GET và Phương thức POST.

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

Phương thức GET gửi thông tin người dùng được mã hóa được nối vào yêu cầu trang. Trang và thông tin được mã hóa được phân tách bằng dấu? nhân vật như sau -

http://www.test.com/cgi-bin/hello.py?key1=value1&key2=value2

Phương thức GET là phương thức mặc định để truyền thông tin từ trình duyệt đến máy chủ web và nó tạo ra một chuỗi dài xuất hiện trong hộp Location: của trình duyệt của bạn. Không bao giờ sử dụng phương thức GET nếu bạn có mật khẩu hoặc thông tin nhạy cảm khác để truyền đến máy chủ. Phương thức GET có giới hạn kích thước: chỉ có thể gửi 1024 ký tự trong chuỗi yêu cầu. Phương thức GET gửi thông tin bằng tiêu đề QUERY_STRING và sẽ có thể truy cập được trong Chương trình CGI của bạn thông qua biến môi trường QUERY_STRING.

Bạn có thể truyền thông tin bằng cách ghép các cặp khóa và giá trị cùng với bất kỳ URL nào hoặc bạn có thể sử dụng thẻ <FORM> HTML để truyền thông tin bằng phương thức GET.

Ví dụ URL đơn giản: Phương thức Get

Đây là một URL đơn giản, chuyển hai giá trị cho chương trình hello_get.py bằng phương thức GET.

/cgi-bin/hello_get Kumfirst_name=ZARA&last_name=ALI

Dưới đây là tập lệnh hello_get.py để xử lý dữ liệu đầu vào được cung cấp bởi trình duyệt web. Chúng tôi sẽ sử dụng mô-đun cgi , giúp truy cập thông tin đã qua rất dễ dàng -

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
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>Hello - Second CGI Program</title>"
print "</head>"
print "<body>"
print "<h2>Hello %s %s</h2>" % (first_name, last_name)
print "</body>"
print "</html>"

Điều này sẽ tạo ra kết quả sau -

Xin chào ZARA ALI

Ví dụ đơn giản: Phương thức GET

Ví dụ này chuyển hai giá trị bằng cách sử dụng HTML FORM và nút gửi. Chúng tôi sử dụng cùng một tập lệnh CGI hello_get.py để xử lý đầu vào này.

<form action = "/cgi-bin/hello_get.py" method = "get">
First Name: <input type = "text" name = "first_name">  <br />

Last Name: <input type = "text" name = "last_name" />
<input type = "submit" value = "Submit" />
</form>

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

Một phương pháp thông thường đáng tin cậy hơn để truyền thông tin đến chương trình CGI là phương thức POST. Điều này gói thông tin theo cách chính xác giống như các phương thức GET, nhưng thay vì gửi nó dưới dạng một chuỗi văn bản sau một? trong URL nó sẽ gửi nó dưới dạng một tin nhắn riêng biệt. Thông báo này đi vào tập lệnh CGI dưới dạng đầu vào tiêu chuẩn.

Dưới đây là cùng một tập lệnh hello_get.py xử lý phương thức GET cũng như POST.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
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>Hello - Second CGI Program</title>"
print "</head>"
print "<body>"
print "<h2>Hello %s %s</h2>" % (first_name, last_name)
print "</body>"
print "</html>"

Chúng ta hãy lấy lại ví dụ tương tự như trên, vượt qua hai giá trị bằng cách sử dụng HTML FORM và nút gửi. Chúng tôi sử dụng cùng một tập lệnh CGI hello_get.py để xử lý đầu vào này.

<form action = "/cgi-bin/hello_get.py" method = "post">
First Name: <input type = "text" name = "first_name"><br />
Last Name: <input type = "text" name = "last_name" />

<input type = "submit" value = "Submit" />
</form>

Truyền dữ liệu hộp kiểm đến chương trình CGI

Các hộp kiểm được sử dụng khi cần chọn nhiều hơn một tùy chọn.

Dưới đây là ví dụ mã HTML cho một biểu mẫu có hai hộp kiểm -

<form action = "/cgi-bin/checkbox.cgi" method = "POST" target = "_blank">
<input type = "checkbox" name = "maths" value = "on" /> Maths
<input type = "checkbox" name = "physics" value = "on" /> Physics
<input type = "submit" value = "Select Subject" />
</form>

Dưới đây là script.cgi script để xử lý đầu vào được cung cấp bởi trình duyệt web cho nút hộp kiểm.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('maths'):
   math_flag = "ON"
else:
   math_flag = "OFF"

if form.getvalue('physics'):
   physics_flag = "ON"
else:
   physics_flag = "OFF"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Checkbox - Third CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> CheckBox Maths is : %s</h2>" % math_flag
print "<h2> CheckBox Physics is : %s</h2>" % physics_flag
print "</body>"
print "</html>"

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

Nút radio được sử dụng khi chỉ có một tùy chọn được yêu cầu được chọn.

Dưới đây là ví dụ mã HTML cho một biểu mẫu có hai nút radio -

<form action = "/cgi-bin/radiobutton.py" method = "post" target = "_blank">
<input type = "radio" name = "subject" value = "maths" /> Maths
<input type = "radio" name = "subject" value = "physics" /> Physics
<input type = "submit" value = "Select Subject" />
</form>

Dưới đây là tập lệnh radiobutton.py để xử lý đầu vào do trình duyệt web cung cấp cho nút radio -

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('subject'):
   subject = form.getvalue('subject')
else:
   subject = "Not set"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Radio - Fourth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Selected Subject is %s</h2>" % subject
print "</body>"
print "</html>"

Truyền dữ liệu vùng văn bản cho chương trình CGI

Phần tử TEXTAREA được sử dụng khi văn bản nhiều dòng phải được chuyển đến Chương trình CGI.

Dưới đây là ví dụ mã HTML cho một biểu mẫu với hộp TEXTAREA -

<form action = "/cgi-bin/textarea.py" method = "post" target = "_blank">
<textarea name = "textcontent" cols = "40" rows = "4">
Type your text here...
</textarea>
<input type = "submit" value = "Submit" />
</form>

Dưới đây là tập lệnh textarea.cgi để xử lý đầu vào được cung cấp bởi trình duyệt web -

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('textcontent'):
   text_content = form.getvalue('textcontent')
else:
   text_content = "Not entered"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>";
print "<title>Text Area - Fifth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Entered Text Content is %s</h2>" % text_content
print "</body>"

Truyền dữ liệu hộp thả xuống cho chương trình CGI

Hộp thả xuống được sử dụng khi chúng tôi có nhiều tùy chọn khả dụng nhưng chỉ một hoặc hai sẽ được chọn.

Dưới đây là ví dụ mã HTML cho một biểu mẫu với một hộp thả xuống -

<form action = "/cgi-bin/dropdown.py" method = "post" target = "_blank">
<select name = "dropdown">
<option value = "Maths" selected>Maths</option>
<option value = "Physics">Physics</option>
</select>
<input type = "submit" value = "Submit"/>
</form>

Dưới đây là tập lệnh dropdown.py để xử lý dữ liệu đầu vào được cung cấp bởi trình duyệt web.

#!/usr/bin/python

# Import modules for CGI handling 
import cgi, cgitb 

# Create instance of FieldStorage 
form = cgi.FieldStorage() 

# Get data from fields
if form.getvalue('dropdown'):
   subject = form.getvalue('dropdown')
else:
   subject = "Not entered"

print "Content-type:text/html\r\n\r\n"
print "<html>"
print "<head>"
print "<title>Dropdown Box - Sixth CGI Program</title>"
print "</head>"
print "<body>"
print "<h2> Selected Subject is %s</h2>" % subject
print "</body>"
print "</html>"

Sử dụng cookie trong CGI

Giao thức HTTP là một giao thức phi trạng thái. Đối với một trang web thương mại, cần phải duy trì thông tin phiên giữa các trang khác nhau. Ví dụ: một đăng ký người dùng kết thúc sau khi hoàn thành nhiều trang. Làm cách nào để duy trì thông tin phiên của người dùng trên tất cả các trang web?

Trong nhiều tình huống, sử dụng cookie là phương pháp hiệu quả nhất để ghi nhớ và theo dõi sở thích, mua hàng, hoa hồng và các thông tin khác cần thiết để có trải nghiệm khách truy cập hoặc thống kê trang web tốt hơn.

Làm thế nào nó hoạt động?

Máy chủ của bạn gửi một số dữ liệu tới trình duyệt của khách truy cập dưới dạng cookie. Trình duyệt có thể chấp nhận cookie. Nếu có, nó được lưu dưới dạng bản ghi văn bản đơn giản trên ổ cứng của khách truy cập. Bây giờ, khi khách truy cập đến một trang khác trên trang web của bạn, cookie có sẵn để truy xuất. Sau khi truy xuất, máy chủ của bạn biết / ghi nhớ những gì đã được lưu trữ.

Cookies là một bản ghi dữ liệu văn bản đơn giản của 5 trường có độ dài thay đổi -

  1. Hết hạn - Ngày cookie sẽ hết hạn. Nếu đây là trống, cookie sẽ hết hạn khi khách truy cập thoát khỏi trình duyệt.
  2. Tên miền - Tên miền của trang web của bạn.
  3. Đường dẫn - Đường dẫn đến thư mục hoặc trang web đặt cookie. Điều này có thể trống nếu bạn muốn lấy cookie từ bất kỳ thư mục hoặc trang.
  4. Bảo mật - Nếu trường này chứa từ "an toàn", thì cookie chỉ có thể được truy xuất với một máy chủ an toàn. Nếu trường này trống, không có hạn chế như vậy tồn tại.
  5. Tên = Giá trị - Cookies được đặt và truy xuất dưới dạng các cặp khóa và giá trị.

Thiết lập Cookies

Nó rất dễ dàng để gửi cookie đến trình duyệt. Các cookie này được gửi cùng với HTTP Header trước đến trường Kiểu nội dung. Giả sử bạn muốn đặt UserID và Mật khẩu làm cookie. Đặt cookie được thực hiện như sau -

#!/usr/bin/python

print "Set-Cookie:UserID = XYZ;\r\n"
print "Set-Cookie:Password = XYZ123;\r\n"
print "Set-Cookie:Expires = Tuesday, 31-Dec-2007 23:12:40 GMT";\r\n"
print "Set-Cookie:Domain = www.tutorialspoint.com;\r\n"
print "Set-Cookie:Path = /perl;\n"
print "Content-type:text/html\r\n\r\n"
...........Rest of the HTML Content....

Từ ví dụ này, bạn phải hiểu cách đặt cookie. Chúng tôi sử dụng tiêu đề HTTP Set-Cookie để đặt cookie.

Tùy chọn để đặt các thuộc tính cookie như Hết hạn, Miền và Đường dẫn. Đáng chú ý là cookie được đặt trước khi gửi dòng ma thuật "Kiểu nội dung: text / html \ r \ n \ r \ n .

Lấy cookie

Nó rất dễ dàng để lấy tất cả các cookie thiết lập. Cookies được lưu trữ trong biến môi trường CGI HTTP_COOKIE và chúng sẽ có dạng sau -

key1 = value1;key2 = value2;key3 = value3....

Dưới đây là một ví dụ về cách lấy cookie.

#!/usr/bin/python

# Import modules for CGI handling 
from os import environ
import cgi, cgitb

if environ.has_key('HTTP_COOKIE'):
   for cookie in map(strip, split(environ['HTTP_COOKIE'], ';')):
      (key, value ) = split(cookie, '=');
      if key == "UserID":
         user_id = value

      if key == "Password":
         password = value

print "User ID  = %s" % user_id
print "Password = %s" % password

Điều này tạo ra kết quả sau cho các cookie được đặt bởi tập lệnh trên -

User ID = XYZ
Password = XYZ123

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

Để tải lên một tệp, biểu mẫu HTML phải được đặt thuộc tính enctype thành nhiều dữ liệu / biểu mẫu . Thẻ đầu vào với loại tệp tạo nút "Duyệt".

<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>

Ví dụ trên đã bị vô hiệu hóa để lưu người tải lên tệp trên máy chủ của chúng tôi, nhưng bạn có thể thử mã ở trên với máy chủ của mình.

Đây là tập lệnh save_file.py để xử lý tải lên tệp -

#!/usr/bin/python

import cgi, os
import cgitb; cgitb.enable()

form = cgi.FieldStorage()

# Get filename here.
fileitem = form['filename']

# Test if the file was uploaded
if fileitem.filename:
   # strip leading path from file name to avoid 
   # directory traversal attacks
   fn = os.path.basename(fileitem.filename)
   open('/tmp/' + fn, 'wb').write(fileitem.file.read())

   message = 'The file "' + fn + '" was uploaded successfully'
   
else:
   message = 'No file was uploaded'
   
print """\
Content-Type: text/html\n
<html>
<body>
   <p>%s</p>
</body>
</html>
""" % (message,)

Nếu bạn chạy tập lệnh trên trên Unix / Linux, thì bạn cần phải thay thế trình phân tách tệp như sau, nếu không, trên máy tính windows của bạn, câu lệnh open () sẽ hoạt động tốt.

fn = os.path.basename(fileitem.filename.replace("\\", "/" ))

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

Đôi khi, bạn muốn cung cấp tùy chọn trong đó người dùng có thể nhấp vào liên kết và nó sẽ bật lên hộp thoại "Tải xuống tệp" cho người dùng thay vì hiển thị nội dung thực tế. Điều này rất dễ dàng và có thể đạt được thông qua tiêu đề HTTP. Tiêu đề HTTP này khác với tiêu đề được đề cập trong phần trước.

Ví dụ: nếu bạn muốn tạo tệp FileName có thể tải xuống từ một liên kết đã cho, thì cú pháp của nó là như sau -

#!/usr/bin/python

# HTTP Header
print "Content-Type:application/octet-stream; name = \"FileName\"\r\n";
print "Content-Disposition: attachment; filename = \"FileName\"\r\n\n";

# Actual File Content will go here.
fo = open("foo.txt", "rb")

str = fo.read();
print str

# Close opend file
fo.close()
Lượt xem: 213