Request has already been read

3,029 views
Skip to first unread message

Cristiano Martini Bergamo

unread,
Nov 12, 2015, 1:31:16 PM11/12/15
to vert.x
Everytime I try to reroute some request show me the message:

Unexpected exception in route 
java.lang.IllegalStateException: Request has already been read
at io.vertx.core.http.impl.HttpServerRequestImpl.checkEnded(HttpServerRequestImpl.java:414)
at io.vertx.core.http.impl.HttpServerRequestImpl.handler(HttpServerRequestImpl.java:199)
at io.vertx.core.http.impl.HttpServerRequestImpl.bodyHandler(HttpServerRequestImpl.java:275)
at io.vertx.ext.web.impl.HttpServerRequestWrapper.bodyHandler(HttpServerRequestWrapper.java:136) ...

Follow some part of my code that trigger this error.


router.route("/login.do").handler(_event -> {



_event.request().bodyHandler(_req -> {
JsonObject job = new JsonObject();

String params[] = _req.toString().split("&");

for (String param : params) {
String keyValue[] = param.split("=");

if (keyValue[0].equals("usuario")) {
job.put("usuario", keyValue[1]);
} else if (keyValue[0].equals("senha")) {
job.put("senha", keyValue[1]);
}
}

eb.send("erp.autenticarcao", job, _resposta -> {

if (_resposta.succeeded()) {
_event.setUser((User) _resposta.result().body());
_event.next();
} else {
System.err.println(_resposta.cause());
_event.reroute("/dynamic/pageLogin.templ");
}

});
});

});



I already try to  use BodyHandler and same error occurs. If just try to reroute the same error happens too. Someone knows what is the problem?

--- Other informations ---
Vert.x version 3.1.0
Java 8
---

Michel Guillet

unread,
Nov 13, 2015, 3:33:17 AM11/13/15
to ve...@googlegroups.com
This can happens if your request has already been rerouted once. Is this the only route matching? Maybe you also read the body before: you cannot read it twice. 

You should really add a BodyHandler to your route rather than registering your own body handler. Then you'll have access directly to the body through the request. 

Cheers.

Michel
--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
Visit this group at http://groups.google.com/group/vertx.
To view this discussion on the web, visit https://groups.google.com/d/msgid/vertx/fd2969e9-25d7-46ab-a205-2570a4a31c9c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Cristiano Martini Bergamo

unread,
Nov 13, 2015, 6:01:21 AM11/13/15
to vert.x
Thanks, Michel, for the reply but, the I already try BodyHandler and I change to see if the problem was with it.
This post has the last try that I made trying to gettin things work

All routes that I have are:
router.route("/")... (for the index page)
router.route("/static/*")... (for the static content)
router.route("/dynamic/*")... (for dynamic content)
router.route("/login.do")... (and this to the route when happens the error. I posted before)

No other routes are available yet, its a project that I start to make to learn about Vert.x.

Any other idea?

Michel Guillet

unread,
Nov 13, 2015, 6:20:43 AM11/13/15
to ve...@googlegroups.com
With just (redacted) code snippets I won’t be able to tell much… You may be omitting something relevant to the issue here.

If you can make the project available on Github I might be able to help, otherwise this will be very difficult for me.

Cheers,

Michel

Cristiano Martini Bergamo

unread,
Nov 13, 2015, 9:37:21 AM11/13/15
to vert.x
I put the source code in https://github.com/cmbergamo/test-vertx

Thx,

Cristiano

Michel Guillet

unread,
Nov 13, 2015, 9:58:40 AM11/13/15
to ve...@googlegroups.com
Ok, I think I got it:

http://vertx.io/docs/apidocs/io/vertx/ext/web/RoutingContext.html#reroute-java.lang.String-
> RoutingContext.reroute
> Restarts the current router with a new path and reusing the original method. All path parameters are then parsed and available on the params list.

This means that your router will go through the body handler, then to your "/login.do” route. At this point your handler reroute it to "/dynamic/pageLogin.templ”: it then restart and go through the body handler and boom!

You need to setup body handler carefully so that you don’t end up with requests being read twice. Or in your case issue a 3xx HTTP redirection for a successful authorisation, that’s usually how it’s done for a login.

