Skip to content

Commit

Permalink
fix(rest-api) improve error handling for 415 unsupported media type #…
Browse files Browse the repository at this point in the history
…30828 (#30910)

### Proposed Changes
* Added `NotSupportedExceptionMapper` to handle
`javax.ws.rs.NotSupportedException` and return JSON responses for `415
Unsupported Media Type` errors.
* Included new test cases in the Postman collection to validate proper
handling and responses for requests with invalid `Content-Type` headers.

### Checklist
- [x] Tests
- [x] Translations
- [x] Security Implications Contemplated (add notes if applicable)

### Additional Info
This PR addresses the issue where REST endpoints annotated with
`@Consumes(multipart/form-data)` would return HTML responses instead of
JSON when the `Content-Type` header is incorrect. The new implementation
ensures consistency and better user experience by providing meaningful
JSON error messages across the application.

### Screenshots
Original             |  Updated
:-------------------------:|:-------------------------:
<img width="1017" alt="image"
src="https://github.com/user-attachments/assets/a20e9cc5-3887-444c-8ed4-257c1cb60ecc">
| <img width="961" alt="image"
src="https://github.com/user-attachments/assets/768f6e72-9160-436e-8a6b-e39972b11260">
  • Loading branch information
valentinogiardino authored Dec 10, 2024
1 parent 2e4664f commit d67b5fd
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.dotcms.rest.exception.mapper;

import com.dotmarketing.util.Logger;

import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

/**
* Exception mapper for handling NotSupportedException.
* <p>
* This class maps the javax.ws.rs.NotSupportedException to a proper HTTP response.
* It logs the warning and returns a response with a status of UNSUPPORTED_MEDIA_TYPE.
* </p>
*/
@Provider
public class NotSupportedExceptionMapper implements ExceptionMapper<javax.ws.rs.NotSupportedException> {

/**
* Converts a NotSupportedException into an HTTP response.
*
* @param exception The NotSupportedException that was thrown.
* @return A Response object containing the error message and a status of UNSUPPORTED_MEDIA_TYPE.
*/
@Override
public Response toResponse(javax.ws.rs.NotSupportedException exception) {

Logger.warn(this.getClass(), exception.getMessage(), exception);
return ExceptionMapperUtil.createResponse(ExceptionMapperUtil.getJsonErrorAsString(exception.getMessage()),
exception.getMessage(), Response.Status.UNSUPPORTED_MEDIA_TYPE);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"info": {
"_postman_id": "1d5dd0a7-7d6b-4d1a-9096-47ced212ac23",
"_postman_id": "13ba66c7-fa5d-4baf-882a-71de5536689d",
"name": "ContentImportResource",
"description": "Postman collection for testing the ContentImportResource API endpoints.",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
Expand Down Expand Up @@ -946,6 +946,76 @@
"description": "Creates a new job in the specified queue."
},
"response": []
},
{
"name": "Validate Content Import With Unsupported Media Type Expect Failure Copy",
"event": [
{
"listen": "test",
"script": {
"exec": [
"// Validate the response status is 415",
"pm.test(\"Response status is 415\", function () {",
" pm.response.to.have.status(415);",
"});",
"",
"// Validate that the response body contains the 'message' property and it is not empty",
"pm.test(\"Response should have an error message\", function () {",
" const responseBody = pm.response.json();",
" pm.expect(responseBody).to.have.property('message').that.is.not.empty;",
" pm.expect(responseBody.message).to.equal('HTTP 415 Unsupported Media Type');",
"});",
""
],
"type": "text/javascript",
"packages": {}
}
}
],
"protocolProfileBehavior": {
"disabledSystemHeaders": {
"content-type": true
}
},
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"type": "file",
"src": "resources/ContentImportResource/test-import-content-job-final.csv"
},
{
"key": "form",
"value": "{\"contentType\":\"{{contentType}}\",\"language\":\"{{language}}\",\"workflowActionId\":\"{{workflowActionId}}\", \"fields\": {{fields}}}",
"type": "text"
}
]
},
"url": {
"raw": "{{serverURL}}/api/v1/content/_import/_validate",
"host": [
"{{serverURL}}"
],
"path": [
"api",
"v1",
"content",
"_import",
"_validate"
]
},
"description": "Creates a new job in the specified queue."
},
"response": []
}
]
},
Expand Down Expand Up @@ -1820,6 +1890,75 @@
"description": "Creates a new job in the specified queue."
},
"response": []
},
{
"name": "Create Import Content Job With Unsupported Media Type Expect Failure",
"event": [
{
"listen": "test",
"script": {
"exec": [
"// Validate the response status is 415",
"pm.test(\"Response status is 415\", function () {",
" pm.response.to.have.status(415);",
"});",
"",
"// Validate that the response body contains the 'message' property and it is not empty",
"pm.test(\"Response should have an error message\", function () {",
" const responseBody = pm.response.json();",
" pm.expect(responseBody).to.have.property('message').that.is.not.empty;",
" pm.expect(responseBody.message).to.equal('HTTP 415 Unsupported Media Type');",
"});",
""
],
"type": "text/javascript",
"packages": {}
}
}
],
"protocolProfileBehavior": {
"disabledSystemHeaders": {
"content-type": true
}
},
"request": {
"method": "POST",
"header": [
{
"key": "Content-Type",
"value": "application/json"
}
],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "file",
"type": "file",
"src": "resources/ContentImportResource/test-import-content-job-final.csv"
},
{
"key": "form",
"value": "{\"contentType\":\"{{contentType}}\",\"language\":\"{{language}}\",\"workflowActionId\":\"{{workflowActionId}}\", \"fields\": {{fields}}}",
"type": "text"
}
]
},
"url": {
"raw": "{{serverURL}}/api/v1/content/_import",
"host": [
"{{serverURL}}"
],
"path": [
"api",
"v1",
"content",
"_import"
]
},
"description": "Creates a new job in the specified queue."
},
"response": []
}
]
},
Expand Down

0 comments on commit d67b5fd

Please sign in to comment.