Fastapi websockets.exceptions.PayloadTooBig: payload length exceeds size limit - fastapi

I have created a backend server and we are sending data from the frontend to the backend by using sockets. Now we have to share some images that are encoded into base64.
When we are doing that we are getting below error.
websockets.exceptions.PayloadTooBig: payload length exceeds size limit
Below connection manager class.
class ConnectionManager:
def __init__(self):
self.active_connections: List[WebSocket] = []
async def connect(self, websocket: WebSocket):
await websocket.accept()
self.active_connections.append(websocket)
def disconnect(self, websocket: WebSocket):
self.active_connections.remove(websocket)
async def send_personal_message(self, message: str, websocket: WebSocket):
await websocket.send_text(message)
async def send_json(self, json, websocket: WebSocket):
await websocket.send_json(json)
async def broadcast(self, message: str):
for connection in self.active_connections:
await connection.send_text(message)
manager = ConnectionManager()
await manager.connect(websocket)
json.loads(await websocket.receive_text())

Related

NextAuth: How do I get the JWT Session Token (undecoded) on the client?

I've tried getting the session token from the next-auth.session-token cookie, but failed to get the value of the cookie (even after using multiple libraries).
I tried passing token along with the session when forming the session object, but it seems to return the decoded token instead of the raw JWT token text.
I need the JWT token to be able to send it across to another service that I need to authenticate with (Hasura, through URQL).
Right now, I have a hack set up: I have created an API /api/me which returns the token for the currently logged in user.
import type { NextApiRequest, NextApiResponse } from "next";
import { getToken } from "next-auth/jwt";
export default async (req: NextApiRequest, res: NextApiResponse) => {
const token = await getToken({ req, raw: true });
res.status(200).json({ token });
};
and then I instantiate the urql client from the response of this API, but I don't want to spend precious ms making another fetch.
How do I get the JWT Session Token (undecoded) on the client?

Close stream after all data has been recieved

I am trying to make an HTTP request (I realise there is an http package that would probably make this easier but I want to learn how to do it with dart:io). My code below successfully prints out index.html from example.com, except the program runs forever, I assume because it is continues listening for data from the response. How do I stop the listener once all the data has been received from the stream? I assume I need to pass a handler to the onDone argument but I'm not sure what. I tried calling response.detachSocket() as per below, as that was the only logical seeming thing I could find, but it didn't work. If it's not obvious, I'm not totally sure what I'm doing here so any explanation would be greatly appreciated.
import 'dart:convert';
import 'dart:io';
main() async {
var client = new HttpClient();
var request = await client.getUrl(Uri.parse("http://www.example.com/"));
var response = await request.close();
response.transform(utf8.decoder).listen((data) {
print(data);
}, onDone: () => response.detachSocket());
}
You never close your HttpClient. Close it after you're done with it. The stream subscription will close itself when it's done, the onDone handler is a convenient way to run code when a stream completes, it's not necessary to use it to close the stream.
import 'dart:convert';
import 'dart:io';
main() async {
var client = new HttpClient();
var request = await client.getUrl(Uri.parse("http://www.example.com/"));
var response = await request.close();
response.transform(utf8.decoder).listen((data) {
print(data);
}, onDone: () => response.detachSocket());
client.close();
}
There is also no need to detach the socket.
You could even call client.close earlier with the force parameter set to false, which is the default:
main() async {
var client = new HttpClient();
var request = await client.getUrl(Uri.parse("http://www.example.com/"));
client.close();
var response = await request.close();
response.transform(utf8.decoder).listen((data) {
print(data);
});
}

How to pull in Heroku postgres credentials for next-auth?

