Каналы Django – распространение исключений клиенту
Мне было интересно, как лучше всего передавать исключения клиенту, используяdjango-channels
.
Мой клиент — приложение Swift для iOS, использующееURLSessionWebSocketTask
.
Например, у меня есть 3 основных сценария, когда выдается исключение, и я хочу уведомить об этом клиента.
- Аутентификация с использованием специального промежуточного программного обеспечения.
from api.jwt_handler import jwt_websocket_decode, get_device_id, get_auth_token
from inbox.exceptions import WebSocketErrors
class WebsocketAuthMiddleware:
def __init__(self, app):
self.app = app
async def __call__(self, scope, receive, send):
headers = scope["headers"]
token = get_auth_token(headers)
device_id = get_device_id(headers)
if token is None or device_id is None:
raise WebSocketErrors.invalid_bearer_token <--- Notify client
user = await jwt_websocket_decode(token, device_id)
if user is None:
raise WebSocketErrors.invalid_bearer_token <--- Notify client
scope['user'] = user
return await self.app(scope, receive, send)
Я пробовал обертывать__call__
в операторе try, но я не уверен, как передать ошибку на транспортный уровень http. Клиент получает1011 - There was a bad response from the server
- Отказ от соединения – рукопожатие.
class ConversationConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.ws_conversation_id = self.scope["url_route"]["kwargs"]["conversation_id"]
self.room_group_name = self.ws_conversation_id
self.user = self.scope["user"]
if user.can_participate_in_conversation(self.ws_conversation_id) is False:
raise WebSocketErrors.not_authorized <--- Notify client
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
await self.accept()
Здесь я хочу отклонить соединение, если пользователь не является частью данного идентификатора разговора, чтобы предотвратить злоупотребления.
- Внутрисессионная обработка данных – подключен веб-сокет.
async def receive(self, bytes_data):
message_json = json.loads(bytes_data)
type = WebSocketType(message_json["type"])
try:
web_socket_item = self.get_websocket_item(type, message_json)
user_id = self.scope["user"].id
message_body = await web_socket_item.save_and_get_message_body(sender_id=user_id)
except Exception as error:
message_body = {
"type": WebSocketType.error.value,
"error": {
"code": error.code,
"message": error.message
}
}
# Send message to room group
await self.channel_layer.group_send(
self.room_group_name,
{"type": type.value, "message": message_body}
)
Здесь я перехватил исключение и использовал открытое соединение для отправки сообщения с типом ошибки, но я не уверен, что это правильная практика.
Любое необработанное исключение, вызывающее отключение, и клиент получает то же самое.1011
ошибка. Я хочу предотвратить отключение сокета в некоторых случаях (например, в 3) и дать клиенту возможность лучше обрабатывать ошибки.