I deployed a WebSocket service on Azure Kubernetes. It's worked fine if connect to the service directly, but when I try to connect my service through API Management. It always closes the connection after receiving a message from the client.
Service code
from fastapi import FastAPI, Request, Header, Response
from fastapi import WebSocket, WebSocketDisconnect, Query
from fastapi.middleware.cors import CORSMiddleware
from pathlib import Path
import os
import time
import websockets
import logging
from custom_logging import CustomizeLogger
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# logger = logging.getLogger(__name__)
config_path=Path(__file__).with_name("log_config.json")
logger = CustomizeLogger.make_logger(config_path)
@app.websocket("/ws")
async def websoc(websocket: WebSocket):
await websocket.accept()
try:
while True:
msg = await websocket.receive_text()
logger.info('recieve:'+ msg)
await websocket.send_text(msg)
except Exception as e:
logger.info(e)
Client Code
import websockets
import asyncio
import time
async def send_receive():
async with websockets.connect(
'wss://xxxx.azure-api.net/testwebsocket?subscription-key=xxx',
ping_interval=5,
ping_timeout=20) as websocket:
for i in range(10):
await websocket.send(str(i))
await asyncio.sleep(0.1)
msg = await websocket.recv()
print(msg)
asyncio.run(send_receive())
Result from my custom log on service when call through API management
Result from my custom log on service when call it directly
Network trace from backend.
Red is API management.
Blue is backend.
Network trace from my local machine.
Red is API management. Green is local machine.
APIM does not support custom Sec-WebSocket-Extensions
. Your client websocket library is likely sending some. You can add a set Sec-WebSocket-Extensions
header to be empty in api policy and confirm. Refer https://learn.microsoft.com/en-us/azure/api-management/api-management-transformation-policies#SetHTTPheader