Search code examples
web-servicescharacter-encodingcontent-type

Content-type header in response is getting appended by charset=ISO-8859-1


I have a web service that produces MediaType.APPLICATION_XML_VALUE

In rest client, I see content-type header as application/xml;charset=ISO-8859-1

Caller has set Accept header as application/xml

Not sure what is adding charset=ISO-8859-1 in the header.

To remove charset from content-type header,

  • Tried with mentioning application/xml instead of MediaType.APPLICATION_XML_VALUE
  • Tried adding spring filter CharacterEncodingFilter
  • Tried adding spring.http.encoding.force=false in application.properties file

None of the above made any difference.

Caller


    curl -v -X POST \
      https://<URL> \
      -H 'Content-Type: application/x-www-form-urlencoded' \
      -H 'accept: application/xml' 

Java Resource


    @RequestMapping(value = "<URL>",
                    method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
                    produces = MediaType.APPLICATION_XML_VALUE)
    @ResponseBody
    public String processRequest(HttpServletRequest request) {
        try {
            Object response = service(request);
            if (response != null) {
                return response.toString();
            }
        } catch (Exception e) {
            logger.error(e);
        }
        return createErrorResponse(ERR_CODE).toString();
    }

// response header
200 OK
Time:1247 ms
Size:1.62 KB
Save
Download
Date →Wed, 17 Jul 2019 07:30:28 GMT
Server →Apache
Strict-Transport-Security →max-age=31536000; includeSubDomains
Content-Type →application/xml;charset=ISO-8859-1
Content-Length →1374
Via →1.1 <URL>
Keep-Alive →timeout=5, max=10000
Connection →Keep-Alive

This was working fine. Started seeing above behavior post upgrading following libraries


    jackson 2.6.0 to 2.6.3
    httpclient 4.5 to 4.5.3
    httpcomponents 4.4.1 to 4.4.6
    springframework 4.2.9 to 4.3.17

Need to know a way how to omit charset from header and what is adding it in the first place.


Solution

  • Found the issues.

    @ResponseBody annotation was converting String output to HTTP supported format.

    Internally, it would append charset=ISO-8859-1 to the content-type header if not specified.

    As I wanted to remove this, changed method return from String to ResponseEntity<String> ResponseEntity will take care of converting output to HTTP supported format and not the annotation. So control on converting to HTTP is now in code rather than letting spring do it. Here we can explicitly set headers that we want.

    New code looks something like this :

    @RequestMapping(value = "<URL>",method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,produces = MediaType.APPLICATION_XML_VALUE)
    public ResponseEntity<String> processRequest(HttpServletRequest request) {
        try {
            Object response = service(request);
            if (response != null) {
                prepareResponseEntity(response.toString());
            }
        } catch (Exception e) {
            logger.error(e);
        }
        return prepareResponseEntity(createErrorResponse(ERR_CODE).toString());
    }
    
    private static ResponseEntity<String> prepareResponseEntity (String responseBody){
        HttpHeaders responseHeaders = new HttpHeaders();
        responseHeaders.add(HeartBeatServerConstants.HEADER_CONTENT_TYPE,MediaType.APPLICATION_XML_VALUE);
        return new ResponseEntity<String>(responseBody,responseHeaders,HttpStatus.OK);  
    }
    

    Update : AbstractHttpMessageConverter of spring-web has changed between spring 4.2.9 and 4.3.17 to add charset if not present.Spring Doc