Search code examples
javaspringspring-bootjackson-databind

Remove Json Prefix in Response from particular API Spring boot


I have Java Spring-boot project that basically have all APIs to perform business logic and send data to UI. We have used MappingJackson2HttpMessageConverter -> JsonPrefix to attach some prefix to make JSON invalid as per the VAPT findings to resolve application vulnerability. Code for the same is as below

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setJsonPrefix(")]}',\n");
        converters.add(new StringHttpMessageConverter());
        converters.add(converter);   
    }
}

This works corrects and provides response as expected. attaching one sample response

)
]
}',
{"error":null,"status":200,"message":"Success","body:{"id":null,"is_api_available":false}}

Now the problem is there is some requirement where in particular 2-3 APIs, I dont want this prefix to come. So is there any way to achieve the same?

I Tried looking into the MappingJackson2HttpMessageConverter methods if there is any way, but I didnt found any. Also i tried to print value of List<HttpMessageConverter<?>> converters so if i can get any particular info, so i can keep any condition, but nothing worked.

Update:

As suggested by @being_ethereal, it worked. just a small difference of method parameter changes due to change in versions.

In my case writePrefix method was overriden in below way.

@Override
protected void writePrefix(JsonGenerator generator, Object object) throws IOException {
    if (!excludedApis.contains(request.getRequestURI())) {
        generator.writeRaw(")]}',\n");
    }
}

Solution

  • You could implement a custom converter which takes a request object & maintain list of requestUris, where you don't want to include the prefix

    public class CustomRespConverter extends MappingJackson2HttpMessageConverter {
    
        private final HttpServletRequest request;
        private final List<String> excludedApis = List.of("/api/excluded1", "/api/excluded2");
    
        public CustomRespConverter(ObjectMapper objectMapper, HttpServletRequest request) {
            super(objectMapper);
            this.request = request;
        }
    
        @Override
        protected void writePrefix(HttpOutputMessage outputMessage) throws IOException {
            if (!excludedApis.contains(request.getRequestURI())) {
                StreamUtils.copy(")]}',\n".getBytes(StandardCharsets.UTF_8), outputMessage.getBody());
            }
        }
    }
    

    You can also make this class as a @Component & import the list of excluded APIs from the properties. After this, add & pass the HttpServletRequest request object from WebConfig config class:

        private final HttpServletRequest request;
    
        public WebConfig(HttpServletRequest request) {
            this.request = request;
        }
    
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            ObjectMapper objectMapper = new ObjectMapper();
            converters.add(new CustomRespConverter(objectMapper, request));
        }
    

    Try this method & let me know if it works or not! I tried similar method for another use-case & my code is working for almost 5 years.