Κοινή χρήση τεχνολογίας

Οδηγός διακομιστή WSGI: Ανάλυση μεθόδου «start_response».

2024-07-12

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

Εκμάθηση διακομιστή Python WSGI:start_response Ανάλυση μεθόδου

Σε αυτό το άρθρο, θα αναλύσουμε λεπτομερώς έναν διακομιστή WSGI start_response μέθοδος.Αυτή η μέθοδος είναι υπεύθυνη για την επεξεργασία του κωδικού κατάστασης και των κεφαλίδων απόκρισης της απόκρισης HTTP και την επιστροφή του αwrite Λειτουργία που χρησιμοποιείται για την αποστολή δεδομένων απόκρισης. Θα εξηγήσουμε πώς λειτουργεί η μέθοδος γραμμή προς γραμμή και θα παρέχουμε κάποιο υπόβαθρο για να κατανοήσουμε τις δυνατότητές της.

γνώσεις υποβάθρου

Το WSGI (Διασύνδεση Πύλης Διακομιστή Ιστού) είναι μια τυπική διεπαφή που χρησιμοποιείται για τη σύνδεση ενός διακομιστή ιστού με μια εφαρμογή ή πλαίσιο Ιστού. Μέσω του WSGI, μπορείτε να επικοινωνείτε μεταξύ του διακομιστή και της εφαρμογής και να χειρίζεστε αιτήματα και απαντήσεις HTTP.

Κατά την υλοποίηση ενός διακομιστή WSGI,start_response Η μέθοδος είναι ένα βασικό τμήμα που καλείται από την εφαρμογή WSGI για να ορίσει την κατάσταση απόκρισης HTTP και τις κεφαλίδες απόκρισης και επιστρέφει μια συνάρτηση για την εγγραφή των δεδομένων απόκρισης.

start_response Υλοποίηση μεθόδου

Το παρακάτω είναι χαρακτηριστικό start_response Υλοποίηση μεθόδου:

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

Εξήγηση βήμα προς βήμα

  1. ασχολούμαι με exc_info παράμετρος
if exc_info:
    try:
        if headers_sent:
            reraise(*exc_info)
    finally:
        exc_info = None
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • exc_info Το όρισμα συνήθως περιέχει μια πλειάδα εξαίρεσης στη μορφή(type, value, traceback) , χρησιμοποιείται για χειρισμό εξαιρέσεων.ανexc_info Οχι γιαNone, υποδεικνύοντας ότι υπάρχει μια εξαίρεση που πρέπει να αντιμετωπιστεί.
  • try Έλεγχοι εντός μπλοκheaders_sent Εάν η κεφαλίδα της απάντησης έχει σταλεί.Εάν έχουν σταλεί οι κεφαλίδες των απαντήσεων, καλέστεreraise(*exc_info) Επαναφέρετε την εξαίρεση.
  • finally Το μπλοκ διασφαλίζει ότι μετά τον χειρισμό της εξαίρεσης, τοexc_info οριστεί σεNoneγια να αποφευχθεί η διπλή επεξεργασία.
  1. Ελέγξτε αν έχει οριστεί η κεφαλίδα απόκρισης
elif headers_set:
    raise AssertionError("Headers already set")
  • 1
  • 2
  • αν headers_set Η λίστα περιέχει ήδη τιμές (δηλαδή έχει οριστεί η κεφαλίδα απόκρισης), αυξήσειςAssertionError ασυνήθιστος.Αυτός ο έλεγχος διασφαλίζειstart_response Μπορεί να κληθεί μόνο μία φορά για να ορίσετε κεφαλίδες απόκρισης.
  1. Ορίστε την κατάσταση απόκρισης και τις κεφαλίδες απόκρισης
headers_set[:] = [status, response_headers]
  • 1
  • Χρησιμοποιήστε την ανάθεση φέτας σε status καιresponse_headers ανατεθείheaders_set λίστα.Σκοπός αυτού είναι η διατήρησηheaders_set αναφορά, αλλά ενημερώνει το περιεχόμενό του.
  • status είναι μια συμβολοσειρά που αντιπροσωπεύει τον κωδικό κατάστασης απόκρισης HTTP και το μήνυμα, για παράδειγμα"200 OK"
  • response_headers είναι μια λίστα που περιέχει πλειάδες, κάθε πλειάδα αντιπροσωπεύει ένα ζεύγος κλειδιού-τιμής μιας κεφαλίδας απόκρισης, για παράδειγμα[("Content-Type", "text/html"), ("Content-Length", "123")]
  1. ΕΠΙΣΤΡΟΦΗ write λειτουργία
return write
  • 1
  • start_response Η μέθοδος επιστρέφει awrite λειτουργία. Αυτή η λειτουργία καλείται από την εφαρμογή WSGI για αποστολή δεδομένων απόκρισης.

Παράδειγμα χρήσης

Ακολουθεί ένα πλήρες παράδειγμα που δείχνει πώς να το χρησιμοποιήσετε start_response Μέθοδοι χειρισμού απαντήσεων 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

Συνοψίζω

Μέσα από αυτό το σεμινάριο, αναλύσαμε λεπτομερώς έναν διακομιστή WSGI start_response Μέθοδος που εξηγεί πώς χειρίζεται τον κωδικό κατάστασης και τις κεφαλίδες απόκρισης μιας απόκρισης HTTP και επιστρέφει μια συνάρτηση για την εγγραφή των δεδομένων απόκρισης. Η κατανόηση αυτών των περιεχομένων θα σας βοηθήσει να κατανοήσετε καλύτερα τις προδιαγραφές WSGI και να εφαρμόσετε έναν προσαρμοσμένο διακομιστή WSGI. Ελπίζω ότι αυτό το σεμινάριο είναι χρήσιμο για εσάς.Για περισσότερες λεπτομέρειες και παραδείγματα, ανατρέξτε στοΕπίσημη τεκμηρίωση