10.5. 카메라용 제어 API

소유자는 어디서든 모션 검출기의 감도를 설정할 필요가 있습니다 – 바람이 부는 날에는 바람이 나무를 더 많이 흔드니까요. 즉, 대시보드가 현재 설정을 읽고 변경 사항을 게시할 수 있는 라우트가 필요합니다.

조절 값을 담아두기에는 모듈 상의 작은 공유 상태 dict 하나면 충분합니다. 이후 페이지에서 거기에 키를 더 추가하지만, 지금은 하나만 있습니다:

state = {
    'threshold': 12,
    'frame_count': 0,
    'trigger_count': 0,
}

10.5.1. 읽기는 GET, 쓰기는 POST

라우트 한 쌍 – 하나는 get, 하나는 post – 이 대시보드에 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은 본문을 JSON으로 파싱하여 반환하거나, Content-Typeapplication/json이 아니면 None을 반환합니다. post 핸들러는 각 실패 모드 – 누락된 키, 잘못된 타입, 범위 초과 – 를 차례로 검사하고 microdot.abort()로 빠져나오는데, 이 함수는 microdot.HTTPException을 발생시켜 주어진 상태와 메시지로 핸들러를 단락시킵니다.

10.5.2. GET, POST, PUT, DELETE

get()post()가 우리가 가장 많이 사용할 두 가지입니다. put()delete()는 REST 규약을 따르는 경우 – 이벤트 42를 교체하는 PUT /events/42, 그것을 삭제하는 DELETE /events/42 – 를 위해 존재합니다. 핸들러는 그 외에는 동일합니다.

10.5.3. 쿼리 문자열과 폼 읽기

대시보드는 JSON을 게시하므로 우리가 원하는 것은 request.json입니다. 카메라가 데이터를 받을 수 있는 다른 두 가지 방법은 다음과 같습니다:

  • args – 쿼리 문자열입니다. ?foo=1&bar=2request.args.get('foo')로 읽을 수 있는 microdot.MultiDict가 됩니다.

  • formapplication/x-www-form-urlencoded로 게시된 HTML 폼입니다. 동일한 MultiDict 타입입니다.

MultiDict는 dict와 비슷하지만 하나의 키가 여러 값을 가질 수 있게 해줍니다(?tag=cat&tag=dog는 두 개의 tag 값입니다). 전체 인터페이스는 microdot.MultiDict를 참고하세요.

10.5.4. 동적 URL 세그먼트

라우트 경로는 microdot가 추가 인수로 핸들러에 전달하는 타입 지정 플레이스홀더를 선언할 수 있습니다:

@app.get('/events/<int:event_id>')
async def get_event(request, event_id):
    return {'id': event_id, 'msg': 'placeholder'}

지원되는 변환기는 <int:>, 커스텀 정규식을 위한 <re:>, 슬래시를 포함할 수 있는 세그먼트를 위한 <path:>, 그리고 “다음 슬래시까지 무엇이든 일치”를 의미하는 기본값(접두사 없음)입니다. <int:event_id>/events/42를 받아들이고 /events/abc를 거부합니다 – 거부는 핸들러가 실행되지 않은 채 404가 됩니다.

10.5.5. 커스텀 오류 응답

microdot가 보내는 기본 404는 단순한 Not found입니다. 대시보드는 모든 응답에 JSON을 기대하므로, 404 핸들러를 재정의하여 JSON도 반환하도록 합니다:

@app.errorhandler(404)
async def not_found(request):
    return {'error': 'not found', 'path': request.path}, 404

errorhandler()는 상태 코드(해당 상태의 모든 오류를 잡음) 또는 예외 클래스(그 예외를 발생시킨 모든 핸들러를 잡음) 중 하나를 받습니다. (body, status) 튜플은 Response를 구성하지 않고 응답을 단락시킵니다.

이제 카메라는 자신의 상태를 노출하고 편집을 받아들입니다.