Получение полного URL из HttpServletRequest в Java
Быстрый ответ
Для создания полного URL на основе объекта HttpServletRequest необходимо скомбинировать схему, имя сервера, контекстный путь и URI запроса в единое целое. В случае наличия строки параметров запроса, её также следует включить. Имеет смысл проверить, потребуется ли включение номера порта: его стоит опустить при использовании стандартных портов HTTP или HTTPS. Возьмём в качестве примера следующий код:
HttpServletRequest request; // Предполагаем, что объект уже инициализирован
String scheme = request.getScheme(); // http или https
String serverName = request.getServerName(); // Доменное имя сервера
int serverPort = request.getServerPort(); // Номер порта на сервере
String contextPath = request.getContextPath(); // Контекстное имя веб-приложения
String servletPath = request.getServletPath(); // Путь к сервлету
String pathInfo = request.getPathInfo(); // Дополнительная информация о пути
String queryString = request.getQueryString(); // Параметры запроса после "?"
// Собираем все части URL воедино
String fullUrl = scheme + "://" + serverName +
(serverPort == 80 || serverPort == 443 ? "" : ":" + serverPort) +
contextPath + servletPath +
(pathInfo == null ? "" : pathInfo) +
(queryString == null ? "" : "?" + queryString);
Данный метод динамично учитывает использование порта и наличие строки запроса для корректного составления URL.
Улучшим формирование URL с помощью StringBuilder
Применение StringBuilder
в Java позволяет улучшить производительность при составлении строк, благодаря его изменяемости. Стоит подумать о использовании StringBuilder
для более эффективного составления URL.
// Строим URL при помощи StringBuilder
StringBuilder urlBuilder = new StringBuilder();
urlBuilder.append(scheme).append("://")
.append(serverName)
.append(serverPort == 80 || serverPort == 443 ? "" : ":" + serverPort)
.append(contextPath)
.append(servletPath)
.append(pathInfo == null ? "" : pathInfo)
.append(queryString == null ? "" : "?" + queryString);
// Получаем итоговый URL
String fullUrl = urlBuilder.toString();
Интригующие приёмы и скрытые опасности при формировании URL
Особенности работы с нестандартными портами
Будьте особенно внимательны при работе приложения на нестандартных портах: их следует добавлять в URL корректно.
Обработка закодированных строк запроса
Спецсимволы в строке запроса требуют особых подходов к кодированию:
String encodedQuery = URLEncoder.encode(request.getQueryString(), "UTF-8");
// Теперь 'encodedQuery' можно непринуждённо добавлять к URL
Возможности использования UriComponentsBuilder
Если вы работаете с фреймворком Spring, UriComponentsBuilder
может стать полезным инструментом:
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(request.getRequestURL().toString());
if (queryString != null) {
builder.query(queryString);
}
String fullUrl = builder.toUriString();
Данный класс автоматически обеспечивает корректность кодировки.
Взаимодействие с различными контейнерами сервлетов
Разница между контейнерами сервлетов (такими как Tomcat, Jetty и пр.) может влиять на формирование URL, поэтому необходимо провести тестирование.
Визуализация
Вот компоненты, которые нужно собрать в пазл URL:
- Схема:
request.getScheme() + "://"
- Имя сервера:
request.getServerName()
- Порт:
":" + request.getServerPort()
- Контекстный путь:
request.getContextPath()
- Путь сервлета:
request.getServletPath()
- Дополнительная информация пути:
request.getPathInfo()
- Строка запроса:
"?" + request.getQueryString()
Примечание: Порт и строку запроса следует добавлять только при их наличии
Стандартные сценарии и профессиональные рекомендации
Работа через прокси-сервер или балансировщик нагрузки
Используйте заголовки X-Forwarded-* для точного определения реального URL:
String trueScheme = request.getHeader("X-Forwarded-Proto");
String trueServerName = request.getHeader("X-Forwarded-Host");
Передача идентификатора сессии в URL
Для сохранения идентификатора сессии используйте HttpServletResponse.encodeURL(fullUrl)
.
Безопасность
Будьте осторожны в отношении возможных уязвимостей при использовании полного URL, основанного на пользовательском вводе.
Полезные материалы
- Обсуждение на Stack Overflow о формировании полного URL с использованием HttpServletRequest.
- Официальная документация HttpServletRequest.
- Документация Spring – ServletRequestAttributes.
- Руководство DigitalOcean по извлечению параметров URL в сервлетах.
- Учебник от Tutorialspoint по работе с клиентскими HTTP запросами в сервлетах.