I'm trying to use a postgres instance on Heroku with Next-Auth.js Heroku's documentation notes that the credentials shouldn't be hardcoded into the application; so, I'm trying to use Heroku's api to pull in the needed url. My issue - I think - is when I try to run the axios request asynchronously, the value of the return statement isn't being assigned to the database property of the options object. What am I doing wrong? Many thanks!
import NextAuth from "next-auth";
import Providers from "next-auth/providers";
const axios = require("axios");
// Heroku api key and postgres instance
const herokuApiKey = PROCESS.ENV.API_KEY;
const herokuPostgres = PROCESS.ENV.POSTGRES_INSTANCE;
// Connection to Heroku API
const herokuApi = axios.create({
baseURL: `https://api.heroku.com`,
headers: {
Authorization: `Bearer ${herokuApiKey}`,
Accept: "application/vnd.heroku+json; version=3",
},
});
// Async function to get database string
const getCredentials = async () => {
const response = await herokuApi.get(`addons/${herokuPostgres}/config`);
const pgConnStr = response.data[0].value; // Logging this value displays the needed string
return pgConnStr;
};
export default async (req, res) => NextAuth(req, res, {
providers: [
Providers.Email({
server: process.env.EMAIL_SERVER,
from: process.env.EMAIL_FROM,
}),
],
database: getCredentials(),
});
Your getCredentials is an async function, meaning it returns a promise. As such you'll need to await for it.
database: await getCredentials()

Custom authentication backend not called with Django rest?

I'm trying to use Firebase for my django rest / nuxt project and I need to verify the id tokens after the user logs in - I only use Firebase for the auth part.
My custom auth class looks like this:
class FirebaseAuthentication(authentication.BaseAuthentication):
def authenticate(self, request, **kwargs):
print("Why is this never called")
auth_header = request.META.get("HTTP_AUTHORIZATION")
if not auth_header:
raise NoAuthToken("No auth token provided")
id_token = auth_header.split(" ").pop()
decoded_token = None
try:
decoded_token = auth.verify_id_token(id_token)
except Exception:
raise InvalidAuthToken("Invalid auth token")
pass
if not id_token or not decoded_token:
return None
try:
uid = decoded_token.get("uid")
except Exception:
raise FirebaseError()
user, created = User.objects.get_or_create(email=uid)
user.profile.last_activity = timezone.localtime()
return (user, None)
And in my settings.py I got
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"firebase.authentication.FirebaseAuthentication",
),
}
views.py
#require_POST
def login_view(request):
data = json.loads(request.body)
email = data.get("email")
password = data.get("password")
if email is None or password is None:
return JsonResponse({"detail": "Please provide email and password."}, status=400)
user = authenticate(email=email, password=password)
if user is None:
return JsonResponse({"detail": "Invalid credentials."}, status=400)
login(request, user)
return JsonResponse({"detail": "Successfully logged in.", "isAuthenticated": True})
And on my nuxt app, the login:
async login() {
this.error = null;
try {
const response = await firebase.auth().signInWithEmailAndPassword(this.email, this.password);
const token = await response.user.getIdTokenResult();
console.log(token.token);
const res = await fetch("/account/login/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"HTTP_AUTHORIZATION": token.token,
"X-CSRFToken": this.$store.getters.CSRFToken
},
credentials: "include",
mode: "cors",
body: JSON.stringify({ email: this.email, password: this.password }),
});
return await res.json()
} catch (error) {
this.error = error;
}
},
I get a 200 everywhere - the user is logged in, both on firebase and on the django side of things, but the FirebaseAuthentication is not fired. What am I missing?
You are mixing two steps
Obtain JWT token from Firebase
Authenticate the user by django REST ("DEFAULT_AUTHENTICATION_CLASSES") by obtained JWT token from step 1.
Login view is unnecessary here. You already did it from Frontend side.
Now you should do; just write class based view (prefer class based view to function based view).
NB: authenticate function will call AUTHENTICATION_BACKENDS not DEFAULT_AUTHENTICATION_CLASSES under REST_FRAMEWORK dict.
from rest_framework.permissions import IsAuthenticated
class SampleProtectedAPIView(APIView):
permission_classes = (IsAuthenticated,) # Must include it to test user is authenticated
def post(self, request, *args, **kwargs):
print(request.user) # will get user instance

How do I check for async functions in Python that have been called without await?

Let's say we have the following functions:
async def x1():
print("inside x1")
async def x2():
print("inside x2")
async def main():
await x1()
x2()
await asyncio.sleep(5)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
I will get a warning of the following:
RuntimeWarning: coroutine 'x2' was never awaited
Are there any way to make Python raises an error instead of just printing a warning?

Resources