Skip to content

Bug: PUT/PATCH/DELETE request body not parsed in local dev server (createActionParametersFromRequest) #164

@aawanchiri

Description

@aawanchiri

Description

The local dev server (aio app dev) does not parse the request body for PUT, PATCH, and DELETE HTTP methods. Only POST request bodies are parsed and merged into action parameters. This causes a discrepancy between the local dev environment and the actual Adobe I/O Runtime (OpenWhisk), where all HTTP methods with a body are correctly handled.

Environment

  • @adobe/aio-cli: 11.0.2
  • @adobe/aio-cli-plugin-app-dev: 2.2.0
  • Node.js: v22.x
  • OS: macOS (Darwin 24.6.0)

Steps to Reproduce

  1. Create a web action that accepts PUT with a JSON body:
    async function main(params) {                                                                                                                                             
      // params.myField should contain the body data       
      return { statusCode: 200, body: { received: params.myField } }
    }
                                                                                                                                                                              
  2. Run aio app dev
  3. Send a PUT request with a JSON body:
    curl -sk -X PUT "https://localhost:9080/api/v1/web//"
    -H "Content-Type: application/json"
    -d '{"myField": "hello"}'
  4. Expected: params.myField is "hello" (same behavior as deployed Runtime)
  5. Actual: params.myField is undefined — the body is silently discarded

Root Cause

In src/lib/run-dev.js, the function createActionParametersFromRequest (line 604) only processes the request body when the method is post:

// Current code (line 604)
if (params.__ow_method === 'post' && req.body !== null) {

This should include all HTTP methods that can carry a request body:

// Suggested fix
const methodsWithBody = ['post', 'put', 'patch', 'delete']
if (methodsWithBody.includes(params.__ow_method) && req.body !== null) {

The Express middleware (express.json()) already parses the body for all methods correctly. The issue is only in the condition that decides whether to merge req.body into the action params.

Impact

  • PUT/PATCH/DELETE actions with JSON body fail locally but work correctly when deployed to Adobe I/O Runtime
  • Developers cannot test REST APIs following standard HTTP conventions locally
  • Workaround requires sending data as query strings, which is not standard for mutation operations

Suggested Fix

Change line 604 in src/lib/run-dev.js:

  • if (params.__ow_method === 'post' && req.body !== null) {
  • const methodsWithBody = ['post', 'put', 'patch', 'delete']
  • if (methodsWithBody.includes(params.__ow_method) && req.body !== null) {

---- Recommended Format ;

#Expected Behaviour
The local dev server (aio app dev) should parse and merge the request body into action parameters for all HTTP methods that support a body — including PUT, PATCH, and DELETE — consistent with how Adobe I/O Runtime (OpenWhisk) handles these requests in production.

#Actual Behaviour
The local dev server only parses the request body for POST requests. When a PUT, PATCH, or DELETE request is made with a JSON body, the body is silently ignored and not merged into the action parameters. This causes the action to behave differently locally compared to when it is deployed to Adobe I/O Runtime.

#Steps to Reproduce

Create an Adobe App Builder project with a backend action that reads parameters from the request body (e.g. params.id, params.data).
Configure the action to be accessible via PUT, PATCH, or DELETE.
Start the local dev server with aio app dev.
Send a PUT, PATCH, or DELETE request to the local action endpoint with a JSON body:

bash curl -X PUT https://localhost:9080/api/v1/web/
-H "Content-Type: application/json"
-d '{"id": "123", "data": "updated-value"}'

Observe that the action receives an empty or incomplete parameter set — the body fields are missing.
Deploy the same action with aio app deploy and repeat the same curl request against the deployed Runtime URL — body parameters are received correctly.

#Sample Code that illustrates the problem
Action handler (actions/update/index.js):
javascriptasync function main(params) {
// Expected: { id: '123', data: 'updated-value' }
// Actual (local): {} — body not parsed for PUT/PATCH/DELETE
const { id, data } = params;

if (!id) {
return {
statusCode: 400,
body: { error: 'Missing required parameter: id' }
};
}

return {
statusCode: 200,
body: { message: Updated ${id} with ${data} }
};
}

module.exports = { main };
app.config.yaml (action configured for PUT):
yamlapplication:
actions: actions
runtimes:
default:
actions:
update:
function: actions/update/index.js
web: yes
annotations:
require-adobe-auth: false
Request that fails locally but works on Runtime:
bashcurl -X PUT https://localhost:9080/api/v1/web///update
-H "Content-Type: application/json"
-d '{"id": "123", "data": "updated-value"}'

Logs taken while reproducing problem

Local dev (aio app dev) — body params missing

{
"__ow_method": "put",
"__ow_headers": { "content-type": "application/json" },
"__ow_path": ""

❌ 'id' and 'data' are absent — body was not parsed

}

Adobe I/O Runtime (deployed) — body params correctly included

{
"__ow_method": "put",
"__ow_headers": { "content-type": "application/json" },
"__ow_path": "",
"id": "123", # ✅ present
"data": "updated-value" # ✅ present
}
Suspected source: The body-parsing middleware in aio-cli-plugin-app-dev likely has a condition that limits body parsing to POST only. The fix should extend this to also handle PUT, PATCH, and DELETE methods.

Environment Info

  System:
    OS: macOS 26.4
    CPU: (10) arm64 Apple M1 Pro
    Memory: 168.97 MB / 16.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 22.21.1 - /Users/allan/.nvm/versions/node/v22.21.1/bin/node
    Yarn: 1.22.22 - /Users/allan/.nvm/versions/node/v22.21.1/bin/yarn
    npm: 10.9.4 - /Users/allan/.nvm/versions/node/v22.21.1/bin/npm
  Virtualization:
    Docker: 24.0.6 - /usr/local/bin/docker
  npmGlobalPackages:
    @adobe/aio-cli: 11.0.2

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