Skip to content

Commit e9e2dc2

Browse files
committed
Fix validation issues and improve exceptions logs
1 parent ca48efa commit e9e2dc2

File tree

4 files changed

+33
-23
lines changed

4 files changed

+33
-23
lines changed

gns3server/api/routes/compute/images.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535

3636
@router.get("/docker/images")
37-
async def get_docker_images() -> List[str]:
37+
async def get_docker_images() -> List[dict]:
3838
"""
3939
Get all Docker images.
4040
"""

gns3server/api/routes/controller/computes.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
API routes for computes.
1919
"""
2020

21-
from fastapi import APIRouter, Depends, Response, status
22-
from typing import List, Union, Optional
21+
from fastapi import APIRouter, Depends, status
22+
from typing import Any, List, Union, Optional
2323
from uuid import UUID
2424

2525
from gns3server.controller import Controller
@@ -157,7 +157,7 @@ async def dynamips_autoidlepc(compute_id: Union[str, UUID], auto_idle_pc: schema
157157

158158

159159
@router.get("/{compute_id}/{emulator}/{endpoint_path:path}", deprecated=True)
160-
async def forward_get(compute_id: Union[str, UUID], emulator: str, endpoint_path: str) -> dict:
160+
async def forward_get(compute_id: Union[str, UUID], emulator: str, endpoint_path: str) -> Any:
161161
"""
162162
Forward a GET request to a compute.
163163
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
169169

170170

171171
@router.post("/{compute_id}/{emulator}/{endpoint_path:path}", deprecated=True)
172-
async def forward_post(compute_id: Union[str, UUID], emulator: str, endpoint_path: str, compute_data: dict) -> dict:
172+
async def forward_post(compute_id: Union[str, UUID], emulator: str, endpoint_path: str, compute_data: dict) -> Any:
173173
"""
174174
Forward a POST request to a compute.
175175
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
180180

181181

182182
@router.put("/{compute_id}/{emulator}/{endpoint_path:path}", deprecated=True)
183-
async def forward_put(compute_id: Union[str, UUID], emulator: str, endpoint_path: str, compute_data: dict) -> dict:
183+
async def forward_put(compute_id: Union[str, UUID], emulator: str, endpoint_path: str, compute_data: dict) -> Any:
184184
"""
185185
Forward a PUT request to a compute.
186186
Read the full compute API documentation for available routes.

gns3server/api/server.py

+26-16
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@
2121

2222
import time
2323

24-
from fastapi import FastAPI, Request, HTTPException
24+
from fastapi import FastAPI, Request, HTTPException, status
2525
from fastapi.middleware.cors import CORSMiddleware
2626
from fastapi.responses import JSONResponse
27+
from fastapi.exceptions import RequestValidationError
2728
from sqlalchemy.exc import SQLAlchemyError
2829
from uvicorn.main import Server as UvicornServer
2930

@@ -87,54 +88,54 @@ def handle_exit(*args, **kwargs):
8788

8889
@app.exception_handler(ControllerError)
8990
async def controller_error_handler(request: Request, exc: ControllerError):
90-
log.error(f"Controller error: {exc}")
91+
log.error(f"Controller error in {request.url.path} ({request.method}): {exc}")
9192
return JSONResponse(
92-
status_code=409,
93+
status_code=status.HTTP_409_CONFLICT,
9394
content={"message": str(exc)},
9495
)
9596

9697

9798
@app.exception_handler(ControllerTimeoutError)
9899
async def controller_timeout_error_handler(request: Request, exc: ControllerTimeoutError):
99-
log.error(f"Controller timeout error: {exc}")
100+
log.error(f"Controller timeout error in {request.url.path} ({request.method}): {exc}")
100101
return JSONResponse(
101-
status_code=408,
102+
status_code=status.HTTP_408_REQUEST_TIMEOUT,
102103
content={"message": str(exc)},
103104
)
104105

