Как получить org.eclipse.jetty.server.Request из моего сервлета - PullRequest
0 голосов
/ 22 марта 2020

Рассмотрим этот бит кода. Эта работа еще не завершена, но цель - получить доступ к каналу NIO, который я могу использовать для создания полнодуплексного экземпляра RubyIO (org.j ruby .RubyIO), который можно выбрать с помощью селектора NIO.

Но сначала я хочу канал NIO ...

        //  This call returns a `javax.servlet.ServletRequest` but the underlying
        // instance was created by Jetty - it seems to me - and is actually an
        // `org.eclipse.jetty.server.Request`
        ServletRequest srv_req = this.http_servlet_request_wrapper.getRequest();
        Request req;
        ClassLoader cl1 = Request.class.getClassLoader();
        ClassLoader cl2 = srv_req.getClass().getClassLoader();

        System.out.println("DBG: cl1: " + cl1.toString());
        // => DBG: cl1: WebAppClassLoader{66233253}@3f2a3a5

        System.out.println("DBG: cl2: " + cl2.toString());
        // => DBG: cl2: java.net.URLClassLoader@63947c6b

        if (srv_req instanceof Request) {
            System.out.println("DBG: srv_req IS REQUEST");
            req = (Request)srv_req;
            System.out.println("DBG: req class: " + req.getClass().getName());
        } else {
            System.out.println("DBG: srv_req IS NOT REQUEST");
            System.out.println("DBG: srv_req class: " + srv_req.getClass().getName());
            throw new Exception("<expletive deleted>!");
        }

        HttpChannel http_channel = req.getHttpChannel();
        EndPoint end_point = http_channel.getEndPoint();

Что выводится на консоль ...

DBG: cl1: WebAppClassLoader{66233253}@3f2a3a5
DBG: cl2: java.net.URLClassLoader@63947c6b
DBG: srv_req IS NOT REQUEST
DBG: srv_req class: org.eclipse.jetty.server.Request

Наконец, генерируется исключение.

Так что, похоже, instanceof говорит, что srv_req не является экземпляром Reuest, потому что загрузчики классов не совпадают. Класс srv_req равен org.eclipse.jetty.server.Request. Но в сервлете я не могу рассматривать его как таковое и не могу его разыграть.

Я прочитал https://www.eclipse.org/jetty/documentation/current/jetty-classloading.html, но мне все еще не ясно, как получить доступ к srv_req как org.eclipse.jetty.server.Request экземпляр.

Я подозреваю, что я не должен делать это из сервлета, но спрашивать не мешает.

Могу ли я получить доступ к javax.servlet.ServletRequest, возвращенный из моего HttpServletRequestWrapper объекта, как он выглядит, как экземпляр org.eclispe.jetty.server.Request?

В качестве альтернативы, я могу создать полнодуплексный канал NIO из того, к чему я МОГУ получить доступ в сервлете

1 Ответ

0 голосов
/ 22 марта 2020

Во-первых, чтобы получить org.eclipse.jetty.server.Request от javax.servlet.HttpServletRequest, просто используйте ...

Request baseRequest = Request.getBaseRequest(httpServletRequest);

Но это не даст вам слишком далеко.

org.eclipse.jetty.server.HttpChannel и org.eclipse.jetty.io.EndPoint не предоставляют приложениям интерфейсы или поведение NIO.

Это внутренние классы, которые реализуют поведение HTTP spe c через один интерфейс для обработки такие вещи, как ...

  • Кодировки передачи
  • Кодирование
  • Кодировки содержимого
  • Gzip
  • Многочастное кодирование
  • et c ..

И это именно то, что HTTP / 1.1 приносит в таблицу, если вы начинаете использовать HTTP / 2, все становится еще сложнее (с физическим соединением, контролирующим много виртуальных потоки).

Но что, если вы не хотите использовать или заботиться о HTTP?

Вы можете обновить соединение и выйти из-под HTTP, используя свой собственный Connection object.

jettyEndPoint.setConnection(myConnection);
jettyEndPoint.upgrade(myConnection);

Не забудьте реализовать Connection.UpgradeTo, чтобы получить устаревшие (необработанные) байты из p rior connection.

Но это все равно не дает вам NIO, поскольку EndPoint не освобожден от Jetty, и он по-прежнему управляет селектором и ведет протокол низкого уровня. (например, поток из HTTP / 2)

Хорошо, вернемся к HTTP, какие опции у вас остались?

Ничего, что раскрывает или позволяет управлять селектором NIO.

Вы должны были бы подделать селектор для j ruby.

Если вы хотите придерживаться HTTP, то используйте сервлет spe c Asyn c поведения ввода / вывода в качестве вашей стороны Jetty Уровень API.

Если вы не хотите придерживаться HTTP, то обновите соединение с HTTP, просто убедитесь, что вы говорите это в HTTP-разговоре, сначала используя соответствующие заголовки (например: Connection: upgrade) .

...