Lập trình HTTP trong Python

Một máy chủ web trong Python có thể được thiết lập theo hai cách. Python hỗ trợ một máy chủ web ngay lập tức. Bạn có thể bắt đầu một máy chủ web với một lớp lót

Nhưng bạn cũng có thể tạo một máy chủ web tùy chỉnh có chức năng độc đáo. Trong bài viết này, bạn sẽ học cách làm điều đó

Máy chủ web trong ví dụ này chỉ có thể được truy cập trên mạng cục bộ của bạn. Đây có thể là máy chủ cục bộ hoặc máy chủ mạng khác. Bạn có thể phục vụ nó qua nhiều vị trí với một VPN

khóa học liên quan. Hoàn thành khóa học & bài tập lập trình Python

Thí dụ

Máy chủ web dựng sẵn

Để khởi động một máy chủ web, hãy chạy lệnh bên dưới

1
python3 -m http.server

Điều đó sẽ mở một máy chủ web trên cổng 8080. Sau đó, bạn có thể mở trình duyệt của mình tại http. //127. 0. 0. 1. 8080/

Máy chủ web cũng có thể truy cập qua mạng bằng cách sử dụng 192. 168. -. - địa chỉ

Đây là máy chủ mặc định mà bạn có thể sử dụng để tải tệp xuống từ máy

máy chủ web

Chạy mã bên dưới để khởi động máy chủ web tùy chỉnh. Để tạo một máy chủ web tùy chỉnh, chúng ta cần sử dụng giao thức HTTP

Theo thiết kế, giao thức http có yêu cầu “lấy” trả về một tệp trên máy chủ. Nếu tệp được tìm thấy, nó sẽ trả về 200

Máy chủ sẽ bắt đầu tại cổng 8080 và chấp nhận các yêu cầu trình duyệt web mặc định

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Python 3 server example
from http.server import BaseHTTPRequestHandler, HTTPServer
import time

hostName = "localhost"
serverPort = 8080

class MyServer(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes("https://pythonbasics.org", "utf-8"))
self.wfile.write(bytes("

Request: %s

"
% self.path, "utf-8"))

self.wfile.write(bytes("", "utf-8"))
self.wfile.write(bytes("

This is an example web server.

"
, "utf-8"))

self.wfile.write(bytes("", "utf-8"))

if __name__ == "__main__":
webServer = HTTPServer((hostName, serverPort), MyServer)
print("Server started http://%s:%s" % (hostName, serverPort))

try:
webServer.serve_forever()
except KeyboardInterrupt:
pass

webServer.server_close()
print("Server stopped.")

Nếu bạn mở một url như http. //127. 0. 0. 1/ví dụ phương thức do_GET() được gọi. Chúng tôi gửi trang web theo cách thủ công theo phương thức này

Về bản chất, web hiện đại chỉ là văn bản qua lại giữa máy khách và máy chủ. Là nhà phát triển, chúng tôi thường sử dụng các khung web để giúp chúng tôi xây dựng các chuỗi để gửi cho khách hàng. Các khung web trừu tượng chúng ta khỏi "thực tế văn bản" cơ bản bằng cách phân tích cú pháp các yêu cầu http đến (chỉ là một chuỗi), gọi hàm tương ứng và tạo phản hồi chuỗi (chủ yếu bằng cách sử dụng các mẫu). Cuối cùng, khách hàng phân tích các chuỗi đó và làm bất cứ điều gì họ muốn từ nó

Bài đăng trên blog này cho thấy cách xây dựng một máy chủ HTTP barebones từ đầu và nó dựa trên một bài tập mà tôi đã đưa ra cho các sinh viên ThS của mình. Điều kiện tiên quyết duy nhất là hiểu biết cơ bản về Python 3. Nếu bạn muốn thực hiện điều này khi chúng tôi thực hiện, bạn có thể lấy ứng dụng bắt đầu từ liên kết này. Mã nguồn cuối cùng có thể được tìm thấy trong ý chính này

HTTP chỉ là văn bản

HTTP là giao thức mà trình duyệt sử dụng để truy xuất và đẩy thông tin đến máy chủ. Về bản chất, HTTP chỉ là văn bản tuân theo một mẫu nhất định. trên dòng đầu tiên bạn chỉ định tài nguyên nào bạn muốn, sau đó nó theo sau các tiêu đề và sau đó bạn có một dòng trống ngăn cách các tiêu đề với nội dung của thư (nếu có). Đây là cách bạn có thể truy xuất trang giới thiệu của một trang web

