Search code examples
azureazure-api-managementapi-gateway

WebSocket service always closes the connection after receiving a message from the client when connecting through Azure API Management


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 enter image description here

Result from my custom log on service when call it directly enter image description here


Network trace from backend.

Red is API management. Blue is backend. enter image description here

Network trace from my local machine.

Red is API management. Green is local machine.

enter image description here


Logs from APIM enter image description here enter image description here


Solution

  • 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