Berbagi teknologi

Tutorial server WSGI: analisis metode `start_response`

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

Tutorial server Python WSGI:start_response Analisis metode

Pada artikel ini, kami akan menganalisis secara detail server WSGI start_response metode.Metode ini bertanggung jawab untuk memproses kode status dan header respons dari respons HTTP dan mengembalikan awrite Fungsi yang digunakan untuk mengirim data respons. Kami akan menjelaskan cara kerja metode ini baris demi baris dan memberikan beberapa latar belakang untuk membantu memahami kemampuannya.

latar belakang pengetahuan

WSGI (Web Server Gateway Interface) adalah antarmuka standar yang digunakan untuk menghubungkan server web dengan aplikasi atau kerangka web. Melalui WSGI, Anda dapat berkomunikasi antara server dan aplikasi serta menangani permintaan dan respons HTTP.

Saat mengimplementasikan server WSGI,start_response Metode ini merupakan bagian penting yang dipanggil oleh aplikasi WSGI untuk mengatur status respons HTTP dan header respons, serta mengembalikan fungsi untuk menulis data respons.

start_response Implementasi metode

Berikut ini tipikalnya start_response Implementasi metode:

def start_response(status, response_headers, exc_info=None):
    if exc_info:
        try:
            if headers_sent:
                reraise(*exc_info)
        finally:
            exc_info = None
    elif headers_set:
        raise AssertionError("Headers already set")
    headers_set[:] = [status, response_headers]
    return write
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Penjelasan langkah demi langkah

  1. berurusan dengan exc_info parameter
if exc_info:
    try:
        if headers_sent:
            reraise(*exc_info)
    finally:
        exc_info = None
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • exc_info Argumen biasanya berisi tupel pengecualian dalam format(type, value, traceback) , digunakan untuk penanganan pengecualian.jikaexc_info Tidak untukNone, menunjukkan bahwa ada pengecualian yang perlu ditangani.
  • try Pemeriksaan di blokheaders_sent Apakah header respons telah terkirim.Jika header respons telah dikirim, hubungireraise(*exc_info) Lemparkan kembali pengecualian tersebut.
  • finally blok memastikan bahwa setelah menangani pengecualian, fileexc_info mulaiNoneuntuk menghindari duplikasi pemrosesan.
  1. Periksa apakah header respons telah disetel
elif headers_set:
    raise AssertionError("Headers already set")
  • 1
  • 2
  • jika headers_set Daftar sudah berisi nilai (yaitu header respons telah disetel), munculkanAssertionError abnormal.Pemeriksaan ini memastikanstart_response Hanya dapat dipanggil sekali untuk menyetel header respons.
  1. Tetapkan status respons dan header respons
headers_set[:] = [status, response_headers]
  • 1
  • Gunakan penugasan irisan untuk status Danresponse_headers ditugaskan untukheaders_set daftar.Tujuannya adalah untuk mempertahankanheaders_set referensi, tetapi memperbarui isinya.
  • status adalah string yang mewakili kode dan pesan status respons HTTP, misalnya"200 OK"
  • response_headers adalah daftar yang berisi tupel, setiap tupel mewakili pasangan nilai kunci dari header respons, misalnya[("Content-Type", "text/html"), ("Content-Length", "123")]
  1. kembali write fungsi
return write
  • 1
  • start_response Metode ini mengembalikan awrite fungsi. Fungsi ini dipanggil oleh aplikasi WSGI untuk mengirimkan data respon.

Contoh penggunaan

Berikut adalah contoh lengkap yang menunjukkan cara menggunakannya start_response Metode untuk menangani tanggapan WSGI:

import socketserver

class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        self.headers_set = []
        self.headers_sent = []

        def start_response(status, response_headers, exc_info=None):
            if exc_info:
                try:
                    if self.headers_sent:
                        raise exc_info[1]
                finally:
                    exc_info = None
            elif self.headers_set:
                raise AssertionError("Headers already set")
            self.headers_set[:] = [status, response_headers]
            return self.write

        def write(data):
            assert self.headers_set, "write() before start_response"
            if not self.headers_sent:
                status, response_headers = self.headers_sent[:] = self.headers_set
                try:
                    code, msg = status.split(None, 1)
                except ValueError:
                    code, msg = status, ""
                code = int(code)
                self.send_response(code, msg)
                header_keys = set()
                for key, value in response_headers:
                    self.send_header(key, value)
                    key = key.lower()
                    header_keys.add(key)
                if not (
                    "content-length" in header_keys
                    or self.environ["REQUEST_METHOD"] == "HEAD"
                    or code < 200
                    or code in (204, 304)
                ):
                    self.close_connection = True
                    self.send_header("Connection", "close")
                if "server" not in header_keys:
                    self.send_header("Server", self.version_string())
                if "date" not in header_keys:
                    self.send_header("Date", self.date_time_string())
                self.end_headers()

            assert isinstance(data, bytes), "applications must write bytes"
            self.wfile.write(data)
            self.wfile.flush()

        self.write = write
        self.environ = self.make_environ()

        try:
            result = self.server.app(self.environ, start_response)
            try:
                for data in result:
                    write(data)
                if not self.headers_sent:
                    write(b"")
            finally:
                if hasattr(result, "close"):
                    result.close()
        except Exception as e:
            self.send_error(500, str(e))

if __name__ == "__main__":
    HOST, PORT = "localhost", 9999
    with socketserver.TCPServer((HOST, PORT), MyTCPHandler) as server:
        print("Server started at {}:{}".format(HOST, PORT))
        server.serve_forever()
  • 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
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73

Meringkaskan

Melalui tutorial ini, kami menganalisis secara detail server WSGI start_response Metode yang menjelaskan cara menangani kode status dan header respons dari respons HTTP, dan mengembalikan fungsi untuk menulis data respons. Memahami konten ini akan membantu Anda lebih memahami spesifikasi WSGI dan mengimplementasikan server WSGI yang disesuaikan. Semoga tutorial ini bermanfaat bagi Anda.Untuk lebih jelasnya dan contohnya silakan merujuk keDokumentasi resmi