10.5. Un API de control pentru cameră#
Proprietarul are nevoie să seteze sensibilitatea detectorului de mișcare de oriunde – vântul mișcă mai mult copacii într-o zi cu vânt. Asta înseamnă rute din care tabloul de bord poate citi setările curente și către care poate trimite modificări.
Un mic dicționar de stare partajat pe modul este suficient pentru a păstra reglajele. Paginile ulterioare adaugă mai multe chei la el; deocamdată există una singură:
state = {
'threshold': 12,
'frame_count': 0,
'trigger_count': 0,
}
10.5.1. GET pentru citire, POST pentru scriere#
O pereche de rute – una get, una post – oferă tabloului de bord acces de citire/scriere la state:
from microdot import abort
@app.get('/config')
async def get_config(request):
return state
@app.post('/config')
async def set_config(request):
body = request.json
if not body or 'threshold' not in body:
abort(400, 'missing threshold')
try:
threshold = int(body['threshold'])
except (TypeError, ValueError):
abort(400, 'threshold must be an integer')
if not 0 <= threshold <= 100:
abort(400, 'threshold out of range')
state['threshold'] = threshold
return {'ok': True, 'threshold': threshold}
microdot.Request.json returnează corpul analizat ca JSON, sau None dacă Content-Type nu a fost application/json. Handlerul post parcurge fiecare mod de eșec – cheie lipsă, tip greșit, valoare în afara intervalului – și abandonează cu microdot.abort(), care ridică microdot.HTTPException pentru a scurtcircuita handlerul cu statusul și mesajul date.
10.5.2. GET, POST, PUT, DELETE#
get() și post() sunt cele două pe care le vom folosi cel mai mult. put() și delete() există pentru cazurile care urmează convențiile REST – un PUT /events/42 pentru a înlocui evenimentul 42, un DELETE /events/42 pentru a-l elimina. Handlerul este în rest identic.
10.5.3. Citirea șirurilor de interogare și a formularelor#
Tabloul de bord trimite JSON, așa că request.json este ceea ce dorim. Alte două moduri în care camera ar putea primi date:
args– șirul de interogare.?foo=1&bar=2devine unmicrodot.MultiDictpe care îl poți citi curequest.args.get('foo').form– un formular HTML trimis caapplication/x-www-form-urlencoded. Același tipMultiDict.
MultiDict este asemănător unui dicționar, dar permite unei chei să poarte mai multe valori (?tag=cat&tag=dog reprezintă două valori tag); vezi microdot.MultiDict pentru suprafața completă.
10.5.4. Segmente de URL dinamice#
O cale de rută poate declara substituenți tipizați pe care microdot îi transmite handlerului ca argumente suplimentare:
@app.get('/events/<int:event_id>')
async def get_event(request, event_id):
return {'id': event_id, 'msg': 'placeholder'}
Convertoarele acceptate sunt <int:>, <re:> pentru o expresie regulată personalizată, <path:> pentru un segment care poate conține bare oblice și cel implicit (fără prefix) pentru „potrivește orice până la următoarea bară oblică.” <int:event_id> acceptă /events/42 și respinge /events/abc – respingerea devine un 404 fără ca handlerul să ruleze.
10.5.5. Răspunsuri de eroare personalizate#
Răspunsul 404 implicit pe care îl trimite microdot este pur și simplu Not found. Tabloul de bord așteaptă JSON pentru fiecare răspuns; suprascrie handlerul de 404 astfel încât să returneze și el JSON:
@app.errorhandler(404)
async def not_found(request):
return {'error': 'not found', 'path': request.path}, 404
errorhandler() acceptă fie un cod de status (prinde fiecare eroare cu acel status), fie o clasă de excepție (prinde fiecare handler care a ridicat acea excepție). Tuplul (body, status) scurtcircuitează răspunsul fără a construi un Response.
Camera își expune acum starea și acceptă modificări.