[Python] How to receive the request object from webhook, Clientdisconnect exception. `Client...

Discussão em 'Python' iniciado por Stack, Agosto 11, 2025.

  1. Stack

    Stack Membro Participativo

    I'm integrating the LINE messaging API with bot server. Likewise the Whatsapp Business API. To create the public URL, I used ngrok. Now whenever the user send the message to us, the LINE server send the request to our server. But I'm stuck in such common issue, first I wasn't receiving the request object, sometime server receive and sometime server say exception client disconnected. After RCA, I found that the LINE server which act as a client while sending the request to bot server, disconnected due to timeout, Just to clarify, the server processing is so fast, it's not the bot server issue. I'm not getting why I don't receive the request object. So I can process it. As I'm using ngrok, ngrok does provide the inspection for the request handling. Below is my code:

    @line_router.post("/callback")
    async def handle_webhook(request: Request, background_tasks: BackgroundTasks):
    st = time.time()
    logger.info(f"Received LINE webhook request at {st}")

    try:

    body_bytes = await request.body()

    signature = request.headers.get("X-Line-Signature")
    response = JSONResponse(content={"status": "success", "message": "Webhook received"}, status_code=200)

    et = time.time()
    logger.info(f"[Time] Processing Time: {et-st}")
    except ClientDisconnect:
    logger.warning("Client disconnected before the request body could be fully read.")
    et = time.time()
    logger.info(f"[Time] Processing Time: {et-st}")
    try:
    retry = get_last_failed_request()
    if retry:
    body_bytes, signature = retry
    logger.info("[RETRY] Retrying with last failed request data.")
    background_tasks.add_task(process_failed_line_webhook, body_bytes, signature)
    return JSONResponse(content={"status": "success", "message": "Webhook received"}, status_code=200)
    except Exception:
    logger.exception("Retry failed.")

    return JSONResponse(content={"status": "error", "message": "Service temporarily unavailable, please retry."}, status_code=503)

    background_tasks.add_task(process_line_webhook, body_bytes, signature)

    return response


    async def process_failed_line_webhook(body: str, signature: str):
    try:
    logger.info(f"[Decode] Incoming Webhook Data: {body}")
    logger.info(f"[Signature] Received LINE Callback request with signature: {signature}")

    if not line_client.verify_signature(body, signature if isinstance(signature, str) else signature[0]):
    logger.error("Invalid signature")
    raise HTTPException(status_code=400, detail="Invalid signature")

    else:
    logger.info("Signature verified successfully.")

    data = json.loads(body)
    events = data.get("events", [])
    for event in events:
    logger.info(f"Incoming Event: {event}")

    if event.get("type") == "message":

    user_id = event.get("source", {}).get("userId")
    reply_token = event.get("replyToken")

    allowed_list = []

    if user_id not in allowed_list:
    line_client.send_text(
    reply_token, "Test")
    else:
    redis_data = {
    "message": json.dumps(event)
    }
    redis_client.xadd( stream_name, redis_data )
    logger.info(f"Message_Added_to_Redis : {redis_data}")

    return JSONResponse(content={"status": "success", "message": "Messages Recieved successfully"}, status_code=200)

    return JSONResponse(
    content={"status": "success", "message": "Messages processed successfully"},
    status_code=200
    )

    except HTTPException as http_exc:
    logger.error(f"HTTP Exception in LINE webhook: {http_exc.detail}")
    raise

    except Exception:
    logger.exception(f"Error handling Line webhook: ")
    return JSONResponse(
    content={"status": "error"},
    status_code=500
    )


    I tried to send 200 as soon as I'll receive the request to avoid the client disconnect issue. I tried to get the request as stream, and send 200 as soon as I get the first chunk. But the issue persist because I'm not getting the request object at all and went for exception. Now using the ngrok/inspect to get the last recent request. But It's for testing because on server I'll be using my own domain for public url in LINE, no ngrok.

    Continue reading...

Compartilhe esta Página