Cheers,

Michel
> To view this discussion on the web, visit https://groups.google.com/d/msgid/vertx/5e934d0a-16bc-4729-86c5-80e6170103df%40googlegroups.com.

Cristiano Martini Bergamo

unread,
Nov 13, 2015, 10:51:52 AM11/13/15
to vert.x
I made the changes that you told me, but the problem persists.

I already refresh the github with your suggestions.

Michel Guillet

unread,
Nov 13, 2015, 12:16:49 PM11/13/15
to ve...@googlegroups.com
Ok I think there is a bug with the reroute method. 

Try to get rid of it with a basic http redirection. That what you should do anyway during a login phase (otherwise your browser will show a login.do page with completely unrelated content)

These basics examples are not working, and you end up with a stack overflow exception. I created a bug here: https://github.com/vert-x3/vertx-web/issues/252

BTW, someone logged a bug on the previous issue you had : https://github.com/vert-x3/vertx-web/issues/243

Michel


mathias

unread,
Nov 21, 2015, 9:12:39 AM11/21/15
to vert.x
Here is my stacktrace:
SCHWERWIEGEND: Unexpected exception in route
java
.lang.IllegalStateException: Request has already been read
    at io
.vertx.core.http.impl.HttpServerRequestImpl.checkEnded(HttpServerRequestImpl.java:426)
    at io
.vertx.core.http.impl.HttpServerRequestImpl.setExpectMultipart(HttpServerRequestImpl.java:322)
    at io
.vertx.ext.web.impl.HttpServerRequestWrapper.setExpectMultipart(HttpServerRequestWrapper.java:146)
    at io
.vertx.ext.web.handler.impl.BodyHandlerImpl$BHandler.<init>(BodyHandlerImpl.java:86)
    at io
.vertx.ext.web.handler.impl.BodyHandlerImpl.handle(BodyHandlerImpl.java:50)
    at io
.vertx.ext.web.handler.impl.BodyHandlerImpl.handle(BodyHandlerImpl.java:37)
    at io
.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:220)
    at io
.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:78)
    at io
.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:93)
    at io
.vertx.ext.web.handler.impl.UserSessionHandlerImpl.handle(UserSessionHandlerImpl.java:63)
    at io
.vertx.ext.web.handler.impl.UserSessionHandlerImpl.handle(UserSessionHandlerImpl.java:29)
    at io
.vertx.ext.web.impl.RouteImpl.handleContext(RouteImpl.java:220)
    at io
.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:78)
    at io
.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:93)
    at io
.vertx.ext.web.handler.impl.SessionHandlerImpl.lambda$handle$156(SessionHandlerImpl.java:117)
    at io
.vertx.ext.web.handler.impl.SessionHandlerImpl$$Lambda$135/1023898452.handle(Unknown Source)
    at io
.vertx.ext.web.handler.impl.SessionHandlerImpl.lambda$doGetSession$158(SessionHandlerImpl.java:142)
    at io
.vertx.ext.web.handler.impl.SessionHandlerImpl$$Lambda$136/969740892.handle(Unknown Source)
    at io
.vertx.ext.web.sstore.impl.LocalSessionStoreImpl.get(LocalSessionStoreImpl.java:55)
    at io
.vertx.ext.web.handler.impl.SessionHandlerImpl.doGetSession(SessionHandlerImpl.java:130)
    at io
.vertx.ext.web.handler.impl.SessionHandlerImpl.lambda$null$157(SessionHandlerImpl.java:137)
    at io
.vertx.ext.web.handler.impl.SessionHandlerImpl$$Lambda$137/442015822.handle(Unknown Source)
    at io
.vertx.core.impl.VertxImpl$InternalTimerHandler.handle(VertxImpl.java:732)
    at io
.vertx.core.impl.VertxImpl$InternalTimerHandler.handle(VertxImpl.java:703)
    at io
.vertx.core.impl.ContextImpl.lambda$wrapTask$3(ContextImpl.java:335)
    at io
.vertx.core.impl.ContextImpl$$Lambda$13/134138801.run(Unknown Source)
    at io
.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:358)
    at io
