[GH-ISSUE #1898] Scripting does not preserve binary payload #1891

Closed
opened 2026-03-03 19:55:12 +03:00 by kerem · 6 comments
Owner

Originally created by @baotrung-pham-20230331 on GitHub (Jan 2, 2024).
Original GitHub issue: https://github.com/ProxymanApp/Proxyman/issues/1898

Description

If "Content-Type: image/jpeg" is missing from the request header, scripting function seems to assume "Content-Type: application/x-www-form-urlencoded" and convert the binary payload to base64.

I suppose this is somewhat expected, given that the client should have included the correct "Content-Type" header, but sometimes its difficult for me to control this with our current client-side solution. It'd be nice if the Scripting feature does not make any assumption and send the request as-is.

Steps to Reproduce

  1. Enable Scripting
async function onRequest(context, url, request) {
  request.body = request.rawBody; // without this, payload is empty. 
  return request;
}
  1. send dummy image
curl 'https://www.example.com' \
-X POST \
--data-binary "@path-to-test-image.jpg" --proxy http://localhost:9090

Current Behavior

payload becomes b64 encoded string
image

binary payload is preserved
image

Environment

  • App version: e.g Proxyman 4.15.0
  • macOS version: macOS Monterey
Originally created by @baotrung-pham-20230331 on GitHub (Jan 2, 2024). Original GitHub issue: https://github.com/ProxymanApp/Proxyman/issues/1898 ## Description If "Content-Type: image/jpeg" is missing from the request header, scripting function seems to assume "Content-Type: application/x-www-form-urlencoded" and convert the binary payload to base64. I suppose this is somewhat expected, given that the client should have included the correct "Content-Type" header, but sometimes its difficult for me to control this with our current client-side solution. It'd be nice if the Scripting feature does not make any assumption and send the request as-is. ## Steps to Reproduce <!-- Add relevant code and/or a live example --> 1. Enable Scripting ``` async function onRequest(context, url, request) { request.body = request.rawBody; // without this, payload is empty. return request; } ``` 2. send dummy image ``` curl 'https://www.example.com' \ -X POST \ --data-binary "@path-to-test-image.jpg" --proxy http://localhost:9090 ``` ## Current Behavior <!--- What went wrong? --> payload becomes b64 encoded string <img width="857" alt="image" src="https://github.com/ProxymanApp/Proxyman/assets/129530501/1cf73abd-03f8-4f14-90d5-4d2ec63990de"> <!--- What should have happened? --> binary payload is preserved <img width="715" alt="image" src="https://github.com/ProxymanApp/Proxyman/assets/129530501/536f2b96-c3e0-43eb-98f9-5dfd7e0ebd19"> ## Environment - App version: e.g Proxyman 4.15.0 - macOS version: macOS Monterey
kerem 2026-03-03 19:55:12 +03:00
  • closed this issue
  • added the
    bug
    label
Author
Owner

@NghiaTranUIT commented on GitHub (Jan 2, 2024):

@baotrung-pham-20230331 I'm not sure why you do this:

async function onRequest(context, url, request) {
  // This line 👇
  request.body = request.rawBody; // without this, payload is empty. 
  return request;
}

It means you try to set the rawBody (base64) to the body, so you get the Base64 String in the Request Body. It's intended.

Remove this line, the image body will be preserved.

<!-- gh-comment-id:1873873472 --> @NghiaTranUIT commented on GitHub (Jan 2, 2024): @baotrung-pham-20230331 I'm not sure why you do this: ```js async function onRequest(context, url, request) { // This line 👇 request.body = request.rawBody; // without this, payload is empty. return request; } ``` It means you try to set the rawBody (base64) to the body, so you get the Base64 String in the Request Body. It's intended. Remove this line, the image body will be preserved.
Author
Owner

@baotrung-pham-20230331 commented on GitHub (Jan 2, 2024):

if i remove it, the body becomes empty.

image

also, if i add "Content-type: image/jpeg" to the request headers, the binary payload is preserved, with or without request.body = request.rawBody;

@baotrung-pham-20230331 I'm not sure why you do this:

async function onRequest(context, url, request) {
  // This line 👇
  request.body = request.rawBody; // without this, payload is empty. 
  return request;
}

It means you try to set the rawBody (base64) to the body, so you get the Base64 String in the Request Body. It's intended.

Remove this line, the image body will be preserved.

<!-- gh-comment-id:1874003870 --> @baotrung-pham-20230331 commented on GitHub (Jan 2, 2024): if i remove it, the body becomes empty. <img width="710" alt="image" src="https://github.com/ProxymanApp/Proxyman/assets/129530501/5ff538c2-2d74-4c74-bb5f-d1e1958002c5"> also, if i add "Content-type: image/jpeg" to the request headers, the binary payload is preserved, with or without `request.body = request.rawBody;` > @baotrung-pham-20230331 I'm not sure why you do this: > > ```js > async function onRequest(context, url, request) { > // This line 👇 > request.body = request.rawBody; // without this, payload is empty. > return request; > } > ``` > > It means you try to set the rawBody (base64) to the body, so you get the Base64 String in the Request Body. It's intended. > > Remove this line, the image body will be preserved.
Author
Owner

@NghiaTranUIT commented on GitHub (Jan 2, 2024):

It's hard to fix because the Content-Type indicates it's a application/x-www-form-urlencoded. So Proxyman tries to parse your Image as a form data -> Lead to incorrect data.

You can fix it by overriding the Content-Type

async function onRequest(context, url, request) {
request.headers["Content-Type"] = "application/octet-stream";
 request.body = request.rawBody;
  return request;
}

<!-- gh-comment-id:1874050433 --> @NghiaTranUIT commented on GitHub (Jan 2, 2024): It's hard to fix because the Content-Type indicates it's a `application/x-www-form-urlencoded`. So Proxyman tries to parse your Image as a form data -> Lead to incorrect data. You can fix it by overriding the Content-Type ```js async function onRequest(context, url, request) { request.headers["Content-Type"] = "application/octet-stream"; request.body = request.rawBody; return request; } ```
Author
Owner

@baotrung-pham-20230331 commented on GitHub (Jan 2, 2024):

Thanks for the prompt reply :)

