Skip to content

API validation is bypassed if content-type header is missing #100

Open

Description

@avilaton

Hi everyone, I think we have found a bug in restates's API validation.

Given a service with 3 mandatory arguments make(str),year(str),model (int), we found that this request

curl --request POST \
  --url 'http://restate:8080/Vins/notify_missing_suggested_vin/send' \
  --header 'Content-Type: application/json'

fails with 400 status error and this message

{"message":"input validation error: Empty body not allowed"}

while this

curl --request POST \
  --url 'http://restate:8080/Vins/notify_missing_suggested_vin/send'

succeeds, and creates an invocation with broken parameters

{"invocationId":"inv_1faXAMNrjkWq46yXz5nAKyjfuVEOa2rI7n","executionTime":"2025-05-29T02:20:35.027000000Z","status":"Accepted"}

which results in a never ending failing invocation since those empty parameters were actually expected.

Please let me know if you think we made a mistake filing this. Thanks for creating restate it is awesome.

Activity

  1. avilaton commented on May 29, 2025

    @avilaton
    Author

    More weird/incorrect cases

    Requests with incomplete data (missing year in this case)

    curl --request POST   --url 'http://restate:8080/Vins/notify_missing_suggested_vin/send' \
      --header 'Content-Type: application/json' \
      --data '{"make":"hola","model":"mundo"}'
    {"invocationId":"inv_1eDPloDKJ9ho6wP12kDcy4J4Wj7EdqLIlP","status":"Accepted"}
    

    but there are no signs of this invocation anywhere in the UI/CLI.

    These are also confusing, here we are rejected due to a validation error (we include content-type)

    curl --request POST   --url 'http://restate:8080/Vins/notify_missing_suggested_vin/send' \
      --header 'idempotency-key: 5' \
      --header 'Content-Type: application/json'
    {"message":"input validation error: Empty body not allowed"}
    

    while here we are allowed through (without sending content-type):

    curl --request POST   --url 'http://restate:8080/Vins/notify_missing_suggested_vin/send' \
      --header 'idempotency-key: 6'
    {"invocationId":"inv_16HxFwmpUywS6u2dDPl5Mso8x6SdiNPIr4","status":"Accepted"}
    

    Success cases

    Requests to direct invocations work

    curl --request POST   --url 'http://restate:8080/Vins/notify_missing_suggested_vin'   --header 'Content-Type: application/json' --data '{"make":"hola","model":"mundo","year":1234}'
    {"message":"Notified make hola model mundo year 1234 missing!"}
    

    as do requests to /send

    curl --request POST   --url 'http://restate:8080/Vins/notify_missing_suggested_vin/send' \
      --header 'Content-Type: application/json' \
      --data '{"make":"hola","model":"mundo","year":1234}'
    {"invocationId":"inv_1ePLdjQdwiml3k8I7fseQRoQFXhmFLkuCB","status":"Accepted"}
    
  2. slinkydeveloper commented on May 30, 2025

    @slinkydeveloper
    Contributor

    Will check this out. In the meantime which sdk are you using?

  3. avilaton commented on May 30, 2025

    @avilaton
    Author

    Thanks! We are using the python SDK with the latest release of everything.

  4. slinkydeveloper commented on Jun 2, 2025

    @slinkydeveloper
    Contributor

    Let me answer one by one on the cases here:

    Given a service with 3 mandatory arguments make(str),year(str),model (int), we found that this request

    curl --request POST
    --url 'http://restate:8080/Vins/notify_missing_suggested_vin/send'
    --header 'Content-Type: application/json'
    fails with 400 status error and this message

    {"message":"input validation error: Empty body not allowed"}

    This is correct, empty body is not a valid json

    while this

    curl --request POST
    --url 'http://restate:8080/Vins/notify_missing_suggested_vin/send'
    succeeds, and creates an invocation with broken parameters

    {"invocationId":"inv_1faXAMNrjkWq46yXz5nAKyjfuVEOa2rI7n","executionTime":"2025-05-29T02:20:35.027000000Z","status":"Accepted"}

    This one should indeed not happen, because missing the content type application json when the expected payload is json is wrong. cc @igalshilman

    Requests with incomplete data (missing year in this case)

    curl --request POST --url 'http://restate:8080/Vins/notify_missing_suggested_vin/send'
    --header 'Content-Type: application/json'
    --data '{"make":"hola","model":"mundo"}'
    {"invocationId":"inv_1eDPloDKJ9ho6wP12kDcy4J4Wj7EdqLIlP","status":"Accepted"}
    but there are no signs of this invocation anywhere in the UI/CLI.

    Be aware that the "schema" validation happens in the SDK at the moment, and not in restate-server. Restate will only check the content type, and whether the body is empty or not, the rest of the validation happens in the SDK.
    What probably happened here is that the invocation was rejected in the SDK, and after that is not retained. If you send the request with idempotency key, you'll see the failed result persisted after completion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions