Не получается отправить данные на frontend с backend для подгрузки новой страницы. В чем причина?
Пишу сайт на Django, DRF, Redis, Nginx, Guvicorn. Столкнулся с такой проблемой: У меня есть frontend, который в этом блоке
const ws = new WebSocket(
`wss://storisbro.com/ws/auth_status/?token=${token}`
);
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log("Auth status changed:", data["authenticated"]);
setAuthedVk(data["authenticated"]);
};
Получает данные с вк и если пользователь авторизован через вк, то подгружает новую страницу. Как я понял, что отправляет это все дело мой бэк. И вот текущий код:
Функция для отправки этой информации.
@csrf_exempt
@api_view(['GET', 'POST'])
@authentication_classes([JWTAuthentication])
@permission_classes([IsAuthenticated])
def vk_callback(request):
"""Получение токенов пользователя от ВК"""
user = request.user
try:
logger.debug(f"[VK CALLBACK] Called by user ID {user.id}")
code = request.GET.get("code")
code_verifier = request.GET.get("code_verifier")
device_id = request.GET.get("device_id")
logger.debug(f"[VK CALLBACK] Params: code={code}, code_verifier={code_verifier}, device_id={device_id}")
if not code or not code_verifier:
logger.error("[VK CALLBACK] Missing code or code_verifier.")
return JsonResponse({'error': 'Missing required parameters.'}, status=400)
logger.info(f"[VK CALLBACK] Authenticated user: id={user.id}, email={user.email}")
token_url = "https://id.vk.com/oauth2/auth"
payload = {
'grant_type': 'authorization_code',
'code': code,
'redirect_uri': 'https://storisbro.com/accounts/vk/login/callback/',
'client_id': settings.SOCIAL_AUTH_VK_OAUTH2_KEY,
'client_secret': settings.SOCIAL_AUTH_VK_OAUTH2_SECRET,
'code_verifier': code_verifier,
'device_id': device_id,
}
headers = {'Content-Type': 'application/x-www-form-urlencoded'}
logger.debug(f"[VK CALLBACK] Sending token request to VK")
response = requests.post(token_url, data=payload, headers=headers)
logger.debug(f"[VK CALLBACK] VK response: {response.status_code} - {response.text}")
if response.status_code != 200:
logger.error(f"[VK CALLBACK] Failed to exchange code: {response.text}")
return JsonResponse({'error': 'Failed to exchange code for tokens.'}, status=response.status_code)
data = response.json()
access_token = data.get('access_token')
refresh_token = data.get('refresh_token')
expires_in = data.get('expires_in', 86400)
logger.debug(
f"[VK CALLBACK] Received tokens: access_token={bool(access_token)}, refresh_token={bool(refresh_token)}, expires_in={expires_in}")
if not access_token or not refresh_token:
logger.error("[VK CALLBACK] Missing tokens in VK response.")
return JsonResponse({'error': 'Tokens not received from VK.'}, status=400)
user_data = fetch_vk_user_info(access_token)
vk_user_id = user_data.get('user_id')
logger.debug(f"[VK CALLBACK] VK user ID: {vk_user_id}")
if not vk_user_id:
logger.error("[VK CALLBACK] VK user ID not found.")
return JsonResponse({'error': 'Failed to retrieve VK user info.'}, status=400)
existing_user = User.objects.filter(vk_user_id=vk_user_id).exclude(id=user.id).first()
if existing_user:
logger.warning(f"[VK CALLBACK] VK account {vk_user_id} already linked to user {existing_user.id}.")
return JsonResponse({'error': 'This VK account is already linked to another user.'}, status=400)
logger.debug(f"[VK CALLBACK] Updating user profile from VK data.")
update_vk_user_profile(user, user_data, device_id)
logger.debug(f"[VK CALLBACK] Saving VK tokens.")
update_vk_tokens(user, access_token, refresh_token, expires_in)
logger.info(f"[VK CALLBACK] VK account linked for user {user.id}")
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
f"user_{user.id}",
{
"type": "vk_auth",
"authenticated": True,
"vk_user_id": vk_user_id,
}
)
return JsonResponse({
'status': 'success',
'message': 'VK account linked successfully. Please authorize groups.',
})
except Exception as e:
logger.exception("[VK CALLBACK] Unexpected error")
return JsonResponse({'error': str(e)}, status=500)
Файл middleware.py
import jwt
import logging
import django
from channels.middleware import BaseMiddleware
from django.conf import settings
from urllib.parse import parse_qs
from asgiref.sync import sync_to_async
from rest_framework_simplejwt.settings import api_settings
logger = logging.getLogger("communities.middleware")
class JWTAuthMiddleware(BaseMiddleware):
def init(self, inner):
super().init(inner)
async def call(self, scope, receive, send):
from django.contrib.auth import get_user_model # Переносим внутрь метода
User = get_user_model()
query_string = scope.get("query_string", b"").decode()
logger.info(f"[JWT MW] raw query_string: {query_string!r}")
params = parse_qs(query_string)
token = params.get("token", [None])[0] # Берем токен из URL
logger.info(f"Extracted token: {token}")
if not token:
logger.warning("[JWT] No token, closing WS")
await send({"type": "websocket.close", "code": 4001})
return
if token:
try:
secret_key = api_settings.SIGNING_KEY
payload = jwt.decode(token, secret_key, algorithms=["HS256"])
logger.info(f"Decoded JWT payload: {payload}")
user = await sync_to_async(User.objects.get)(id=payload['user_id'])
scope['user'] = user # Кладем пользователя в scope
logger.info(f"User authenticated: {user}")
except jwt.ExpiredSignatureError:
logger.warning("[JWT MW] Token expired, closing")
await send({"type": "websocket.close", "code": 4002})
return
except Exception as e:
logger.exception(f"[JWT MW] JWT error: {e!r}")
await send({"type": "websocket.close", "code": 4003})
return
return await self.inner(scope, receive, send)
Файл consumer.py
import json
import logging
from channels.generic.websocket import AsyncWebsocketConsumer
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(name)
class AuthStatusConsumer(AsyncWebsocketConsumer):
async def connect(self):
logger.info(f"[Consumer] connect() called, scope['user'] = {self.scope.get('user')!r}")
self.user = self.scope.get('user')
logger.info(f"WebSocket connection attempt: user={self.user}")
if not(self.user and self.user.is_authenticated):
await self.close(code=4001)
logger.info("WebSocket connection closed (unauthenticated)")
return
self.groupname = f"user{self.user.id}"
await self.channel_layer.group_add(self.group_name, self.channel_name)
await self.accept()
await self.send_auth_status()
logger.info(f"WebSocket connected and added to group")
async def disconnect(self, close_code):
await self.channel_layer.group_discard(self.group_name, self.channel_name)
logger.info(f"WebSocket disconnected: {close_code}")
async def send_auth_status(self):
is_authenticated = bool(self.user.vk_user_id)
response_data = {
'authenticated': is_authenticated,
'vk_user_id': self.user.vk_user_id if self.user else None
}
logger.info(f"Sending auth status: {response_data}")
await self.send(text_data=json.dumps(response_data))
async def vk_auth(self, event):
"""Обрабатывает сообщения об изменении статуса VK аутентификации"""
logger.info(f"Received vk_auth event: {event}")
response_data = {
'authenticated': event.get('authenticated', False),
'vk_user_id': event.get('vk_user_id')
}
await self.send(text_data=json.dumps(response_data))
Файл urls.py
from .views import get_user_groups, add_user_group, vk_callback
urlpatterns = [
path('vk/callback/', vk_callback, name='vk_callback'),
path('api/vk/groups/', get_user_groups, name='get_user_groups'),
path('api/vk/add-group/', add_user_group, name='add_user_group'),
На самом сайте ссылка точно получается в виде websocket и создается тоже правильно, но почему-то всегда имеет status - Finished, хотя как я понял должна быть 101. Этот момент для меня тоже не понятен.
Если кто-то сталкивался с таким, или просто может помочь выявить ошибку, помогите пожалуйста, если будет нужно, то готов предоставить больше кода и информации.
Сразу скажу, что в том, что направление и конфиги настроены верно - я уверен. Но вот в чем проблема и почему данные не отправляются я понять не могу.