Подтвердить что ты не робот

Получить полный URL и строку запроса в Servlet для HTTP и HTTPS-запросов

Я пишу код, задачей которого является получение запрошенного URL-адреса или полного пути. Я написал этот код:

HttpServletRequest request;//obtained from other functions
String uri = request.getRequestURI();
if (request.getQueryString() != null)
    uri += "?" + request.getQueryString();

Итак, когда я просматриваю http://google.com?q=abc, это нормально (правильно). Но есть проблема, когда я просматриваю https://google.com. Значение uri равно http://google.com:443google.com:443, поэтому программа используется не только при использовании HTTPS.

И результат будет таким же для request.getRequestURL().toString().

Какое решение?

4b9b3361

Ответ 1

По дизайну getRequestURL() вы получаете полный URL-адрес, не содержащий только строку запроса.

В HttpServletRequest вы можете получить отдельные части URI, используя следующие методы:

// Example: http://myhost:8080/people?lastname=Fox&age=30

String uri = request.getScheme() + "://" +   // "http" + "://
             request.getServerName() +       // "myhost"
             ":" +                           // ":"
             request.getServerPort() +       // "8080"
             request.getRequestURI() +       // "/people"
             "?" +                           // "?"
             request.getQueryString();       // "lastname=Fox&age=30"
  • .getScheme() даст вам "https", если это был запрос https://domain.
  • .getServerName() дает domain на http(s)://domain.
  • .getServerPort() предоставит вам порт.

Используйте фрагмент ниже:

String uri = request.getScheme() + "://" +
             request.getServerName() + 
             ("http".equals(request.getScheme()) && request.getServerPort() == 80 || "https".equals(request.getScheme()) && request.getServerPort() == 443 ? "" : ":" + request.getServerPort() ) +
             request.getRequestURI() +
            (request.getQueryString() != null ? "?" + request.getQueryString() : "");

Этот фрагмент выше получит полный URI, скрывая порт, если использовался по умолчанию, и не добавлял "?" и строку запроса, если последняя не была предоставлена.


Проксированные запросы

Обратите внимание, что если ваш запрос проходит через прокси-сервер, вам нужно посмотреть заголовок X-Forwarded-Proto, так как схема может быть изменена:

request.getHeader("X-Forwarded-Proto")

Кроме того, общий заголовок X-Forwarded-For, который показывает исходный IP-адрес запроса вместо proxys-IP.

request.getHeader("X-Forwarded-For")

Если вы сами отвечаете за конфигурацию прокси-сервера/балансировки нагрузки, вам необходимо убедиться, что эти заголовки настроены при пересылке.

Ответ 2

Просто используйте:

String Uri = request.getRequestURL()+"?"+request.getQueryString();

Ответ 3

Тот факт, что запрос HTTPS становится HTTP, когда вы пытались создать URL-адрес на стороне сервера, указывает на то, что у вас может быть балансировщик прокси/нагрузки (nginx, pound и т.д.), разгружая шифрование SSL спереди и вперед к вашей задней панели в обычном HTTP.

Если в этом случае проверьте,

  • Правильно ли настроен ваш прокси-сервер для форвардных заголовков (Host, X-forwarded-proto, X-forwarded-for и т.д.).
  • установлен ли ваш контейнер обслуживания (например, Tomcat) для распознавания прокси-сервера спереди. Например, Tomcat требует добавления атрибутов secure="true" scheme="https" proxyPort="443" к своему Connector
  • Правильно ли обрабатывает ваш код или контейнер обслуживания. Например, Tomcat автоматически заменяет значения scheme, remoteAddr и т.д., Когда вы добавляете RemoteIpValve к своему Engine. (см. Руководство по настройке, JavaDoc), поэтому вам не нужно вручную обрабатывать эти заголовки в своем коде.

Неправильное значение заголовка прокси-сервера может привести к некорректному выводу, если request.getRequestURI() или request.getRequestURL() пытается создать исходный URL-адрес.