134

I have a javascript library that is sending a POST request to my Java servlet, but in the doPost method, I can't seem to get the contents of the request payload. In chrome Developer Tools, all the content is in the Request Payload section in the headers tab, and the content is there, and I know that the POST is being received by the doPost method, but it just comes up blank.

For the HttpServletRequest object, what way can I get the data in the request payload?

public class TestFilter implements Filter {

John Little
  • 10,707
  • 19
  • 86
  • 158
Fasih Awan
  • 1,891
  • 4
  • 17
  • 24
  • you need to specify which parameter e.g. if you have keyword in the body use String keyword = request.getParameter("keyword"); – justMe Jan 25 '13 at 16:28
  • It'd be interesting to see the JavaScript code sending the request. It's apparently composing the request parameters in a wrong way. – BalusC Jan 25 '13 at 16:30
  • @Razh well yes I know, I was just specifying which methods I was trying. BalusC I am using the resumable.js library to handle split file uploads – Fasih Awan Jan 25 '13 at 16:33
  • 4
    If I'm not mistaking, it's important that you do NOT use request.getParameter() prior to reading from the input stream otherwise no data will be available (already read). – Jeach Apr 30 '13 at 21:52

9 Answers9

127

Simple answer:
Use getReader() to read the body of the request

More info:
There are two methods for reading the data in the body:

  1. getReader() returns a BufferedReader that will allow you to read the body of the request.

  2. getInputStream() returns a ServletInputStream if you need to read binary data.

Note from the docs: "[Either method] may be called to read the body, not both."

davidfrancis
  • 3,734
  • 2
  • 24
  • 21
  • 4
    No problems, it's a bit hidden that one – davidfrancis Jan 25 '13 at 16:46
  • 30
    This post may be useful if you've just used this in a filter and then discovered nothing else can read the body again! http://natch3z.blogspot.co.uk/2009/01/read-request-body-in-filter.html – JonnyRaa Jul 30 '14 at 10:17
  • 3
    @SgtPooki feel free to add some reasoning for that comment, my good sir! – davidfrancis May 15 '19 at 14:50
  • @davidfrancis I'm not trying to judge you personally here, but: you have provided no context.. no link to documentation, no example. Your reply to my comment seems to have required more effort than the answer itself. – SgtPooki May 15 '19 at 18:52
  • @SgtPooki Correct, as none of those things are needed. IMHO the name of the method needed is somewhat obscure, hence the method name is the answer to this question. Simple as that I thought. Feel free to submit a longer answer if you think it would be useful. – davidfrancis May 15 '19 at 21:07
  • @davidfrancis, you're missing the point. The actual question is "How do I get data from the request". Now try, with your answer as it stands, to get data by writing req.getReader(). Does that give you the data in the request payload, or does it give you the reader, which facilitates getting the body of the request? – SgtPooki May 15 '19 at 21:24
  • @sgtPooki Your answer is more detailed, but it has extraneous detail that may not be useful. Many people using this API will not be interested in reading the body line by line at all, they will be parsing the body using a library e.g. as JSON. IMHO you should really have submitted it as a new answer because it's no longer my text. – davidfrancis May 16 '19 at 22:52
  • Likewise, I hope if your day job you don't overwrite code without discussion first, if you don't like it - even if 93 previous people happened to like it. I read around about the etiquette of editing answers so am fully up to date with the various opinions 8=}. Thanks for your input to the answer. – davidfrancis May 20 '19 at 13:05
85
String payloadRequest = getBody(request);

Using this method

public static String getBody(HttpServletRequest request) throws IOException {

    String body = null;
    StringBuilder stringBuilder = new StringBuilder();
    BufferedReader bufferedReader = null;

    try {
        InputStream inputStream = request.getInputStream();
        if (inputStream != null) {
            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            char[] charBuffer = new char[128];
            int bytesRead = -1;
            while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                stringBuilder.append(charBuffer, 0, bytesRead);
            }
        } else {
            stringBuilder.append("");
        }
    } catch (IOException ex) {
        throw ex;
    } finally {
        if (bufferedReader != null) {
            try {
                bufferedReader.close();
            } catch (IOException ex) {
                throw ex;
            }
        }
    }

    body = stringBuilder.toString();
    return body;
}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • 7
    Take into account that `request.getInputStream()` doesn't honor request character encoding as `request.getReader()` does. So this example uses default system charset. – Vadzim Apr 28 '14 at 16:26
  • 14
    `new BufferedReader(new InputStreamReader(request.getInputStream()))` could be simplified to just `request.getReader()` that is already buffered and also preserves request encoding. – Vadzim Apr 28 '14 at 16:30
  • 3
    I found this solution helpful as an exception was thrown: `javax.servlet.ServletException: java.lang.IllegalStateException: getInputStream() has already been called for this request` when I called getReader() as a result of the reader already being open. – Benjamin Slabbert Jul 27 '17 at 15:38
  • Thanks sir, this is a clean and concise solution! – obayral Jan 12 '21 at 17:49
  • 1
    why do you append empty string to the SB? – Li3ro Jul 09 '21 at 07:11
  • public static String getBody(HttpServletRequest request){ return new String(request.getInputStream().readAllBytes()); } – Ilya Feb 26 '22 at 13:57
  • else {stringBuilder.append("");} is redundant! – Soroush Shemshadi May 05 '22 at 13:02
58

You can use Buffer Reader from request to read

    // Read from request
    StringBuilder buffer = new StringBuilder();
    BufferedReader reader = request.getReader();
    String line;
    while ((line = reader.readLine()) != null) {
        buffer.append(line);
        buffer.append(System.lineSeparator());
    }
    String data = buffer.toString()
scriptfoo
  • 476
  • 5
  • 17
Fizer Khan
  • 88,237
  • 28
  • 143
  • 153
44

Java 8 streams

String body = request.getReader().lines()
    .reduce("", (accumulator, actual) -> accumulator + actual);
bbviana
  • 641
  • 6
  • 4
  • This is interesting, but looks quite inefficient in terms of string concatenation! Any way this can be improved? – davidfrancis Aug 15 '16 at 15:47
  • 13
    String body = request.getReader().lines().collect(Collectors.joining()); may also work. Collectors.joining uses a StringBuilder under the hood apparently. – Oliver Kohll Aug 30 '16 at 16:57
  • 3
    I think it should request.getReader().lines().collect(joining("\n")) to preserve the newlines. – Michael Böckling Feb 08 '17 at 16:17
  • In java 8,stream will be processed parallely so need to add sequential method otherwise it will merge wrong portion of data - String body = request.getReader().lines().sequential().reduce(System.lineSeparator(), (accumulator, actual) -> accumulator + actual) – Jatin Bodarya Mar 01 '18 at 06:10
  • 2
    You can replace `(accumulator, actual) -> accumulator + actual` with `String::concat`. – shmosel Jun 28 '18 at 19:34
37

With Apache Commons IO you can do this in one line.

IOUtils.toString(request.getReader())
Diji Adeyemo
  • 492
  • 4
  • 7
24

If the contents of the body are a string in Java 8 you can do:

String body = request.getReader().lines().collect(Collectors.joining());

twonkeys
  • 552
  • 6
  • 11
Lloyd Rochester
  • 689
  • 8
  • 7
7

If you are able to send the payload in JSON, this is a most convenient way to read the playload:

Example data class:

public class Person {
    String firstName;
    String lastName;
    // Getters and setters ...
}

Example payload (request body):

{ "firstName" : "John", "lastName" : "Doe" }

Code to read payload in servlet (requires com.google.gson.*):

Person person = new Gson().fromJson(request.getReader(), Person.class);

That's all. Nice, easy and clean. Don't forget to set the content-type header to application/json.

Harry Developer
  • 260
  • 1
  • 3
  • 15
  • This worked in my case where I had to implement JWT authentication. I was sending JSON payload with username and password, then mapped that to my custom Auth Token class. – KnockingHeads May 06 '21 at 08:59
2

Using Java 8 try with resources:

    StringBuilder stringBuilder = new StringBuilder();
    try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(request.getInputStream()))) {
        char[] charBuffer = new char[1024];
        int bytesRead;
        while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
            stringBuilder.append(charBuffer, 0, bytesRead);
        }
    }
1

You only need

request.getParameterMap()

for getting the POST and GET - Parameters.

The Method returns a Map<String,String[]>.

You can read the parameters in the Map by

Map<String, String[]> map = request.getParameterMap();
//Reading the Map
//Works for GET && POST Method
for(String paramName:map.keySet()) {
    String[] paramValues = map.get(paramName);

    //Get Values of Param Name
    for(String valueOfParam:paramValues) {
        //Output the Values
        System.out.println("Value of Param with Name "+paramName+": "+valueOfParam);
    }
}
Komal12
  • 3,340
  • 4
  • 16
  • 25
Arol
  • 62
  • 7
  • 5
    Beware: The parameters are only available if you use the encoding `application/x-www-form-urlencoded`; for `multipart/form-data`, you apparently need to access the body part through `request.getReader()` and parse it manually. – twonkeys Oct 25 '17 at 08:48