GET /about.html HTTP/1.0
User-Agent: Mozilla/5.0

Và đây là cách bạn có thể gửi một số dữ liệu biểu mẫu tới máy chủ web, sử dụng phương thức POST

POST /form.php HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 21

name=John&surname=Doe

Để chứng minh rằng đây chỉ là văn bản, bạn chỉ cần sao chép-dán văn bản ở trên và sử dụng thứ gì đó cho phép bạn gửi văn bản qua mạng. Hãy sử dụng telnet để lấy trang giới thiệu của google

$> telnet google.com 80
Trying 84.91.171.170...
Connected to google.com.
Escape character is '^]'.

(1)
GET /about/ HTTP/1.0

(2)
HTTP/1.0 200 OK
Vary: Accept-Encoding
Content-Type: text/html
Date: Thu, 09 Feb 2017 16:41:37 GMT
Expires: Thu, 09 Feb 2017 16:41:37 GMT
Cache-Control: private, max-age=0
Last-Modified: Thu, 08 Dec 2016 01:00:57 GMT
X-Content-Type-Options: nosniff
Server: sffe
X-XSS-Protection: 1; mode=block
Accept-Ranges: none


    "google mmfb" lang="en">
        
        ...


Connection closed by foreign host.

và gửi một tin nhắn POST tới http. //httpbin. tổ chức/bài đăng

$> telnet httpbin.org 80

Trying 54.175.219.8...
Connected to httpbin.org.
Escape character is '^]'.

(1)
POST /post HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 21

name=John&surname=Doe

(2)
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 09 Feb 2017 16:38:26 GMT
Content-Type: application/json
Content-Length: 328
Connection: close
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

{
  "form": {
    "name": "John",
    "surname": "Doe"
  },
  "headers": {
    "Content-Length": "21",
    "Content-Type": "application/x-www-form-urlencoded",
    "Host": "httpbin.org"
  },
  "url": "http://httpbin.org/post"
}
Connection closed by foreign host.

Bạn có thể thấy các yêu cầu HTTP (1) theo sau là phản hồi của máy chủ HTTP trong (2). Cùng một mẫu về các yêu cầu và phản hồi, và văn bản ở mọi nơi. Thông tin thêm về HTTP trên cuốn sách Mạng trình duyệt hiệu suất cao tuyệt vời

Gửi phản hồi HTTP bằng cách sử dụng ổ cắm

Nếu bạn dự định triển khai các ứng dụng mạng từ đầu, có thể bạn sẽ cần phải làm việc với ổ cắm mạng. Ổ cắm là một khái niệm trừu tượng được cung cấp bởi hệ điều hành của bạn, cho phép bạn gửi và nhận byte qua mạng. Đây là cách triển khai cơ bản của máy chủ HTTP (bạn có thể lấy nó từ liên kết này)

________số 8

Chúng tôi bắt đầu bằng cách xác định máy chủ ổ cắm và cổng. Sau đó, chúng tôi tạo biến server_socket và đặt nó thành AF_INET (họ địa chỉ IPv4) và SOCK_STREAM (về cơ bản là TCP). Phần còn lại của mã ở đó để thiết lập ổ cắm để lắng nghe các yêu cầu trên (máy chủ, cổng) đã cho. Kiểm tra tài liệu Python trên ổ cắm để biết thêm thông tin

Phần còn lại của mã là tự giải thích. chờ kết nối máy khách, đọc chuỗi yêu cầu, gửi chuỗi có định dạng HTTP với Hello World trên nội dung phản hồi và đóng kết nối máy khách. Chúng tôi làm điều này mãi mãi (hoặc cho đến khi ai đó nhấn Ctrl+C). Mở trình duyệt của bạn trên http. //máy chủ cục bộ. 8000/ và bạn sẽ thấy phản hồi của máy chủ

Lập trình HTTP trong Python

As an exercise, change the Hello World to

Hello World

and see what happens. And did you see the print(request) in the server's source code? Here's what it outputs in the console:

Listening on port 8000 ...

GET / HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:51.0) Gecko/20100101 Firefox/51.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: pt-PT,pt;q=0.8,en;q=0.5,en-US;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0

