修复重定向没有按照RFC7231规范跳转的问题,修改为除了307外重定向使用GET方式

This commit is contained in:
Looly 2024-09-06 17:13:55 +08:00
parent 844e98b6fe
commit 388dc7e3a4
2 changed files with 29 additions and 13 deletions

View File

@ -32,6 +32,7 @@ import org.dromara.hutool.http.client.cookie.GlobalCookieManager;
import org.dromara.hutool.http.client.engine.AbstractClientEngine; import org.dromara.hutool.http.client.engine.AbstractClientEngine;
import org.dromara.hutool.http.meta.HeaderName; import org.dromara.hutool.http.meta.HeaderName;
import org.dromara.hutool.http.meta.HttpStatus; import org.dromara.hutool.http.meta.HttpStatus;
import org.dromara.hutool.http.meta.Method;
import java.io.IOException; import java.io.IOException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
@ -135,13 +136,13 @@ public class JdkClientEngine extends AbstractClientEngine {
// 覆盖默认Header // 覆盖默认Header
.header(message.headers(), true); .header(message.headers(), true);
if(!message.method().isIgnoreBody()){ if (!message.method().isIgnoreBody()) {
// 在允许发送body的情况下如果用户自定义了Content-Length则使用用户定义的值 // 在允许发送body的情况下如果用户自定义了Content-Length则使用用户定义的值
final long contentLength = message.contentLength(); final long contentLength = message.contentLength();
if(contentLength > 0){ if (contentLength > 0) {
// 固定请求长度 // 固定请求长度
conn.setFixedLengthStreamingMode(contentLength); conn.setFixedLengthStreamingMode(contentLength);
} else if(message.isChunked()){ } else if (message.isChunked()) {
conn.setChunkedStreamingMode(4096); conn.setChunkedStreamingMode(4096);
} }
} }
@ -176,6 +177,15 @@ public class JdkClientEngine extends AbstractClientEngine {
if (code != HttpURLConnection.HTTP_OK) { if (code != HttpURLConnection.HTTP_OK) {
if (HttpStatus.isRedirected(code)) { if (HttpStatus.isRedirected(code)) {
message.url(getLocationUrl(message.handledUrl(), conn.header(HeaderName.LOCATION))); message.url(getLocationUrl(message.handledUrl(), conn.header(HeaderName.LOCATION)));
// https://www.rfc-editor.org/rfc/rfc7231#section-6.4.7
// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Redirections
// 307方法和消息主体都不发生变化
if (HttpStatus.HTTP_TEMP_REDIRECT != code) {
// 重定向默认使用GET
message.method(Method.GET);
}
if (conn.redirectCount < message.maxRedirects()) { if (conn.redirectCount < message.maxRedirects()) {
conn.redirectCount++; conn.redirectCount++;
return send(message, isAsync); return send(message, isAsync);

View File

@ -21,7 +21,6 @@ package org.dromara.hutool.http.meta;
* *
* @author Looly, Ningqingsheng * @author Looly, Ningqingsheng
* @see java.net.HttpURLConnection * @see java.net.HttpURLConnection
*
*/ */
public interface HttpStatus { public interface HttpStatus {
@ -112,12 +111,16 @@ public interface HttpStatus {
int HTTP_MOVED_PERM = 301; int HTTP_MOVED_PERM = 301;
/** /**
* HTTP Status-Code 302: Temporary Redirect. * HTTP Status-Code 302: Temporary Redirect.<br>
* 由于不可预见的原因该页面暂不可用<br>
* GET 方法不会发生变更其他方法有可能会变更为 GET 方法
*/ */
int HTTP_MOVED_TEMP = 302; int HTTP_MOVED_TEMP = 302;
/** /**
* HTTP Status-Code 303: See Other. * HTTP Status-Code 303: See Other.<br>
* 用于 PUT POST 请求完成之后重定向来防止由于页面刷新导致的操作的重复触发<br>
* GET 方法不会发生变更其他方法会变更为 GET 方法消息主体丢失
*/ */
int HTTP_SEE_OTHER = 303; int HTTP_SEE_OTHER = 303;
@ -133,7 +136,9 @@ public interface HttpStatus {
/** /**
* HTTP 1.1 Status-Code 307: Temporary Redirect.<br> * HTTP 1.1 Status-Code 307: Temporary Redirect.<br>
* RFC-7231 * 由于不可预见的原因该页面暂不可用当站点支持非 GET 方法的链接或操作的时候该状态码优于 302 状态码<br>
* 方法和消息主体都不发生变化<br>
* https://www.rfc-editor.org/rfc/rfc7231#section-6.4.7
*/ */
int HTTP_TEMP_REDIRECT = 307; int HTTP_TEMP_REDIRECT = 307;
@ -349,11 +354,12 @@ public interface HttpStatus {
/** /**
* 是否为重定向状态码 * 是否为重定向状态码
*
* @param responseCode 被检查的状态码 * @param responseCode 被检查的状态码
* @return 是否为重定向状态码 * @return 是否为重定向状态码
* @since 5.6.3 * @since 5.6.3
*/ */
static boolean isRedirected(final int responseCode){ static boolean isRedirected(final int responseCode) {
return responseCode == HTTP_MOVED_PERM return responseCode == HTTP_MOVED_PERM
|| responseCode == HTTP_MOVED_TEMP || responseCode == HTTP_MOVED_TEMP
|| responseCode == HTTP_SEE_OTHER || responseCode == HTTP_SEE_OTHER