.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
    at io
.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
    at java
.lang.Thread.run(Thread.java:745)

This exception never happened before. I don't know what causes this exception to occur suddenly.

mathias

unread,
Nov 21, 2015, 9:15:24 AM11/21/15
to vert.x
I can't reproduce this exception which occurs during the login. The application hasn't been redeployed since than.

Cristiano Martini Bergamo

unread,
Nov 21, 2015, 7:54:30 PM11/21/15
to vert.x
What happens Mathias? You sent a stacktrace and now you can't reproduce? Is it right?

mathias

unread,
Nov 22, 2015, 4:30:31 AM11/22/15
to vert.x
Exactly. The issue occurs every once in a while in my case. I haven't found a way to reproduce it yet. In case of any progress I will keep you up to date.

mathias

unread,
Nov 22, 2015, 10:57:25 AM11/22/15
to vert.x
I solved my issue by moving the BodyHandler further up in the sequence of handlers.

I changed from
CookieHandlerSessionHandler, UserSessionHandler, RedirectAuthHandler, StaticHandler, BodyHandler, LoginHandler, LogoutHandler
to this:
CookieHandler, BodyHandler, SessionHandler, UserSessionHandler, RedirectAuthHandler, StaticHandler, LoginHandler, LogoutHandler

The key to success was the following example: https://github.com/vert-x3/vertx-examples/blob/master/web-examples/src/main/java/io/vertx/example/web/auth/Server.java

Paulo Lopes

unread,
Nov 23, 2015, 4:52:29 AM11/23/15
to vert.x
I've created a fix for this: see: https://github.com/vert-x3/vertx-web/issues/265

J0t1

unread,
Jan 6, 2016, 2:02:35 PM1/6/16
to vert.x
Hi Paulo,

I am trying to forward request from one handler to another and facing same issue when using reroute. I get error "Request has already been read". I am using vertx version 3.2.0, can you please tell me in which version this fix is available.

Thanks in advance

Paulo Lopes

unread,
Jan 7, 2016, 3:51:15 AM1/7/16
to vert.x
This is in 3.2, can you share the code you're trying to use so I can investigate the issue?

Ihor Zadyra

unread,
Oct 27, 2016, 12:22:49 PM10/27/16
to vert.x

















воскресенье, 22 ноября 2015 г., 17:57:25 UTC+2 пользователь mathias написал: 

Paulo Lopes

unread,
Oct 28, 2016, 4:08:48 AM10/28/16
to vert.x
That is almost definitely because your initBasicAuthProvider will perform some async task and therefore not instruct the httpserver that is should process the body so the body handler can properly take care of it. As it stated on the documentation:

http://vertx.io/docs/vertx-web/java/#_request_body_handling

"The usage of this handler requires that it is installed as soon as possible in the router since it needs to install handlers to consume the HTTP request body and this must be done before executing any async call."

Adam Medeiros

unread,
Jul 27, 2018, 7:29:02 PM7/27/18
to vert.x
I'm running into this also and I have followed every suggestion I could find but nothing seems to work for the following code. The "c.next()" line fails. I think I've moved that bodyhandler up as far as I possibly can. Is there a line of code I'm leaving out? (I left the two Procs out since they aren't even being reached - I think)

SEVERE: Unexpected exception in route

java.lang.IllegalStateException: Request has already been read


server  = $vertx.create_http_server()
router = VertxWeb::Router.router($vertx)

router.post("/ldclive/video_chunk")
.handler(&VertxWeb::BodyHandler.create().method(:handle))
.handler() {|c|
c.request().set_expect_multipart(true)
c.next
}.blocking_handler(chunk_proc, false)
.handler() {|c|
c.response.put_header('content-type', 'application/json').end({msg: 'Received'}.to_json)
}

router.post("/ldclive/video_chunk/finish")
.handler(&VertxWeb::BodyHandler.create().method(:handle))
.blocking_handler(finish_proc, false)
.handler() {|c|
c.response.put_header('content-type', 'application/json').end({msg: 'Received'}.to_json)
}

server.request_handler(&router.method(:accept)).listen(8080)

Vincent Olivier

unread,
Sep 13, 2018, 8:53:20 PM9/13/18
to vert.x
This is undoubtably still a problem. I do not want to use a BodyHandler because I need to report on upload progress via WebSocket. Sometimes request.isEnded() is true even before you get a chance to call request.toFlowable() and even then, context.getBody() returns null.

It seems to me that this is a bug and unless someone comes up with a solution here, I might file a bug report depending if my über-ugly (read: blocking) workarounds actually prevent the problem from popping up.

Thanks.

Bob Namestka

unread,
Oct 30, 2018, 5:37:08 PM10/30/18
to vert.x
I, too, am getting the dreaded:

Unexpected exception in route
java.lang.IllegalStateException: Request has already been read

I've been away from vert.x for a while (pre 2.X) when life was simple.  I'm NOT and expert.  Currently using Java 8 with Vert.x 3.5.4 with the following code:

public class TwilioServer extends AbstractVerticle {

final DeliveryOptions deliveryOptions = new DeliveryOptions().setSendTimeout(30000);

@Override
public void start(Future<Void> future) {

Router router = Router.router(vertx);
router.route().handler(BodyHandler.create());

// Bind "/" to our hello message.
router.route("/").handler(routingContext -> {
HttpServerResponse response = routingContext.response();
response.putHeader("content-type", "text/html").end("<h1>Hello from Twilio Server v0.1</h1>");
});

router.postWithRegex("/sms").produces("application/xml").handler(routingContext -> {
routingContext.request().setExpectMultipart(true);
routingContext.next();
}).blockingHandler(this::twilioPost);

vertx.createHttpServer().requestHandler(router::accept).listen(
// Retrieve the port from the configuration, default to 4567
config().getInteger("http.port", 4567), result -> {
if (result.succeeded()) {
future.complete();
} else {
future.fail(result.cause());
}
});
}

private void twilioPost(RoutingContext routingContext) {
final HttpServerResponse response = routingContext.response();
response.putHeader("Access-Control-Allow-Origin", "*");
System.out.println("************* request params from Twilio ********************");
System.out.println(routingContext.request().params().toString());
System.out.println("************* request form attrs from Twilio ********************");
System.out.println(routingContext.request().formAttributes().toString());
System.out.println("*******************************************************");
final JsonObject twilioPostBody = routingContext.getBodyAsJson();
System.out.println("************* request body from Twilio ********************");
System.out.println(twilioPostBody.toString());
System.out.println("*******************************************************");
final String fromPhoneNumber = twilioPostBody.getString("From");
final String textMsg = twilioPostBody.getString("Body");
System.out.println("************* request from ********************");
System.out.println(fromPhoneNumber);
System.out.println("*******************************************************");

Body body = new Body.Builder("Recv'd msg>" + textMsg).build();
Message sms = new Message.Builder().body(body).build();
MessagingResponse twiml = new MessagingResponse.Builder().message(sms).build();
response.setStatusCode(200).end(twiml.toXml());
}
}

Help is MOST appreciated.

Bob Namestka

unread,
Oct 31, 2018, 11:39:59 AM10/31/18
to vert.x
The error occurs during the call to register the post to the router.

router.postWithRegex("/sms").produces("application/xml").handler(routingContext -> {
routingContext.request().setExpectMultipart(true);
routingContext.next();
}).blockingHandler(this::twilioPost);

at the routingContext.request().setExpectMultipart(true);  call.

router.route().handler(BodyHandler.create());

is called immediately after the router is established as per previous suggestions.

As I said, I'm not a Vert.x expert and admit I might be making a newbie error in the code.  As always, help is MOST appreciated.

Adam Medeiros

unread,
Oct 31, 2018, 1:52:21 PM10/31/18
to vert.x
Try moving the setExpectMultipart(true) far up the router chain. I'm a Ruby-ist so please adjust your Java accordingly....


# require 'this'
# require 'that'

is_prod = (ENV['ENVIRONMENT'] == 'production')
class_loader = java.lang.Thread.currentThread().getContextClassLoader()

# .... some db stuff

db_yml = (!is_prod ? class_loader.get_resource('database.yml').get_path : nil)
establish_db_connection(db_yml)

