Cloud Socket is a secure websocket application that uses AES-GCM encryption and is build on fastapi. This also allows you to have google cloud run server without cold starts as it always has an open connection
Project description
☁️ cloud-socket
A lightweight, encrypted WebSocket communication library for Python and JavaScript that enables secure real-time client-server communication with automatic connection management and end-to-end encryption.
✨ Features
- 🔒 End-to-end encryption using AES-GCM
- 🔄 Automatic connection rotation to prevent timeouts
- 🎯 Smart reconnection with window focus detection
- 📦 Type-safe request/response with dataclass support
- 🪝 Decorator-based method registration
- 🔑 Flexible authentication - bring your own auth system
- 📝 Built-in logging with customizable handlers
- ❄️ No cold starts when hosted in cloud functions
- 🎨 Framework agnostic - works with FastAPI or standalone
🚀 Installation
pip install cloud-socket
You'll also need the provided cloudSocket.js file in your frontend project.
📖 Learn by Example
Let's build a simple, secure echo service. This example will show you how to set up the backend, connect from the frontend, and call a Python function from JavaScript.
Step 1: Create the Python Backend
Create a file named main.py. This will be our server.
The server needs two key pieces of logic from you:
- A function to get a user-specific secret key for encryption.
- A function to validate a user's access token.
# main.py
import asyncio
from dataclasses import dataclass
from cloud_socket.auth import User
from cloud_socket.app import aserve
from cloud_socket.registry import register
# This is where you'd integrate your auth system (e.g., check a JWT)
# For this example, we'll just check if the token is not empty.
async def validate_access_token(user: User) -> bool:
print(f"Validating token for user {user.uid}...")
return bool(user.access_token)
# This function retrieves the secret key used for E2E encryption.
# IMPORTANT: This key should be securely managed and known only to the
# user and the server.
async def get_crypto_key(user: User) -> str:
print(f"Fetching crypto key for user {user.uid}...")
# In a real app, you might derive this from a user-specific secret.
return f"super-secret-key-for-{user.uid}"
# Define the structure of the request body using a dataclass.
# The `body` argument in the client's `api` call must match this.
@dataclass
class EchoPayload:
message: str
# Use the @register decorator to expose this function to clients.
# The function signature is flexible; `cloud-socket` injects the
# arguments it needs, like the validated `user` and the `body`.
@register("echo")
async def echo(user: User, body: EchoPayload):
print(f"User {user.uid} sent message: {body.message}")
return {"status": "ok", "response": f"Your message was: '{body.message}'"}
# Start the server
if __name__ == "__main__":
print("Starting Cloud Socket server on ws://localhost:8003/ws")
asyncio.run(
aserve(
get_crypto_key,
validate_access_token,
host="localhost",
port=8003,
)
)
Step 2: Set Up the JavaScript Client
Place cloudSocket.js in your frontend source folder. Here's how you can use it in a simple React component.
// src/App.js
import { useEffect, useState } from 'react';
import { setup, api } from './cloudSocket'; // Adjust the import path
function App() {
const [inputValue, setInputValue] = useState('Hello, world!');
const [result, setResult] = useState(null);
const [isLoading, setIsLoading] = useState(false);
// Setup the connection when the component mounts
useEffect(() => {
const uid = 'user-123';
// In a real app, the uid, access_token, and crypto_key
// would come from your authentication flow after a user logs in.
setup({
url: 'ws://localhost:8003/ws',
uid: uid,
access_token: 'a-valid-user-token',
crypto_key: `super-secret-key-for-${uid}`, // Must match the backend logic
});
}, []);
const handleEcho = async () => {
if (!inputValue) return;
setIsLoading(true);
setResult(null);
try {
// Call the backend function registered as "echo"
const response = await api({
method: 'echo',
body: {
message: inputValue, // This object must match the `EchoPayload` dataclass
},
});
setResult(response);
} catch (error) {
console.error('API call failed:', error);
setResult({ error: error.message });
}
setIsLoading(false);
};
return (
<div>
<h1>Cloud Socket Echo</h1>
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
placeholder="Enter a message"
/>
<button onClick={handleEcho} disabled={isLoading}>
{isLoading ? 'Sending...' : 'Send Echo'}
</button>
{result && (
<pre>
<strong>Response from server:</strong>
<br />
{JSON.stringify(result, null, 2)}
</pre>
)}
</div>
);
}
export default App;
Step 3: Run It!
-
Start the backend server:
python main.py -
Start your frontend application:
npm start
Now, open your browser, type a message, and click the button. You'll see the response from the Python server appear on the screen! 🎉
⚙️ API Reference
Backend (Python)
serve() & aserve()
This is the main function to start the WebSocket server.
aserve(
get_crypto_key: Callable[[User], str | Awaitable[str]],
validate_access_token: Callable[[User], bool | Awaitable[bool]],
host: str = 'localhost',
port: int = 8003,
log_handler: Callable[[CloudSocketLog], None] | None = None,
get_user_info: Callable[[User], dict | Awaitable[dict]] | None = None,
)
get_crypto_key(required): Anasyncor regular function that takes aUserobject and returns the user-specific secret string for deriving the encryption key.validate_access_token(required): Anasyncor regular function that takes aUserobject and returnsTrueif theiraccess_tokenis valid,Falseotherwise.log_handler(optional): A function to process structured logs from the server.get_user_info(optional): Anasyncor regular function to fetch and cache additional user details, available viaawait user.get_info().
@register(method_name)
A decorator to expose a function as an RPC endpoint. The arguments for the decorated function are automatically injected based on their type annotations.
Supported injectable arguments:
user: User: The authenticatedUserobject, containinguid,access_token, and user info.body: <YourDataclass>orbody: dict: The entire decrypted payload sent from the client.<param_name>: <YourDataclass>: If your client sends{ "body": { "param_name": { ... } } },cloud-socketwill automatically extract, validate, and deserializeparam_nameinto your dataclass.
Frontend (JavaScript)
setup(config)
Initializes and configures the WebSocket manager. Call this once when your application loads.
setup({
url: 'ws://your-server/ws',
uid: 'user-id-from-auth',
access_token: 'user-token-from-auth',
crypto_key: 'user-secret-for-encryption',
});
api(request)
Sends a secure request to the backend and returns a Promise that resolves with the server's response.
const response = await api({
method: 'method_name', // The string name from @register()
body: { /* your JSON-serializable payload */ }
});
🔒 A Note on Security
cloud-socket is designed to provide transport-level security. It encrypts the payload of your messages end-to-end.
However, you are responsible for the initial secure handling of credentials:
- Authentication: The user's
uidandaccess_tokenshould be obtained through a standard, secure authentication flow (e.g., OAuth, OIDC). - Key Management: The
crypto_keyis a shared secret. You must have a secure way for the client to obtain this key. It should never be hardcoded in the client-side source code. A common pattern is to fetch it from a secure API endpoint after the user has authenticated.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cloud_socket-0.0.1.tar.gz.
File metadata
- Download URL: cloud_socket-0.0.1.tar.gz
- Upload date:
- Size: 17.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a6e95272a31ab31bee5ed1771b072a399add2bc96bbae626fa54978592cca4b6
|
|
| MD5 |
3f332a7e1993dcf7a4ceb9860b3826fb
|
|
| BLAKE2b-256 |
bcf8673f3eaeb72418c8dcbe9ab8d10ccfa3abed005f71f068a91e6597cf6f75
|
File details
Details for the file cloud_socket-0.0.1-py3-none-any.whl.
File metadata
- Download URL: cloud_socket-0.0.1-py3-none-any.whl
- Upload date:
- Size: 12.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0f664e6e352634e3383ace869d94f1e4f4c183c87e7ef571f0655b55891ce621
|
|
| MD5 |
be873d3f43850a6ba7d50fdf532b1338
|
|
| BLAKE2b-256 |
d4abc30e3022171d2ae922c4b415766774ba2c3a9ac66e3e47eac7307604e272
|