Skip to content

Commit c02e4bb

Browse files
committed
implement get/setBearerToken and setTokenCookie
1 parent c38934a commit c02e4bb

File tree

4 files changed

+164
-96
lines changed

4 files changed

+164
-96
lines changed

src/AndroidClient/android/src/main/java/net/servicestack/client/JsonServiceClient.java

Lines changed: 79 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import java.net.CookieManager;
2121
import java.net.HttpCookie;
2222
import java.net.HttpURLConnection;
23+
import java.net.URI;
24+
import java.net.URISyntaxException;
2325
import java.net.URL;
2426
import java.net.URLEncoder;
2527
import java.nio.charset.Charset;
@@ -30,11 +32,13 @@
3032
public class JsonServiceClient implements ServiceClient {
3133
static Charset UTF8 = Charset.forName("UTF-8");
3234
String baseUrl;
35+
URI baseUri;
3336
String replyUrl;
3437

3538
boolean alwaysSendBasicAuthHeaders;
3639
String userName;
3740
String password;
41+
String bearerToken;
3842

3943
Integer timeoutMs;
4044
public ConnectionFilter RequestFilter;
@@ -47,8 +51,16 @@ public class JsonServiceClient implements ServiceClient {
4751
Gson gson;
4852

4953
public JsonServiceClient(String baseUrl) {
54+
this(baseUrl, true);
55+
}
56+
public JsonServiceClient(String baseUrl, boolean initCookies) {
5057
setBaseUrl(baseUrl);
58+
if (initCookies) {
59+
initCookieHandler();
60+
}
61+
}
5162

63+
public void initCookieHandler() {
5264
//Automatically populate response cookies
5365
if (CookieHandler.getDefault() == null){
5466
CookieHandler.setDefault(new CookieManager());
@@ -57,6 +69,11 @@ public JsonServiceClient(String baseUrl) {
5769

5870
public void setBaseUrl(String baseUrl) {
5971
this.baseUrl = baseUrl.endsWith("/") ? baseUrl : baseUrl + "/";
72+
try {
73+
this.baseUri = new URI(this.baseUrl);
74+
} catch (URISyntaxException e) {
75+
throw new RuntimeException(e);
76+
}
6077
this.replyUrl = this.baseUrl + "json/reply/";
6178
}
6279

@@ -66,13 +83,13 @@ public void setTimeout(int timeoutMs) {
6683

6784
public GsonBuilder getGsonBuilder() {
6885
return new GsonBuilder()
69-
.registerTypeAdapterFactory(JsonSerializers.getCaseInsensitiveEnumTypeAdapterFactory())
70-
.registerTypeAdapter(Date.class, JsonSerializers.getDateSerializer())
71-
.registerTypeAdapter(Date.class, JsonSerializers.getDateDeserializer())
72-
.registerTypeAdapter(TimeSpan.class, JsonSerializers.getTimeSpanSerializer())
73-
.registerTypeAdapter(TimeSpan.class, JsonSerializers.getTimeSpanDeserializer())
74-
.registerTypeAdapter(UUID.class, JsonSerializers.getGuidSerializer())
75-
.registerTypeAdapter(UUID.class, JsonSerializers.getGuidDeserializer());
86+
.registerTypeAdapterFactory(JsonSerializers.getCaseInsensitiveEnumTypeAdapterFactory())
87+
.registerTypeAdapter(Date.class, JsonSerializers.getDateSerializer())
88+
.registerTypeAdapter(Date.class, JsonSerializers.getDateDeserializer())
89+
.registerTypeAdapter(TimeSpan.class, JsonSerializers.getTimeSpanSerializer())
90+
.registerTypeAdapter(TimeSpan.class, JsonSerializers.getTimeSpanDeserializer())
91+
.registerTypeAdapter(UUID.class, JsonSerializers.getGuidSerializer())
92+
.registerTypeAdapter(UUID.class, JsonSerializers.getGuidDeserializer());
7693
}
7794

7895
public Gson getGson() {
@@ -137,10 +154,10 @@ public String createUrl(Object requestDto, Map<String,String> query){
137154
}
138155

139156
public HttpURLConnection createRequest(String requestUrl, String httpMethod, byte[] requestBody, String requestType) {
140-
return createRequest(requestUrl, httpMethod, requestBody, requestType, false);
141-
157+
return createRequest(requestUrl, httpMethod, requestBody, requestType, false);
158+
142159
}
143-
160+
144161
public HttpURLConnection createRequest(String requestUrl, String httpMethod, byte[] requestBody, String requestType, Boolean forceAuthentication) {
145162
try {
146163
URL url = new URL(requestUrl);
@@ -159,8 +176,12 @@ public HttpURLConnection createRequest(String requestUrl, String httpMethod, byt
159176
req.setRequestProperty(HttpHeaders.ContentType, requestType);
160177
}
161178

162-
if (forceAuthentication || alwaysSendBasicAuthHeaders) {
163-
addBasicAuth(req, userName, password);
179+
if (bearerToken != null) {
180+
req.setRequestProperty(HttpHeaders.Authorization, "Bearer " + bearerToken);
181+
req.setRequestProperty("X-Auth", "Bearer"); // HttpURLConnection doesn't allow re-reading Authorization Header
182+
} else if (forceAuthentication || alwaysSendBasicAuthHeaders) {
183+
req.setRequestProperty(HttpHeaders.Authorization, "Basic " + Utils.toBase64String(userName + ":" + password));
184+
req.setRequestProperty("X-Auth", "Basic"); // HttpURLConnection doesn't allow re-reading Authorization Header
164185
}
165186

166187
if (RequestFilter != null) {
@@ -187,18 +208,12 @@ public HttpURLConnection createRequest(String requestUrl, String httpMethod, byt
187208
}
188209
}
189210

190-
private static void addBasicAuth(HttpURLConnection req, String userName, String password) {
191-
req.setRequestProperty(HttpHeaders.Authorization,
192-
"Basic " + Utils.toBase64String(userName + ":" + password));
193-
req.setRequestProperty("X-Auth", "Basic"); // HttpURLConnection doesn't allow re-reading Authorization Header
194-
}
195-
196211
private static boolean shouldAuthenticate(HttpURLConnection req, String userName, String password){
197212
try {
198213
return req.getResponseCode() == 401
199-
&& req.getRequestProperty("X-Auth") == null //only auth if auth never attempted
200-
&& userName != null
201-
&& password != null;
214+
&& req.getRequestProperty("X-Auth") == null //only auth if auth never attempted
215+
&& userName != null
216+
&& password != null;
202217
} catch (IOException e) {
203218
return false;
204219
}
@@ -211,8 +226,8 @@ public static RuntimeException createException(HttpURLConnection res, int respon
211226
InputStream errorStream = res.getErrorStream();
212227

213228
String responseBody = errorStream != null
214-
? Utils.readToEnd(errorStream, UTF8.name())
215-
: null;
229+
? Utils.readToEnd(errorStream, UTF8.name())
230+
: null;
216231

217232
webEx = new WebServiceException(responseCode, res.getResponseMessage(), responseBody);
218233

@@ -243,16 +258,16 @@ public static RuntimeException createException(HttpURLConnection res, int respon
243258
public static String GetSendMethod(Object request)
244259
{
245260
return request instanceof IGet ?
246-
HttpMethods.Get
247-
: request instanceof IPost ?
248-
HttpMethods.Post
249-
: request instanceof IPut ?
250-
HttpMethods.Put
251-
: request instanceof IDelete ?
252-
HttpMethods.Delete
253-
: request instanceof IPatch ?
254-
HttpMethods.Patch :
255-
HttpMethods.Post;
261+
HttpMethods.Get
262+
: request instanceof IPost ?
263+
HttpMethods.Post
264+
: request instanceof IPut ?
265+
HttpMethods.Put
266+
: request instanceof IDelete ?
267+
HttpMethods.Delete
268+
: request instanceof IPatch ?
269+
HttpMethods.Patch :
270+
HttpMethods.Post;
256271
}
257272

258273
public static boolean hasRequestBody(String httpMethod)
@@ -278,6 +293,21 @@ public void setAlwaysSendBasicAuthHeaders(boolean value) {
278293
this.alwaysSendBasicAuthHeaders = value;
279294
}
280295

296+
@Override
297+
public void setBearerToken(String bearerToken) {
298+
this.bearerToken = bearerToken;
299+
}
300+
301+
@Override
302+
public String getBearerToken() {
303+
return bearerToken;
304+
}
305+
306+
@Override
307+
public void setTokenCookie(String value) {
308+
setCookie("ss-tok", value, (long) (365 * 24 * 60 * 60)); //1 year
309+
}
310+
281311
@Override
282312
public void setCredentials(String userName, String password) {
283313
this.userName = userName;
@@ -303,7 +333,7 @@ public <TResponse> TResponse send(IReturn<TResponse> request) {
303333
public void send(IReturnVoid request) {
304334
String httpMethod = GetSendMethod(request);
305335
send(Utils.combinePath(replyUrl, typeName(request)), httpMethod, request,
306-
IReturnVoid.class);
336+
IReturnVoid.class);
307337
}
308338

309339
public <TResponse> TResponse send(String url, String httpMethod, Object responseClass) {
@@ -343,7 +373,7 @@ public <TResponse> TResponse send(String requestUrl, String httpMethod, byte[] r
343373
if (shouldAuthenticate(req, userName, password)){
344374
req.disconnect();
345375
req = createRequest(requestUrl, httpMethod, requestBody, requestType, true);
346-
376+
347377
success = req.getResponseCode() < 400;
348378
}
349379

@@ -384,16 +414,16 @@ public <TResponse> TResponse send(String requestUrl, String httpMethod, byte[] r
384414
Log.d(json);
385415

386416
TResponse response = resClass != null
387-
? (TResponse) getGson().fromJson(json, resClass)
388-
: (TResponse) getGson().fromJson(json, resType);
417+
? (TResponse) getGson().fromJson(json, resClass)
418+
: (TResponse) getGson().fromJson(json, resType);
389419

390420
return response;
391421
}
392422
else {
393423
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
394424
TResponse response = resClass != null
395-
? (TResponse) getGson().fromJson(reader, resClass)
396-
: (TResponse) getGson().fromJson(reader, resType);
425+
? (TResponse) getGson().fromJson(reader, resClass)
426+
: (TResponse) getGson().fromJson(reader, resType);
397427

398428
Utils.closeQuietly(reader);
399429
return response;
@@ -413,9 +443,9 @@ static String typeName(Object o){
413443

414444
private String resolveUrl(String relativeOrAbsoluteUrl) {
415445
return relativeOrAbsoluteUrl.startsWith("http:")
416-
|| relativeOrAbsoluteUrl.startsWith("https:")
417-
? relativeOrAbsoluteUrl
418-
: Utils.combinePath(baseUrl, relativeOrAbsoluteUrl);
446+
|| relativeOrAbsoluteUrl.startsWith("https:")
447+
? relativeOrAbsoluteUrl
448+
: Utils.combinePath(baseUrl, relativeOrAbsoluteUrl);
419449
}
420450

421451
@Override
@@ -451,8 +481,8 @@ public HttpURLConnection get(String path) {
451481
@Override
452482
public <TResponse> TResponse post(IReturn<TResponse> request) {
453483
return send(
454-
Utils.combinePath(replyUrl, typeName(request)), HttpMethods.Post, request,
455-
request.getResponseType());
484+
Utils.combinePath(replyUrl, typeName(request)), HttpMethods.Post, request,
485+
request.getResponseType());
456486
}
457487

458488
@Override
@@ -488,14 +518,14 @@ public HttpURLConnection post(String path, byte[] requestBody, String contentTyp
488518
@Override
489519
public <TResponse> TResponse put(IReturn<TResponse> request) {
490520
return send(
491-
Utils.combinePath(replyUrl, typeName(request)), HttpMethods.Put, request,
492-
request.getResponseType());
521+
Utils.combinePath(replyUrl, typeName(request)), HttpMethods.Put, request,
522+
request.getResponseType());
493523
}
494524

495525
@Override
496526
public void put(IReturnVoid request) {
497527
send(Utils.combinePath(replyUrl, typeName(request)), HttpMethods.Put, request,
498-
IReturnVoid.class);
528+
IReturnVoid.class);
499529
}
500530

501531
@Override
@@ -562,10 +592,11 @@ public void setCookie(String name, String value) {
562592
public void setCookie(String name, String value, Long expiresInSecs) {
563593
CookieManager cookieManager = (CookieManager) CookieHandler.getDefault();
564594
HttpCookie cookie = new HttpCookie(name, value);
595+
cookie.setVersion(0); // Required otherwise it quotes values https://stackoverflow.com/a/20204076/85785
565596
if (expiresInSecs != null){
566597
cookie.setMaxAge(expiresInSecs);
567598
}
568-
cookieManager.getCookieStore().getCookies().add(cookie);
599+
cookieManager.getCookieStore().add(baseUri, cookie);
569600
}
570601

571602
@Override

src/AndroidClient/android/src/main/java/net/servicestack/client/ServiceClient.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
public interface ServiceClient {
1111
boolean getAlwaysSendBasicAuthHeaders();
12+
void setBearerToken(String value);
13+
String getBearerToken();
14+
void setTokenCookie(String value);
1215
void setAlwaysSendBasicAuthHeaders(boolean value);
1316
void setCredentials(String userName, String password);
1417

0 commit comments

Comments
 (0)