1

I have a webhook listener that uses an APIRouter to designate the route for the application on the FastAPI server. The app should receive a POST request (expecting data in JSON format) and log this to the console. However, I am getting consistent redirects. I have attempted the following with curl:

curl -X 'POST' \
'http://127.0.0.1:8010/webhook' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{"data": {"UK":"test"}}'

The listener:

import hmac
from logging import Logger, info
from fastapi import APIRouter, FastAPI, Header, Request, Response
from router.router1 import rout
from pydantic import BaseModel

WEBHOOK_SECRET = '123-456-789'

class WebhookResponse(BaseModel):
    result: str

class WebhookData(BaseModel):
    body: dict

app = FastAPI()
rout = APIRouter()

@app.get("/")
async def welcome() -> dict:
    return { "message": 'Hello World!' }

def printLog(data):
    info(f"Raw data: {data}")

@rout.post("/webhook", response_model=WebhookResponse, status_code=200)
async def webhook(
    webhook_input: WebhookData,
    request: Request,
    response: Response,
    content_length: int = Header(...),
    x_hook_signature: str = Header(None)
):
    if content_length > 1_000_000:
        # To prevent memory allocation attacks
        Logger.error(f"Content too long ({content_length})")
        response.status_code = 400
        return {"result": "Content too long"}
    if x_hook_signature:
        raw_input = await request.body()
        input_hmac = hmac.new(
            key=WEBHOOK_SECRET.encode(),
            msg=raw_input,
            digestmod="sha512"
        )
        if not hmac.compare_digest(
                input_hmac.hexdigest(),
                x_hook_signature
        ):
            Logger.error("Invalid message signature")
            response.status_code = 400
            return {"result": "Invalid message signature"}
        Logger.info("Message signature checked ok")
    else:
        Logger.info("No message signature to check")
    printLog(webhook_input)
    return {"result": "ok"}

app.include_router(rout)

Curl prints out the following error:

{
    "detail": [
        {
            "loc": [
                "body"
            ],
            "msg": "value is not a valid dict",
            "type": "type_error.dict"
        }
    ]
}

With the following printed to console:

INFO:     127.0.0.1:50192 - "POST /webhook/ HTTP/1.1" 422 Unprocessable Entity
Chris
  • 18,724
  • 6
  • 46
  • 80
joe_bill.dollar
  • 374
  • 1
  • 9
  • If you add the `-L` option to your curl request, curl will follow the redirect. – D Malan Oct 28 '22 at 12:29
  • This is a separate question to your one before. You should rather create a separate SO question and revert this one. – D Malan Oct 28 '22 at 12:30
  • The body of the 422 error will have information about exactly what was missing; but please don't edit questions to change the meaning of them as the comments and the (now deleted) answer otherwise is out of place. – MatsLindh Oct 28 '22 at 13:04

2 Answers2

0

You called your dict “data” in your curl , should be called “body”.

JarroVGIT
  • 4,291
  • 1
  • 17
  • 29
0

You are using data as the field name for the body content that you are sending in the curl request, whereas in the Pydantic model this is defined as body. Hence, the error that is being raised complaining about the body value is not a valid dict. The curl requet's body should instead look like this (using the same field name given in your backend):

{
  "body": {"UK":"test"}
}

I would suggest you have a look at similar posts about how to post JSON data here, here, as well as here and here. Also, you can use the auto-generated docs provided by OpenAPI specification and Swagger UI at /docs, which would allow you to see the expected format of the data, as well as provide you with the relevant Curl command.

Chris
  • 18,724
  • 6
  • 46
  • 80