Skip to content

Commit 954be44

Browse files
committed
feat: #I62BTW 隐式转换带 BasicAuth 认证信息的请求
1 parent 17ad056 commit 954be44

File tree

3 files changed

+119
-7
lines changed

3 files changed

+119
-7
lines changed

forest-core/src/main/java/com/dtflys/forest/http/ForestRequest.java

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424

2525
package com.dtflys.forest.http;
2626

27+
import com.dtflys.forest.auth.BasicAuth;
28+
import com.dtflys.forest.auth.ForestAuthenticator;
2729
import com.dtflys.forest.backend.ContentType;
2830
import com.dtflys.forest.backend.HttpBackend;
2931
import com.dtflys.forest.backend.HttpExecutor;
@@ -224,6 +226,13 @@ public class ForestRequest<T> implements HasURL {
224226
*/
225227
private ForestAsyncMode asyncMode = ForestAsyncMode.PLATFORM;
226228

229+
/**
230+
* 请求认证器
231+
*
232+
* @since 1.5.28
233+
*/
234+
private ForestAuthenticator authenticator = new BasicAuth();
235+
227236
/**
228237
* 是否打开自动重定向
229238
*/
@@ -673,6 +682,19 @@ public String getUserInfo() {
673682
return this.url.getUserInfo();
674683
}
675684

685+
/**
686+
* 获取URL用户验证信息
687+
*
688+
* <p>包含在URL中的用户验证信息,比如:
689+
* <p>URL http://xxx:yyy@localhost:8080 中 xxx:yyy 的部分为用户信息
690+
* <p>其中,xxx为用户名,yyy为用户密码
691+
*
692+
* @return URL用户验证信息
693+
*/
694+
public String userInfo() {
695+
return getUserInfo();
696+
}
697+
676698
/**
677699
* 设置URL用户验证信息
678700
*
@@ -2028,13 +2050,59 @@ public ForestAsyncMode asyncMode() {
20282050
* <p>该字段只有在 async = true 时有效</p>
20292051
*
20302052
* @param asyncMode 异步模式
2031-
* @return {@link ForestAsyncMode}枚举实例
2053+
* @return {@link ForestRequest}类实例
20322054
* @since 1.5.27
20332055
*/
20342056
public ForestRequest<T> asyncMode(ForestAsyncMode asyncMode) {
20352057
return setAsyncMode(asyncMode);
20362058
}
20372059

2060+
2061+
/**
2062+
* 获取请求认证器
2063+
*
2064+
* @return 请求认证器, {@link ForestAuthenticator}接口实例
2065+
* @since 1.5.28
2066+
*/
2067+
public ForestAuthenticator getAuthenticator() {
2068+
return authenticator;
2069+
}
2070+
2071+
/**
2072+
* 设置请求认证器
2073+
*
2074+
* @param authenticator 请求认证器, {@link ForestAuthenticator}接口实例
2075+
* @return {@link ForestRequest}类实例
2076+
* @since 1.5.28
2077+
*/
2078+
public ForestRequest<T> setAuthenticator(ForestAuthenticator authenticator) {
2079+
this.authenticator = authenticator;
2080+
return this;
2081+
}
2082+
2083+
/**
2084+
* 获取请求认证器
2085+
*
2086+
* @return 请求认证器, {@link ForestAuthenticator}接口实例
2087+
* @since 1.5.28
2088+
*/
2089+
public ForestAuthenticator authenticator() {
2090+
return authenticator;
2091+
}
2092+
2093+
/**
2094+
* 设置请求认证器
2095+
*
2096+
* @param authenticator 请求认证器, {@link ForestAuthenticator}接口实例
2097+
* @return {@link ForestRequest}类实例
2098+
* @since 1.5.28
2099+
*/
2100+
public ForestRequest<T> authenticator(ForestAuthenticator authenticator) {
2101+
this.authenticator = authenticator;
2102+
return this;
2103+
}
2104+
2105+
20382106
/**
20392107
* 是否打开自动重定向
20402108
*
@@ -4497,6 +4565,10 @@ public Object execute(HttpBackend backend, LifeCycleHandler lifeCycleHandler) {
44974565
processRedirectionRequest();
44984566
// 执行 beforeExecute
44994567
if (interceptorChain.beforeExecute(this)) {
4568+
// 认证信息增强
4569+
if (this.authenticator != null) {
4570+
this.authenticator.enhanceAuthorization(this);
4571+
}
45004572
this.url.mergeAddress().checkAndComplete();
45014573
ForestCookies cookies = new ForestCookies();
45024574
lifeCycleHandler.handleLoadCookie(this, cookies);

forest-core/src/main/java/com/dtflys/forest/lifecycles/authorization/BasicAuthLifeCycle.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.dtflys.forest.lifecycles.MethodAnnotationLifeCycle;
66
import com.dtflys.forest.reflection.ForestMethod;
77
import com.dtflys.forest.utils.Base64Utils;
8+
import com.dtflys.forest.utils.StringUtils;
89

910
public class BasicAuthLifeCycle implements MethodAnnotationLifeCycle<BasicAuth, Object> {
1011

@@ -17,8 +18,9 @@ public void onInvokeMethod(ForestRequest request, ForestMethod method, Object[]
1718
public boolean beforeExecute(ForestRequest request) {
1819
String username = (String) getAttribute(request, "username");
1920
String password = (String) getAttribute(request, "password");
20-
String basic = "Basic " + Base64Utils.encode(username + ":" + password);
21-
request.addHeader("Authorization", basic);
21+
if (StringUtils.isNotEmpty(username) || StringUtils.isNotEmpty(password)) {
22+
request.authenticator(new com.dtflys.forest.auth.BasicAuth(username, password));
23+
}
2224
return true;
2325
}
2426

forest-core/src/test/java/com/dtflys/test/TestGenericForestClient.java

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import com.alibaba.fastjson.JSON;
44
import com.dtflys.forest.Forest;
5+
import com.dtflys.forest.auth.BasicAuth;
6+
import com.dtflys.forest.auth.ForestAuthenticator;
57
import com.dtflys.forest.backend.ContentType;
68
import com.dtflys.forest.backend.HttpBackend;
79
import com.dtflys.forest.converter.ForestEncoder;
@@ -273,6 +275,40 @@ public void testRequest_query_map() {
273275
}
274276

275277

278+
@Test
279+
public void testAuth_UsernamePassword() {
280+
server.enqueue(new MockResponse().setBody(EXPECTED));
281+
ForestRequest request =
282+
Forest.get("http://foo:bar@localhost:" + server.getPort() + "/xxx");
283+
assertThat(request.userInfo()).isEqualTo("foo:bar");
284+
request.execute();
285+
mockRequest(server)
286+
.assertHeaderEquals("Authorization", "Basic Zm9vOmJhcg==");
287+
}
288+
289+
@Test
290+
public void testAuth_BasicAuth() {
291+
server.enqueue(new MockResponse().setBody(EXPECTED));
292+
Forest.get("/")
293+
.port(server.getPort())
294+
.authenticator(new BasicAuth("foo", "bar"))
295+
.execute();
296+
mockRequest(server)
297+
.assertHeaderEquals("Authorization", "Basic Zm9vOmJhcg==");
298+
}
299+
300+
@Test
301+
public void testAuth_BasicAuth2() {
302+
server.enqueue(new MockResponse().setBody(EXPECTED));
303+
Forest.get("/")
304+
.port(server.getPort())
305+
.authenticator(new BasicAuth("foo:bar"))
306+
.execute();
307+
mockRequest(server)
308+
.assertHeaderEquals("Authorization", "Basic Zm9vOmJhcg==");
309+
}
310+
311+
276312
@Test
277313
public void testAsyncPool() {
278314
Forest.config()
@@ -586,7 +622,7 @@ public void testRequest_change_base_path4() {
586622
@Test
587623
public void testRequest_change_base_path5() {
588624
server.enqueue(new MockResponse().setBody(EXPECTED));
589-
ForestRequest request = Forest.get("/A")
625+
ForestRequest request = Forest.get("/A")
590626
.basePath("http://localhost:" + server.getPort() + "/X1/X2");
591627
String result = request.executeAsString();
592628
assertThat(request.basePath()).isEqualTo("/X1/X2");
@@ -1156,7 +1192,7 @@ public byte[] onBodyEncode(ForestRequest request, ForestEncoder encoder, byte[]
11561192
return (str + "&c=3").getBytes();
11571193
}
11581194
})
1159-
.addInterceptor(new Interceptor() {
1195+
.addInterceptor(new Interceptor() {
11601196
@Override
11611197
public byte[] onBodyEncode(ForestRequest request, ForestEncoder encoder, byte[] encodedData) {
11621198
String str = new String(encodedData);
@@ -1291,7 +1327,8 @@ public void testRequest_upload_file() {
12911327
.contentTypeMultipartFormData()
12921328
.addFile("file", file)
12931329
.executeAsResponse()
1294-
.get(new TypeReference<Result<Integer>>() {});
1330+
.get(new TypeReference<Result<Integer>>() {
1331+
});
12951332
assertThat(result).isNotNull();
12961333
assertThat(result.getStatus()).isEqualTo(1);
12971334
assertThat(result.getData()).isEqualTo(2);
@@ -1411,7 +1448,8 @@ public void testRequest_async_await2() {
14111448
.addQuery("a", "1")
14121449
.executeAsFuture()
14131450
.await()
1414-
.get(new TypeReference<Map<String, Object>>() {});
1451+
.get(new TypeReference<Map<String, Object>>() {
1452+
});
14151453
mockRequest(server)
14161454
.assertPathEquals("/")
14171455
.assertQueryEquals("a=1");

0 commit comments

Comments
 (0)