105106

106107
@app.exception_handler(ControllerUnauthorizedError)
107108
async def controller_unauthorized_error_handler(request: Request, exc: ControllerUnauthorizedError):
108-
log.error(f"Controller unauthorized error: {exc}")
109+
log.error(f"Controller unauthorized error in {request.url.path} ({request.method}): {exc}")
109110
return JSONResponse(
110-
status_code=401,
111+
status_code=status.HTTP_401_UNAUTHORIZED,
111112
content={"message": str(exc)},
112113
)
113114

114115

115116
@app.exception_handler(ControllerForbiddenError)
116117
async def controller_forbidden_error_handler(request: Request, exc: ControllerForbiddenError):
117-
log.error(f"Controller forbidden error: {exc}")
118+
log.error(f"Controller forbidden error in {request.url.path} ({request.method}): {exc}")
118119
return JSONResponse(
119-
status_code=403,
120+
status_code=status.HTTP_403_FORBIDDEN,
120121
content={"message": str(exc)},
121122
)
122123

123124

124125
@app.exception_handler(ControllerNotFoundError)
125126
async def controller_not_found_error_handler(request: Request, exc: ControllerNotFoundError):
126-
log.error(f"Controller not found error: {exc}")
127+
log.error(f"Controller not found error in {request.url.path} ({request.method}): {exc}")
127128
return JSONResponse(
128-
status_code=404,
129+
status_code=status.HTTP_404_NOT_FOUND,
129130
content={"message": str(exc)},
130131
)
131132

132133

133134
@app.exception_handler(ControllerBadRequestError)
134135
async def controller_bad_request_error_handler(request: Request, exc: ControllerBadRequestError):
135-
log.error(f"Controller bad request error: {exc}")
136+
log.error(f"Controller bad request error in {request.url.path} ({request.method}): {exc}")
136137
return JSONResponse(
137-
status_code=400,
138+
status_code=status.HTTP_400_BAD_REQUEST,
138139
content={"message": str(exc)},
139140
)
140141

@@ -143,7 +144,7 @@ async def controller_bad_request_error_handler(request: Request, exc: Controller
143144
async def compute_conflict_error_handler(request: Request, exc: ComputeConflictError):
144145
log.error(f"Controller received error from compute for request '{exc.url()}': {exc}")
145146
return JSONResponse(
146-
status_code=409,
147+
status_code=status.HTTP_409_CONFLICT,
147148
content={"message": str(exc)},
148149
)
149150

@@ -160,12 +161,21 @@ async def http_exception_handler(request: Request, exc: HTTPException):
160161

161162
@app.exception_handler(SQLAlchemyError)
162163
async def sqlalchemry_error_handler(request: Request, exc: SQLAlchemyError):
163-
log.error(f"Controller database error: {exc}")
164+
log.error(f"Controller database error in {request.url.path} ({request.method}): {exc}")
164165
return JSONResponse(
165-
status_code=500,
166+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
166167
content={"message": "Database error detected, please check logs to find details"},
167168
)
168169

170+
171+
@app.exception_handler(RequestValidationError)
172+
async def validation_exception_handler(request: Request, exc: RequestValidationError):
173+
log.error(f"Request validation error in {request.url.path} ({request.method}): {exc}")
174+
return JSONResponse(
175+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
176+
content={"message": str(exc)}
177+
)
178+
169179
# FIXME: do not use this middleware since it creates issue when using StreamingResponse
170180
# see https://starlette-context.readthedocs.io/en/latest/middleware.html#why-are-there-two-middlewares-that-do-the-same-thing
171181

requirements.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
uvicorn==0.22.0 # v0.22.0 is the last to support Python 3.7
2-
fastapi==0.101.0
2+
fastapi==0.101.1
33
python-multipart==0.0.6
44
websockets==11.0.3
55
aiohttp>=3.8.5,<3.9

0 commit comments

Comments
 (0)