Repository: chimurai/http-proxy-middleware
Pull request #1015 (2024-06-27 03:17:22)

fix(fix-request-body): support '+json' content-type suffix
<!--- Provide a general summary of your changes in the Title above -->

## Description

<!--- Describe your changes in detail -->
Enhance `fixRequestBody` method to fix `Content-Type` includes `+json`

## Motivation and Context

<!--- Why is this change required? What problem does it solve? -->
<!--- If it fixes an open issue, please link to the issue here. -->
Now, if our Media Type includes `+json` but does not includes `application/json`, the `fixRequestBody` method will not work. For example, the Media Type is `application/merge-patch+json`.

According to [RFC 6838](https://datatracker.ietf.org/doc/html/rfc6838#section-4.2.8), the `+` suffix indicates a structured type. Therefore, for the Media Type includes `+json`, we can directly serialize it to JSON.

This PR fixes the issue where the `fixRequestBody` method does not work for Media Types includes `+json`, such as `application/merge-patch+json`.

## How has this been tested?

<!--- Please describe in detail how you tested your changes. -->
Unit Test

## Types of changes

<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)

## Checklist:

<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [ ] My change requires a change to the documentation.
- [ ] I have updated the documentation accordingly.


coveralls: 
[![Coverage Status](https://coveralls.io/builds/68498218/badge)](https://coveralls.io/builds/68498218)

coverage: 97.686%. remained the same
when pulling **aafb0bd595b701dff8b4c8ee2b1c37d02160ea80 on howiezhao:patch-1**
into **c8d34f1cb0cb797d497874e9720056784e9070a4 on chimurai:master**.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/68498324/badge)](https://coveralls.io/builds/68498324)

coverage: 97.686%. remained the same
when pulling **830cbce498dd082396f3d7ed55cfe8e47f2e38f1 on howiezhao:patch-1**
into **c8d34f1cb0cb797d497874e9720056784e9070a4 on chimurai:master**.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8588f33..f9a2982 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
 - ci(package): npm package provenance
 - fix(logger-plugin): log target port when router option is used
 - refactor: fix circular dependencies
+- fix(fix-request-body): support '+json' content-type suffix
 
 ## [v3.0.0](https://github.com/chimurai/http-proxy-middleware/releases/tag/v3.0.0)
 
diff --git a/src/handlers/fix-request-body.ts b/src/handlers/fix-request-body.ts
index c8c2aa1..4fe1e45 100644
--- a/src/handlers/fix-request-body.ts
+++ b/src/handlers/fix-request-body.ts
@@ -23,7 +23,7 @@ export function fixRequestBody<TReq = http.IncomingMessage>(
     proxyReq.write(bodyData);
   };
 
-  if (contentType && contentType.includes('application/json')) {
+  if (contentType && (contentType.includes('application/json') || contentType.includes('+json'))) {
     writeBody(JSON.stringify(requestBody));
   }
 


Test patch:
diff --git a/test/unit/fix-request-body.spec.ts b/test/unit/fix-request-body.spec.ts
index fe25431..b176506 100644
--- a/test/unit/fix-request-body.spec.ts
+++ b/test/unit/fix-request-body.spec.ts
@@ -57,6 +57,20 @@ describe('fixRequestBody', () => {
     expect(proxyRequest.write).toHaveBeenCalledWith(expectedBody);
   });
 
+  it('should write when body is not empty and Content-Type ends with +json', () => {
+    const proxyRequest = fakeProxyRequest();
+    proxyRequest.setHeader('content-type', 'application/merge-patch+json; charset=utf-8');
+
+    jest.spyOn(proxyRequest, 'setHeader');
+    jest.spyOn(proxyRequest, 'write');
+
+    fixRequestBody(proxyRequest, createRequestWithBody({ someField: 'some value' }));
+
+    const expectedBody = JSON.stringify({ someField: 'some value' });
+    expect(proxyRequest.setHeader).toHaveBeenCalledWith('Content-Length', expectedBody.length);
+    expect(proxyRequest.write).toHaveBeenCalledWith(expectedBody);
+  });
+
   it('should write when body is not empty and Content-Type is application/x-www-form-urlencoded', () => {
     const proxyRequest = fakeProxyRequest();
     proxyRequest.setHeader('content-type', 'application/x-www-form-urlencoded');