REST kann bequem für die Datenkommunikation zwischen dem Server und dem Client verwendet werden. In Bezug auf die Verwendung von REST gibt es Informationen zum Erstellen eines Clients in verschiedenen Sprachen und Frameworks. Auf der Serverseite gibt es jedoch Informationen wie das Erstellen mit "JsonServer" oder Apache + PHP als Mock, die leicht vorbereitet werden können. Dies ist jedoch eine Methode, um Unannehmlichkeiten zu akzeptieren oder Zeit und Mühe zu nehmen. (Es wird so weit sein, wie ich finden kann.)
Dieses Mal habe ich versucht, einen Server zu erstellen, der sich in der Mitte des oben genannten befindet, mit dem Sie Dienste frei festlegen und einfach mit einem Skript erstellen können. (Der Zweck besteht nicht darin, eine ausreichende Robustheit zu erfordern, um im WEB veröffentlicht zu werden, sondern einen eigenen Raspberry Pi-Dienst aufzubauen.)
Es ist ein Live-Ressourcencode.
restserver.py
#!/usr/bin/env python3
import http.server
import json
import threading
import sys,os
import time
class RestHandler(http.server.BaseHTTPRequestHandler):
def do_OPTIONS(self):
#Unterstützt Preflight-Anfragen
print( "options" )
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE')
self.send_header('Access-Control-Allow-Headers', '*')
self.end_headers()
def do_POST(self):
print( "post" )
local_path = self.path.strip("/").split("/")
#Anfrage erhalten
content_len = int(self.headers.get("content-length"))
body = json.loads(self.rfile.read(content_len).decode('utf-8'))
#Antwortverarbeitung
if( local_path[0] == "dat" ):
if(os.path.getsize('./dat.json')):
with open('./dat.json', 'r') as json_open:
json_load = json.load(json_open)
json_load.update(**body)
json_wraite = json.dumps(json_load, sort_keys=False, indent=4, ensure_ascii=False)
else:
json_wraite = json.dumps(body, sort_keys=False, indent=4, ensure_ascii=False)
with open('./dat.json', 'w') as json_open:
json_open.write(json_wraite)
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE')
self.send_header('Access-Control-Allow-Headers', '*')
self.end_headers()
return
else:
print( "no" )
print( self.path )
return
def do_GET(self):
print( "get" )
local_path = self.path.strip("/").split("/")
#Antwortverarbeitung
if( local_path[0] == "dat" ):
print( "dat" )
if(os.path.getsize('./dat.json')):
with open('./dat.json', 'r') as json_open:
json_load = json.load(json_open)
else:
json_load = {}
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE')
self.send_header('Access-Control-Allow-Headers', '*')
self.send_header('Content-type', 'application/json;charset=utf-8')
self.end_headers()
body_json = json.dumps(json_load, sort_keys=False, indent=4, ensure_ascii=False)
self.wfile.write(body_json.encode("utf-8"))
return
else:
print( "no" )
print( self.path )
return
def do_DELETE(self):
print( "delete" )
local_path = self.path.strip("/").split("/")
if( local_path[0] == "dat" ):
print( "dat" )
with open('./dat.json', 'w') as file_open:
pass
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE')
self.send_header('Access-Control-Allow-Headers', '*')
self.end_headers()
return
else:
print( "no" )
print( self.path )
return
def rest_server(port):
httpd_rest = http.server.ThreadingHTTPServer(("", port), RestHandler)
httpd_rest.serve_forever()
def main():
#Serverstart
port_rest = 3333
try:
t1 = threading.Thread(target=rest_server, args=(port_rest,), daemon = True)
t1.start()
while True: time.sleep(1)
except (KeyboardInterrupt, SystemExit):
print("exit")
sys.exit()
if __name__ == "__main__":
main()
Der HTTP-Server wird an Port 3333 durch REST-Analyse mit do_OPTIONS / do_POST / do_GET / do_DELETE von Pythons BaseHTTPRequestHandler eingerichtet. Die Operation ist einfach, sie aktualisiert (POST), ruft den Inhalt ab (GET) und initialisiert (DELETE) die Datei "dat.json" im aktuellen Verzeichnis.
REST akzeptiert normalerweise die folgenden vier Arten von Anforderungen.
Es sollte entsprechend erstellt werden, aber ich habe beschlossen, PUT nicht vorzubereiten, da POST als Ersatz verwendet werden kann.
Für "OPTIONEN", die nicht in den 4 Typen enthalten sind, wird abhängig von den Spezifikationen des Browsers vor der POST-Anforderung eine OPTIONS-Anforderung ausgegeben. Die im Header der Antwort auf diese OPTIONS-Anforderung enthaltenen "Access-Control-Allow-Methods" beschreiben die Methoden, die der Server verarbeiten kann. Wenn POST enthalten ist, wird die POST-Anforderung nach der OPTIONS-Anforderung ausgegeben. Ich werde. Dieser Vorgang wird als Preflight bezeichnet und ist ein Browser-Vorgang. Daher gibt es Problemumgehungen, z. B. das Erstellen einer Anforderung von der Serverseite aus. Wenn Sie jedoch Ihren eigenen Server vorbereiten, ist es einfacher, ihn der OPTIONS-Anforderung anzupassen, damit er kompatibel ist. Ich tat.
Ich werde jeden Band erklären. do_OPTIONS
do_OPTIONS
def do_OPTIONS(self):
#Unterstützt Preflight-Anfragen
print( "options" )
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE')
self.send_header('Access-Control-Allow-Headers', '*')
self.end_headers()
Erstellen Sie eine Antwort auf die im vorherigen Abschnitt beschriebene OPTIONS-Anforderung. Es wird einfach eine Antwort zurückgegeben.
do_POST
do_POST
def do_POST(self):
print( "post" )
local_path = self.path.strip("/").split("/")
#Anfrage erhalten
content_len = int(self.headers.get("content-length"))
body = json.loads(self.rfile.read(content_len).decode('utf-8'))
#Antwortverarbeitung
if( local_path[0] == "dat" ):
if(os.path.getsize('./dat.json')):
with open('./dat.json', 'r') as json_open:
json_load = json.load(json_open)
json_load.update(**body)
json_wraite = json.dumps(json_load, sort_keys=False, indent=4, ensure_ascii=False)
else:
json_wraite = json.dumps(body, sort_keys=False, indent=4, ensure_ascii=False)
with open('./dat.json', 'w') as json_open:
json_open.write(json_wraite)
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', '*')
self.end_headers()
return
else:
print( "no" )
print( self.path )
return
Der POST-Prozess schreibt die in der POST-Anforderung empfangenen JSON-Daten in eine Datei. Wir werden den Prozess in der Reihenfolge von oben verfolgen.
local_path = self.path.strip("/").split("/")
self.path enthält die URL-Daten der Anfrage. Teilen Sie dies mit "/" und behalten Sie es im Array. Wenn die Anforderung beispielsweise "Servername / aaa / bbb / ccc /" lautet, lautet der lokale Pfad wie folgt. local_path[0]='aaa' local_path[1]='bbb' local_path[2]='ccc'
content_len = int(self.headers.get("content-length"))
body = json.loads(self.rfile.read(content_len).decode('utf-8'))
Es ist ein Prozess, die zusammen mit der Anforderung empfangenen JSON-Daten zu analysieren und in den Daten des Wörterbuchtyps zu speichern.
#Antwortverarbeitung
if( local_path[0] == "dat" ):
if(os.path.getsize('./dat.json')):
with open('./dat.json', 'r') as json_open:
json_load = json.load(json_open)
json_load.update(**body)
json_wraite = json.dumps(json_load, sort_keys=False, indent=4, ensure_ascii=False)
else:
json_wraite = json.dumps(body, sort_keys=False, indent=4, ensure_ascii=False)
with open('./dat.json', 'w') as json_open:
json_open.write(json_wraite)
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
self.send_header('Access-Control-Allow-Headers', '*')
self.end_headers()
return
In der nächsten Phase überprüfen wir local_path [0] und definieren die API, wenn es sich um "dat" handelt. Im Beispiel wird nur local_path [0] verwendet, die API wird jedoch definiert, indem local_path [1] und local_path [2] nacheinander überprüft werden. Der Rest sind einfache Dateivorgänge. Der Grund für die Überprüfung der Dateigröße ist, dass beim Laden einer leeren Datei in json.load () ein Fehler auftritt. Wenn die Datei leer ist, werden die empfangenen Daten unverändert in die Datei geschrieben. (Die Dateivorgänge hier sind redundant und matschig.)
Der Teil, der die endgültige Antwort erstellt, ist derselbe wie OPTIONS, und die Fehlerbehandlung wird nicht berücksichtigt.
else:
print( "no" )
print( self.path )
return
Dies ist der Zeitpunkt, an dem eine unerwartete URL eintrifft. Normalerweise sollte ein 404-Fehler zurückgegeben werden, aber da es sich nicht um einen öffentlichen Dienst handelt, wird er mutig weggelassen.
do_GET
do_GET
def do_GET(self):
print( "get" )
local_path = self.path.strip("/").split("/")
#Antwortverarbeitung
if( local_path[0] == "dat" ):
print( "dat" )
if(os.path.getsize('./dat.json')):
with open('./dat.json', 'r') as json_open:
json_load = json.load(json_open)
else:
json_load = {}
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE')
self.send_header('Access-Control-Allow-Headers', '*')
self.send_header('Content-type', 'application/json;charset=utf-8')
self.end_headers()
body_json = json.dumps(json_load, sort_keys=False, indent=4, ensure_ascii=False)
self.wfile.write(body_json.encode("utf-8"))
return
else:
print( "no" )
print( self.path )
return
Der grundlegende Teil ist der gleiche wie POST. Es eliminiert die Erfassung von JSON-Daten aus der Anforderung, liest die Datei und fügt diese Daten in die Antwort ein.
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE')
self.send_header('Access-Control-Allow-Headers', '*')
self.send_header('Content-type', 'application/json;charset=utf-8')
self.end_headers()
body_json = json.dumps(json_load, sort_keys=False, indent=4, ensure_ascii=False)
self.wfile.write(body_json.encode("utf-8"))
Der Unterschied zum POST besteht darin, dass der Inhaltstyp zum Header hinzugefügt und Daten in den Körperteil geschrieben werden.
do_DELETE
do_DELETE
def do_DELETE(self):
print( "delete" )
local_path = self.path.strip("/").split("/")
if( local_path[0] == "dat" ):
print( "dat" )
with open('./dat.json', 'w') as file_open:
pass
self.send_response(200)
self.send_header('Access-Control-Allow-Origin', '*')
self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, DELETE')
self.send_header('Access-Control-Allow-Headers', '*')
self.end_headers()
return
else:
print( "no" )
print( self.path )
return
DELETE öffnet einfach die Zieldatei mit dem Attribut w und schließt sie, ohne etwas zu tun, um sie zu einer leeren Datei zu machen.
rest_server
rest_server
def rest_server(port):
httpd_rest = http.server.ThreadingHTTPServer(("", port), RestHandler)
httpd_rest.serve_forever()
Es ist eine Funktion, die den Server einfach an dem durch das Argument angegebenen Port startet.
main
main
def main():
#Serverstart
port_rest = 3333
try:
t1 = threading.Thread(target=rest_server, args=(port_rest,), daemon = True)
t1.start()
while True: time.sleep(1)
except (KeyboardInterrupt, SystemExit):
print("exit")
sys.exit()
Ich versuche, den Server in einem separaten Thread zu starten. Außerdem endet das Programm, wenn es einen End-Interrupt (Strg + C) von der Tastatur empfängt.
Wenn Sie das Skript starten, wird der Server an Port 3333 gestartet. Führen Sie daher den folgenden Befehl aus.
curl -X POST -H 'Content-Type:application/json' -d '{"key":"val"}' localhost:3333/dat
curl -X GET localhost:3333/dat
curl -X DELETE localhost:3333/dat
Der Befehl wird auf localhost gesetzt, da er auf demselben Computer wie der Server ausgeführt wird. Wenn Sie einen anderen Computer verwenden, versuchen Sie, die IP-Adresse des Computers zu verwenden, der der Server sein soll.
Ich konnte vorerst einen REST-Server bauen. Wenn Sie eine API hinzufügen möchten, können Sie die Pfadanalyse immer mehr verschachteln. Da Sie problemlos einen anderen Befehl aufrufen können, können Sie ihn auch so erweitern, dass er auch für die Systemverwaltung verwendet werden kann.
Versuch es bitte.
Recommended Posts