Vâng, đó là trình duyệt yêu cầu trang gốc ("/") của máy chủ

Mục lục. html

Theo mặc định, khi trình duyệt yêu cầu quyền root của máy chủ (sử dụng yêu cầu HTTP chẳng hạn như GET / HTTP/1. 0), chúng ta nên trả lại chỉ mục. trang html. Hãy thay đổi mã trong khi để luôn trả về nội dung của htdocs/index. tệp html

python3 -m http.server
0

Về cơ bản, chúng tôi đọc nội dung của tệp và thêm nó vào chuỗi phản hồi dưới dạng nội dung thư, thay vì Hello World trước đó. chỉ mục. Tệp html chỉ là một tệp văn bản (bên trong thư mục htdocs) có nội dung html

python3 -m http.server
1

Đây là giao diện của nó trong trình duyệt

Lập trình HTTP trong Python

Bạn có thể nhấp vào liên kết bao nhiêu lần tùy thích, nhưng máy chủ của bạn sẽ luôn trả về nội dung của chỉ mục. html. Nó đã được lập trình để cư xử theo cách đó

Trả lại các trang khác

Cho đến nay máy chủ của chúng tôi trả về chỉ mục. html nhưng chúng ta cũng nên cho phép nó trả về các trang khác. Về mặt kỹ thuật, điều đó có nghĩa là chúng ta phải phân tích cú pháp dòng đầu tiên của yêu cầu HTTP (giống như GET /ipsum. htmlHTTP/1. 0), mở tệp dự định và trả về nội dung của nó. Đây là những thay đổi

python3 -m http.server
2

Về cơ bản, chúng tôi trích xuất tên tệp từ chuỗi yêu cầu, mở tệp (chúng tôi giả sử rằng tất cả các tệp html đều nằm trong thư mục htdocs) và trả về nội dung của nó. Bạn cũng có thể kiểm tra xem chúng tôi có trả lại chỉ mục chính xác không. html khi khách hàng yêu cầu tài nguyên gốc ('/')

Đây là nội dung của htdocs/ipsum. html

python3 -m http.server
3

Hãy thử nó trên mã của riêng bạn và xem liệu bạn có thể mở chỉ mục không. html và ipsum. tập tin html

404 không tìm thấy

Chúng tôi vẫn chưa hoàn thành. Đây là điều xảy ra nếu chúng tôi cố gắng yêu cầu một tệp không tồn tại, chẳng hạn như http. //máy chủ cục bộ. 8000/xin chào. html

POST /form.php HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 21

name=John&surname=Doe
0

Máy chủ gặp sự cố và thoát

Chúng ta cần bắt ngoại lệ và trả về phản hồi 404

POST /form.php HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 21

name=John&surname=Doe
1

Nếu muốn, bạn có thể thay đổi nội dung của phản hồi Http 404 để có các thông báo lỗi được cá nhân hóa

Lập trình HTTP trong Python

Toàn bộ mã nguồn cho ví dụ này có thể được tìm thấy trong ý chính này

PythonServer sideKỹ sư hệ thống phân tán

Báo cáo

Thưởng thức bài viết này?

13

Lập trình HTTP trong Python
4

Đăng lại

João Ventura

Người đam mê Python với 10 năm kinh nghiệm

Tôi là João Ventura, kỹ sư phần mềm đến từ Bồ Đào Nha. Hiện tại tôi đang làm Giáo sư Khoa học Máy tính tại Học viện Bách khoa Setúbal, nơi tôi giảng dạy các khóa học về Hệ điều hành và Điện toán phân tán. một số ar của tôi

Theo dõi

Khám phá và đọc thêm các bài viết từ João Ventura

bắt đầu

Thưởng thức bài viết này?

Để lại một lượt thích và bình luận cho João

13

Lập trình HTTP trong Python
4

Lập trình HTTP trong Python
Hãy là người đầu tiên chia sẻ ý kiến ​​của bạn

Lập trình HTTP trong Python
Hỗ trợ đánh dấu hương vị GitHub

Gửi đi

João Carlos

một năm trước

Xin chào João, ví dụ rất hay mà tôi có thể theo dõi và thực hiện một số điều chỉnh trong mô-đun socketser trong python. Bây giờ tôi có một câu hỏi mà tôi cần biết cách gửi hình ảnh (. jpg, jpeg, png … ) sang phía máy khách, bạn có thể minh họa được không?