Yes, I suppose that would work.
However, I never actually add any Content-Type header in this request. The application/x-www-form-urlencoded was somehow assumed by the Scripting feature

curl 'https://www.example.com' \
-X POST \
--data-binary "@path-to-test-image.jpg" --proxy http://localhost:9090
<!-- gh-comment-id:1874064833 --> @baotrung-pham-20230331 commented on GitHub (Jan 2, 2024): Thanks for the prompt reply :) Yes, I suppose that would work. However, I never actually add any Content-Type header in this request. The `application/x-www-form-urlencoded` was somehow assumed by the Scripting feature ``` curl 'https://www.example.com' \ -X POST \ --data-binary "@path-to-test-image.jpg" --proxy http://localhost:9090 ```
Author
Owner

@NghiaTranUIT commented on GitHub (Jan 2, 2024):

It's from cURL. I disable the Scripting tool and run your cURL command. The application/x-www-form-urlencoded header is automatically added.

Screenshot 2024-01-02 at 22 18 12
<!-- gh-comment-id:1874160293 --> @NghiaTranUIT commented on GitHub (Jan 2, 2024): It's from `cURL`. I disable the Scripting tool and run your cURL command. The `application/x-www-form-urlencoded ` header is automatically added. <img width="725" alt="Screenshot 2024-01-02 at 22 18 12" src="https://github.com/ProxymanApp/Proxyman/assets/5878421/4995ba2b-1b08-4199-b437-e2495aa6b4e0">
Author
Owner

@baotrung-pham-20230331 commented on GitHub (Jan 2, 2024):

dang...you are right.

I'll close this issue then. Thank you

<!-- gh-comment-id:1874179955 --> @baotrung-pham-20230331 commented on GitHub (Jan 2, 2024): dang...you are right. I'll close this issue then. Thank you
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/Proxyman#1891
No description provided.