Skip to content

Callback with x-www-form-urlencoded expression #2725

@thomascombe

Description

@thomascombe

Context

My app specification has a callback using expressions from x-www-form-urlencoded ({$request.body#/url}).
The URL parameter is not decoded from FORM Url-Encode (it works when using JSON)

Current Behavior

Callback not executed:

[15:34:01] ›     [CALLBACK] ℹ  info      actions: > Executing "post" callback to ?token=...
[15:34:01] ›     [CALLBACK] ✖  error     actions: Request failed: Only absolute URLs are supported

Expected Behavior

The callback should execute the same way as it does for a JSON request.

[4:23:48 PM] ›     [CALLBACK] ℹ  info      actions: > Executing "post" callback to http://localhost:4011/notify?token=ssecurre...
[4:23:48 PM] ›     [CALLBACK] ✖  error     actions: Request failed: request to http://localhost:4011/notify?token=ssecurre failed, reason: 

(SSL error because of localhost env)

Possible Workaround/Solution

If I dump request, I can find custom path around my JSON:

{
  method: 'post',
  url: { path: '/invoices/123/subscribe', baseUrl: undefined, query: {} },
  headers: {
    host: '127.0.0.1:4010',
    'user-agent': 'curl/8.7.1',
    accept: '*/*',
    'content-type': 'application/x-www-form-urlencoded',
    'content-length': '57'
  },
  body: {
    _tag: 'Right',
    right: { url: 'http://localhost:4011/notify', token: 'ssecurre' }
  }
}

(packages/http/src/mocker/callback/callbacks.ts:runCallback)

_tag and right are added by packages/http/src/validator/validators/body.ts:deserializeFormBody)

Steps to Reproduce

Use callback example and change application/json validation to x-www-form-urlencoded.

{
  "openapi": "3.0.0",
  "paths": {
    "/invoices/{id}/subscribe": {
      "parameters": [
        {
          "name": "id",
          "in": "path",
          "required": true,
          "description": "The id of the invoice about which you want to receive notifications",
          "schema": {
            "$ref": "#/components/schemas/invoiceId"
          }
        }
      ],
      "post": {
        "summary": "Subscription to events about given invoice",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "properties": {
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "token": {
                    "type": "string"
                  }
                },
                "required": [
                  "url",
                  "token"
                ]
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Successfully subscribed to events about given invoice",
            "content": {
              "text/plain": {
                "examples": {
                  "ok": {
                    "value": "ok"
                  }
                }
              }
            }
          }
        },
        "callbacks": {
          "actions": {
            "{$request.body#/url}?token={$request.body#/token}": {
              "post": {
                "summary": "Receive notification about certain invoice",
                "requestBody": {
                  "required": true,
                  "content": {
                    "application/json": {
                      "schema": {
                        "$ref": "#/components/schemas/notification"
                      }
                    }
                  }
                },
                "responses": {
                  "200": {
                    "description": "Notification successfully processed",
                    "content": {
                      "text/plain": {
                        "examples": {
                          "ok": {
                            "value": "ok"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "invoiceId": {
        "type": "integer",
        "format": "int64"
      },
      "notification": {
        "type": "object",
        "properties": {
          "invoiceId": {
            "$ref": "#/components/schemas/invoiceId"
          },
          "action": {
            "type": "string",
            "enum": [
              "paid",
              "expired",
              "failure"
            ]
          }
        },
        "required": [
          "invoiceId",
          "action"
        ]
      }
    }
  }
}

Run prism:

prism mock mock.json -v=trace

Launch curl:

curl -v -X POST \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "url=http://localhost:4011/notify" \
  --data-urlencode "token=ssecurre" \
  http://127.0.0.1:4010/invoices/123/subscribe

Environment

  • Version used: 5.14.2
  • Environment name and version: NodeJS v25.2.1
  • Operating System and version (desktop or mobile): MacOS

Metadata

Metadata

Assignees

No one assigned

    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