0

I am using Spring's AbstractHttpMessageConverter to allow me instantiate my own object.

Converter

    public class PaypalIPNHttpMessageConverter extends AbstractHttpMessageConverter<IPNMessage> {

    public PaypalIPNHttpMessageConverter() {
        super(MediaType.APPLICATION_FORM_URLENCODED, MediaType.TEXT_PLAIN);
    }

    @Override
    protected boolean supports(Class<?> clazz) {
        return clazz == IPNMessage.class;
    }

    @Override
    protected IPNMessage readInternal(Class<? extends IPNMessage> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
        //Converts HTTPRequest into map<string,string> that IPNMessage can then parse
        String requestString = IOUtils.toString(inputMessage.getBody(), "UTF-8");
        Map<String, String[]> requestMap = new LinkedHashMap<>();
        for (String keyValue : requestString.split("&")) { //each key value is delimited by &
            String[] pairs = keyValue.split("=", 2); // = pairs a key to a value
            requestMap.put(pairs[0], pairs[1].split(",")); // , splits multiple values for that key
        }
        return new IPNMessage(requestMap);
    }

    @Override
    protected void writeInternal(IPNMessage ipnMessage, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {

    }
}

In readINternal(), I am passed a HttpInputMessage object, which only has getBody() function that produces an InputStream of the HTTPRequest.

I have tried to write my own code to parse and build a ParameterMap but it does not always work if the urlencoding is different.

Is there anyway I can get Spring's WebRequest or HttpServletRequest object from the converter and use there wonderful getParameterMap() function?

TL;DR

Is there anyway to use WebRequest or HTTPServletRequest in the MessageConverter instead of HttpInput so I can use the wonderful getParameterMap() function, instead of reinventing the wheel?

Thanks

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
tomaytotomato
  • 3,788
  • 16
  • 64
  • 119
  • You can usually just autowire HttpServletRequest to spring managed beans (e.g. just add this as a field: `@Autowired HttpServletRequest request;` ). Be aware that Spring framework did not intend you to access url parameters in message converters. There might be better places to plug in your functionality (conversion service? argument resolvers?) – Krešimir Nesek Apr 12 '16 at 10:01

2 Answers2

2

Look at how it is implemented in Spring FormHttpMessageConverter. It tokenizes request parameter using & just like your solution. However it dtermines the charset to use from the Content-Type request header if provided. Otherwise it uses default UTF-8

//extract from FormHttpMessageConverter
public MultiValueMap<String, String> read(Class<? extends MultiValueMap<String, ?>> clazz,
            HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {

        MediaType contentType = inputMessage.getHeaders().getContentType();
        Charset charset = (contentType.getCharSet() != null ? contentType.getCharSet() : this.charset);
        String body = StreamUtils.copyToString(inputMessage.getBody(), charset);

        String[] pairs = StringUtils.tokenizeToStringArray(body, "&");
        MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>(pairs.length);
        for (String pair : pairs) {
            int idx = pair.indexOf('=');
            if (idx == -1) {
                result.add(URLDecoder.decode(pair, charset.name()), null);
            }
            else {
                String name = URLDecoder.decode(pair.substring(0, idx), charset.name());
                String value = URLDecoder.decode(pair.substring(idx + 1), charset.name());
                result.add(name, value);
            }
        }
        return result;
    }
ekem chitsiga
  • 5,523
  • 2
  • 17
  • 18
0

You can simply get the current request using the following code

HttpServletRequest httpRequest = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
Kamiel Ahmadpour
  • 1,215
  • 12
  • 16