Skip to content

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

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions