1
Mutant first = request.body();
Mutant second = request.body();

log.info("First: {}, Second: {}", first, 
    Strings.isNullOrEmpty(second.value()) ? "None": second.value()
);

yelds

First: {..my content..}, Second: None

Updated: Jooby library, just for FYI https://jooby.org

Reqeust object used: https://jooby.org/apidocs/org/jooby/request

I looked the de-compiled code and it looks like they do not cache the body property, so if you need to access request.body() from multiple routes, well...

Vera
  • 51
  • 1
  • 6
  • I would imagine not, given that those are usually streams and streams can only be played once. What library are you using to send your requests in the first place? – Makoto May 04 '18 at 19:17
  • Makoto, I do not see how " library are you using to send your requests" is relevant. In my case jooby used for http, so a client could be anything from Chrome & IE to postman and curl – Vera May 04 '18 at 19:22
  • 1
    Vera: The code you've posted doesn't tell us what the type of `request` is, for instance. So we don't know what behavior you'd be right to expect. It would be easy to guess if you were using, e.g., `HttpServletRequest`s, but that class doesn't have the `body()` method. So @Makoto's question is relevant. – ernest_k May 04 '18 at 19:31
  • Oh it is jooby library, https://jooby.org/, this one: https://jooby.org/apidocs/org/jooby/request I will update the original post, if I can – Vera May 04 '18 at 19:39

2 Answers2

2

Yes, this is possible, but requires a work-around.

You can add this use block as the first line in your application. This allows you to access the body multiple times through request.body(). Internally the body will be streamed into memory and offloaded to disk if its too large in all cases, this work-around just makes sure you get the same reference every time.

// Cache body in request scope
use("*", "*", (req, res, chain) -> {
  final Mutant body = req.method().equalsIgnoreCase("post") ? req.body() : null;
  Request.Forwarding wrappedReq = new Request.Forwarding(req) {

    @Override
    public Mutant body() throws Exception {
      if(body != null) {
        return body;
      }
      return super.body();
    }

    @Override
    public <T> T body(Class<T> type) throws Exception {
      return body().to(type);
    }

  };
  chain.next(wrappedReq, res);
});

Any filter or route defined after this block will be able to obtain the request body multiple times. If the body was requested already before this use block, it won't work.

1

Doesn't look like it.

Jooby implements the in parameter (which is what request.body would eventually resolve to) as a InputStream. An InputStream cannot be rewound, and it would not have any context or ability to do so. Therefore, multiple invocations of request.body() would get you the body of your request exactly once.

Makoto
  • 104,088
  • 27
  • 192
  • 230
  • thanks! I was hoping there is a magic flag or configuration setting that I'm missing... – Vera May 04 '18 at 19:43