mirror of
https://github.com/GNS3/gns3-server
synced 2024-11-25 01:38:08 +00:00
Fix validation issues and improve exceptions logs
This commit is contained in:
parent
ca48efa5be
commit
e9e2dc2ca7
@ -34,7 +34,7 @@ router = APIRouter()
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/docker/images")
|
@router.get("/docker/images")
|
||||||
async def get_docker_images() -> List[str]:
|
async def get_docker_images() -> List[dict]:
|
||||||
"""
|
"""
|
||||||
Get all Docker images.
|
Get all Docker images.
|
||||||
"""
|
"""
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
API routes for computes.
|
API routes for computes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Response, status
|
from fastapi import APIRouter, Depends, status
|
||||||
from typing import List, Union, Optional
|
from typing import Any, List, Union, Optional
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from gns3server.controller import Controller
|
from gns3server.controller import Controller
|
||||||
@ -157,7 +157,7 @@ async def dynamips_autoidlepc(compute_id: Union[str, UUID], auto_idle_pc: schema
|
|||||||
|
|
||||||
|
|
||||||
@router.get("/{compute_id}/{emulator}/{endpoint_path:path}", deprecated=True)
|
@router.get("/{compute_id}/{emulator}/{endpoint_path:path}", deprecated=True)
|
||||||
async def forward_get(compute_id: Union[str, UUID], emulator: str, endpoint_path: str) -> dict:
|
async def forward_get(compute_id: Union[str, UUID], emulator: str, endpoint_path: str) -> Any:
|
||||||
"""
|
"""
|
||||||
Forward a GET request to a compute.
|
Forward a GET request to a compute.
|
||||||
Read the full compute API documentation for available routes.
|
Read the full compute API documentation for available routes.
|
||||||
@ -169,7 +169,7 @@ async def forward_get(compute_id: Union[str, UUID], emulator: str, endpoint_path
|
|||||||
|
|
||||||
|
|
||||||
@router.post("/{compute_id}/{emulator}/{endpoint_path:path}", deprecated=True)
|
@router.post("/{compute_id}/{emulator}/{endpoint_path:path}", deprecated=True)
|
||||||
async def forward_post(compute_id: Union[str, UUID], emulator: str, endpoint_path: str, compute_data: dict) -> dict:
|
async def forward_post(compute_id: Union[str, UUID], emulator: str, endpoint_path: str, compute_data: dict) -> Any:
|
||||||
"""
|
"""
|
||||||
Forward a POST request to a compute.
|
Forward a POST request to a compute.
|
||||||
Read the full compute API documentation for available routes.
|
Read the full compute API documentation for available routes.
|
||||||
@ -180,7 +180,7 @@ async def forward_post(compute_id: Union[str, UUID], emulator: str, endpoint_pat
|
|||||||
|
|
||||||
|
|
||||||
@router.put("/{compute_id}/{emulator}/{endpoint_path:path}", deprecated=True)
|
@router.put("/{compute_id}/{emulator}/{endpoint_path:path}", deprecated=True)
|
||||||
async def forward_put(compute_id: Union[str, UUID], emulator: str, endpoint_path: str, compute_data: dict) -> dict:
|
async def forward_put(compute_id: Union[str, UUID], emulator: str, endpoint_path: str, compute_data: dict) -> Any:
|
||||||
"""
|
"""
|
||||||
Forward a PUT request to a compute.
|
Forward a PUT request to a compute.
|
||||||
Read the full compute API documentation for available routes.
|
Read the full compute API documentation for available routes.
|
||||||
|
@ -21,9 +21,10 @@ FastAPI app
|
|||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from fastapi import FastAPI, Request, HTTPException
|
from fastapi import FastAPI, Request, HTTPException, status
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
|
from fastapi.exceptions import RequestValidationError
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from uvicorn.main import Server as UvicornServer
|
from uvicorn.main import Server as UvicornServer
|
||||||
|
|
||||||
@ -87,54 +88,54 @@ UvicornServer.handle_exit = handle_exit
|
|||||||
|
|
||||||
@app.exception_handler(ControllerError)
|
@app.exception_handler(ControllerError)
|
||||||
async def controller_error_handler(request: Request, exc: ControllerError):
|
async def controller_error_handler(request: Request, exc: ControllerError):
|
||||||
log.error(f"Controller error: {exc}")
|
log.error(f"Controller error in {request.url.path} ({request.method}): {exc}")
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=409,
|
status_code=status.HTTP_409_CONFLICT,
|
||||||
content={"message": str(exc)},
|
content={"message": str(exc)},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.exception_handler(ControllerTimeoutError)
|
@app.exception_handler(ControllerTimeoutError)
|
||||||
async def controller_timeout_error_handler(request: Request, exc: ControllerTimeoutError):
|
async def controller_timeout_error_handler(request: Request, exc: ControllerTimeoutError):
|
||||||
log.error(f"Controller timeout error: {exc}")
|
log.error(f"Controller timeout error in {request.url.path} ({request.method}): {exc}")
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=408,
|
status_code=status.HTTP_408_REQUEST_TIMEOUT,
|
||||||
content={"message": str(exc)},
|
content={"message": str(exc)},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.exception_handler(ControllerUnauthorizedError)
|
@app.exception_handler(ControllerUnauthorizedError)
|
||||||
async def controller_unauthorized_error_handler(request: Request, exc: ControllerUnauthorizedError):
|
async def controller_unauthorized_error_handler(request: Request, exc: ControllerUnauthorizedError):
|
||||||
log.error(f"Controller unauthorized error: {exc}")
|
log.error(f"Controller unauthorized error in {request.url.path} ({request.method}): {exc}")
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=401,
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
||||||
content={"message": str(exc)},
|
content={"message": str(exc)},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.exception_handler(ControllerForbiddenError)
|
@app.exception_handler(ControllerForbiddenError)
|
||||||
async def controller_forbidden_error_handler(request: Request, exc: ControllerForbiddenError):
|
async def controller_forbidden_error_handler(request: Request, exc: ControllerForbiddenError):
|
||||||
log.error(f"Controller forbidden error: {exc}")
|
log.error(f"Controller forbidden error in {request.url.path} ({request.method}): {exc}")
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=403,
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
content={"message": str(exc)},
|
content={"message": str(exc)},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.exception_handler(ControllerNotFoundError)
|
@app.exception_handler(ControllerNotFoundError)
|
||||||
async def controller_not_found_error_handler(request: Request, exc: ControllerNotFoundError):
|
async def controller_not_found_error_handler(request: Request, exc: ControllerNotFoundError):
|
||||||
log.error(f"Controller not found error: {exc}")
|
log.error(f"Controller not found error in {request.url.path} ({request.method}): {exc}")
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=404,
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
content={"message": str(exc)},
|
content={"message": str(exc)},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@app.exception_handler(ControllerBadRequestError)
|
@app.exception_handler(ControllerBadRequestError)
|
||||||
async def controller_bad_request_error_handler(request: Request, exc: ControllerBadRequestError):
|
async def controller_bad_request_error_handler(request: Request, exc: ControllerBadRequestError):
|
||||||
log.error(f"Controller bad request error: {exc}")
|
log.error(f"Controller bad request error in {request.url.path} ({request.method}): {exc}")
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=400,
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
content={"message": str(exc)},
|
content={"message": str(exc)},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -143,7 +144,7 @@ async def controller_bad_request_error_handler(request: Request, exc: Controller
|
|||||||
async def compute_conflict_error_handler(request: Request, exc: ComputeConflictError):
|
async def compute_conflict_error_handler(request: Request, exc: ComputeConflictError):
|
||||||
log.error(f"Controller received error from compute for request '{exc.url()}': {exc}")
|
log.error(f"Controller received error from compute for request '{exc.url()}': {exc}")
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=409,
|
status_code=status.HTTP_409_CONFLICT,
|
||||||
content={"message": str(exc)},
|
content={"message": str(exc)},
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -160,12 +161,21 @@ async def http_exception_handler(request: Request, exc: HTTPException):
|
|||||||
|
|
||||||
@app.exception_handler(SQLAlchemyError)
|
@app.exception_handler(SQLAlchemyError)
|
||||||
async def sqlalchemry_error_handler(request: Request, exc: SQLAlchemyError):
|
async def sqlalchemry_error_handler(request: Request, exc: SQLAlchemyError):
|
||||||
log.error(f"Controller database error: {exc}")
|
log.error(f"Controller database error in {request.url.path} ({request.method}): {exc}")
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
status_code=500,
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
content={"message": "Database error detected, please check logs to find details"},
|
content={"message": "Database error detected, please check logs to find details"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.exception_handler(RequestValidationError)
|
||||||
|
async def validation_exception_handler(request: Request, exc: RequestValidationError):
|
||||||
|
log.error(f"Request validation error in {request.url.path} ({request.method}): {exc}")
|
||||||
|
return JSONResponse(
|
||||||
|
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
||||||
|
content={"message": str(exc)}
|
||||||
|
)
|
||||||
|
|
||||||
# FIXME: do not use this middleware since it creates issue when using StreamingResponse
|
# FIXME: do not use this middleware since it creates issue when using StreamingResponse
|
||||||
# see https://starlette-context.readthedocs.io/en/latest/middleware.html#why-are-there-two-middlewares-that-do-the-same-thing
|
# see https://starlette-context.readthedocs.io/en/latest/middleware.html#why-are-there-two-middlewares-that-do-the-same-thing
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
uvicorn==0.22.0 # v0.22.0 is the last to support Python 3.7
|
uvicorn==0.22.0 # v0.22.0 is the last to support Python 3.7
|
||||||
fastapi==0.101.0
|
fastapi==0.101.1
|
||||||
python-multipart==0.0.6
|
python-multipart==0.0.6
|
||||||
websockets==11.0.3
|
websockets==11.0.3
|
||||||
aiohttp>=3.8.5,<3.9
|
aiohttp>=3.8.5,<3.9
|
||||||
|
Loading…
Reference in New Issue
Block a user