done_handler = Proc.new {|c|
  c.response.put_header('content-type', 'application/json').end({msg: 'Received'}.to_json)
}

options = { logActivity: true }
port = 8080

if is_prod

  # .... some SSL stuff
key_file = class_loader.get_resource 'ssl/my-key.pem'
crt_file = class_loader.get_resource 'ssl/my-cert.pem'
key = File.read key_file.get_path
crt = File.read crt_file.get_path

prod_options = {
'ssl' => true,
# 'useAlpn' => true,
'pemKeyCertOptions' => {
'keyValue' => Base64.strict_encode64(key),
'certValue' => Base64.strict_encode64(crt)
}
}

options.merge! prod_options
port = 443
end

server = $vertx.create_http_server(options)
router = VertxWeb::Router.router($vertx)

router.route().failure_handler() do |c|
# If -1, it means that the connection was dropped
# by the client. Safe to ignore.
if c.status_code != -1
c.response.set_status_code(c.status_code).end("Error: #{c.get('message')}")
end
end

# NOTICE HOW HIGH UP THIS IS!!! WAY UP TOP...
router.route().handler() do |c|
c.request().set_expect_multipart(true)
c.next
end

# THESE ALSO NEED TO BE WAYYY UP TOP...
router.route().handler(&VertxWeb::LoggerHandler.create().method(:handle))
router.route().handler(&VertxWeb::BodyHandler.create().method(:handle))

router.route("/my/path1").blocking_handler(&My::ChunkUtil.handle()).handler(&done_handler)
router.route("/my/path2/finish").blocking_handler(&My::TranscodeUtil.handle()).handler(&done_handler)
router.route("/ping").handler(&done_handler)

# CORS
#
allowedHeaders = Set.new
%w(Access-Control-Allow-Origin Access-Control-Allow-Method Access-Control-Allow-Credentials Content-Type).each { |h|
allowedHeaders.add? h
}

cors_origin = (is_prod ? ".*example\\.com" : ".*localhost:.*")

router.route().handler(&VertxWeb::CorsHandler.create(cors_origin)
.allowed_headers(allowedHeaders)
.allow_credentials(true)
.allowed_method(:GET)
.allowed_method(:POST)
.allowed_method(:OPTIONS)
.method(:handle)
)

eb_opts = {
'outboundPermitteds' => [
{'address' => 'video-upload-feed'}
]
}

router.route("/eventbus/*").handler(&VertxWeb::SockJSHandler.create($vertx).bridge(eb_opts).method(:handle))

server.request_handler(&router.method(:accept))
server.listen(port)
puts "Listening."

Bob Namestka

unread,
Oct 31, 2018, 2:59:28 PM10/31/18
to vert.x
Thanks Adam!  That did it.  MUCH appreciated.

BobN

Adam Medeiros

unread,
Oct 31, 2018, 3:41:52 PM10/31/18
to ve...@googlegroups.com
Great Bob. I think what's happening there is you are now setting that flag (expect multipart to true) early - BEFORE any requests are read vs. after requests have been read and now in the response delivery phase which is what the response handlers are for. That is my guess. I'll need to dig into Vertx source to see if that understanding is correct - maybe someone will explain it before me. 

At any rate, to anyone who sees this issue in their project in the future, try locating the setting of "Expect Multipart" up in your route declarations. It worked for me and Bob.

On Wed, Oct 31, 2018 at 11:59 AM Bob Namestka <robert....@gmail.com> wrote:
Thanks Adam!  That did it.  MUCH appreciated.

BobN

--
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.


--
A.R. Medeiros

Julien Viet

unread,
Nov 1, 2018, 2:48:23 PM11/1/18
to ve...@googlegroups.com
Hi,

can you elaborate what is happening so we do have a better understanding of this issue ?

thanks

Julien

Adam Medeiros

unread,
Nov 1, 2018, 5:19:55 PM11/1/18
to ve...@googlegroups.com
Sure, Julien. I may be able to find some time tonight to type something up to show you how this error is triggered and then how it's fixed.


For more options, visit https://groups.google.com/d/optout.


--
A.R. Medeiros
Reply all
Reply to author
Forward
0 new messages