-
Notifications
You must be signed in to change notification settings - Fork 148
Let users configure HTTP client #129
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
2149b54
Working implementation of configurable HttpClient
5a64362
Add integration tests. Add comments. Add Lombok getters and setters
350219a
Update tests
4154127
Remove unnecessary HttpHeaders class
1b07549
Update how multi-valued headers are handled
78e47aa
Add unit test for HttpUtils
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
93 changes: 93 additions & 0 deletions
93
src/integrationtest/java/com.microsoft.aad.msal4j/ApacheHttpClientAdapter.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package com.microsoft.aad.msal4j; | ||
|
||
import org.apache.http.Header; | ||
import org.apache.http.client.methods.CloseableHttpResponse; | ||
import org.apache.http.client.methods.HttpGet; | ||
import org.apache.http.client.methods.HttpPost; | ||
import org.apache.http.client.methods.HttpRequestBase; | ||
import org.apache.http.entity.ContentType; | ||
import org.apache.http.entity.StringEntity; | ||
import org.apache.http.impl.client.CloseableHttpClient; | ||
import org.apache.http.impl.client.HttpClients; | ||
import org.apache.http.util.EntityUtils; | ||
|
||
import java.io.IOException; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
class ApacheHttpClientAdapter implements IHttpClient { | ||
|
||
private CloseableHttpClient httpClient; | ||
|
||
ApacheHttpClientAdapter(){ | ||
this.httpClient = HttpClients.createDefault(); | ||
} | ||
|
||
@Override | ||
public IHttpResponse send(HttpRequest httpRequest) throws Exception { | ||
|
||
HttpRequestBase request = buildApacheRequestFromMsalRequest(httpRequest); | ||
CloseableHttpResponse response = httpClient.execute(request); | ||
|
||
return buildMsalResponseFromApacheResponse(response); | ||
} | ||
|
||
|
||
private HttpRequestBase buildApacheRequestFromMsalRequest(HttpRequest httpRequest){ | ||
|
||
if(httpRequest.httpMethod() == HttpMethod.GET){ | ||
return builGetRequest(httpRequest); | ||
} else if(httpRequest.httpMethod() == HttpMethod.POST){ | ||
return buildPostRequest(httpRequest); | ||
} else { | ||
throw new IllegalArgumentException("HttpRequest method should be either GET or POST"); | ||
} | ||
} | ||
|
||
private HttpGet builGetRequest(HttpRequest httpRequest){ | ||
HttpGet httpGet = new HttpGet(httpRequest.url().toString()); | ||
|
||
for(Map.Entry<String, String> entry: httpRequest.headers().entrySet()){ | ||
httpGet.setHeader(entry.getKey(), entry.getValue()); | ||
} | ||
|
||
return httpGet; | ||
} | ||
|
||
private HttpPost buildPostRequest(HttpRequest httpRequest){ | ||
|
||
HttpPost httpPost = new HttpPost(httpRequest.url().toString()); | ||
for(Map.Entry<String, String> entry: httpRequest.headers().entrySet()){ | ||
httpPost.setHeader(entry.getKey(), entry.getValue()); | ||
} | ||
|
||
String contentTypeHeaderValue = httpRequest.headerValue("Content-Type"); | ||
ContentType contentType = ContentType.getByMimeType(contentTypeHeaderValue); | ||
StringEntity stringEntity = new StringEntity(httpRequest.body(), contentType); | ||
|
||
httpPost.setEntity(stringEntity); | ||
return httpPost; | ||
} | ||
|
||
private IHttpResponse buildMsalResponseFromApacheResponse(CloseableHttpResponse apacheResponse) | ||
throws IOException { | ||
|
||
IHttpResponse httpResponse = new HttpResponse(); | ||
((HttpResponse) httpResponse).statusCode(apacheResponse.getStatusLine().getStatusCode()); | ||
|
||
Map<String, List<String>> headers = new HashMap<>(); | ||
for(Header header: apacheResponse.getAllHeaders()){ | ||
headers.put(header.getName(), Collections.singletonList(header.getValue())); | ||
} | ||
((HttpResponse) httpResponse).headers(headers); | ||
|
||
String responseBody = EntityUtils.toString(apacheResponse.getEntity(), "UTF-8"); | ||
((HttpResponse) httpResponse).body(responseBody); | ||
return httpResponse; | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
src/integrationtest/java/com.microsoft.aad.msal4j/HttpClientIT.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package com.microsoft.aad.msal4j; | ||
|
||
import labapi.LabResponse; | ||
import labapi.LabUserProvider; | ||
import labapi.NationalCloud; | ||
import org.testng.Assert; | ||
import org.testng.annotations.BeforeClass; | ||
import org.testng.annotations.Test; | ||
|
||
import java.util.Collections; | ||
|
||
public class HttpClientIT { | ||
private LabUserProvider labUserProvider; | ||
|
||
@BeforeClass | ||
public void setUp() { | ||
labUserProvider = LabUserProvider.getInstance(); | ||
} | ||
|
||
@Test | ||
public void acquireToken_okHttpClient() throws Exception { | ||
|
||
LabResponse labResponse = getManagedUserAccountWithPassword(); | ||
assertAcquireTokenCommon(labResponse, new OkHttpClientAdapter()); | ||
} | ||
|
||
@Test | ||
public void acquireToken_apacheHttpClient() throws Exception { | ||
|
||
LabResponse labResponse = getManagedUserAccountWithPassword(); | ||
assertAcquireTokenCommon(labResponse, new ApacheHttpClientAdapter()); | ||
} | ||
|
||
private void assertAcquireTokenCommon(LabResponse labResponse, IHttpClient httpClient) | ||
throws Exception{ | ||
PublicClientApplication pca = PublicClientApplication.builder( | ||
labResponse.getAppId()). | ||
authority(TestConstants.ORGANIZATIONS_AUTHORITY). | ||
httpClient(httpClient). | ||
build(); | ||
|
||
IAuthenticationResult result = pca.acquireToken(UserNamePasswordParameters. | ||
builder(Collections.singleton(TestConstants.GRAPH_DEFAULT_SCOPE), | ||
labResponse.getUser().getUpn(), | ||
labResponse.getUser().getPassword().toCharArray()) | ||
.build()) | ||
.get(); | ||
|
||
Assert.assertNotNull(result); | ||
Assert.assertNotNull(result.accessToken()); | ||
Assert.assertNotNull(result.idToken()); | ||
Assert.assertEquals(labResponse.getUser().getUpn(), result.account().username()); | ||
} | ||
|
||
private LabResponse getManagedUserAccountWithPassword(){ | ||
LabResponse labResponse = labUserProvider.getDefaultUser( | ||
NationalCloud.AZURE_CLOUD, | ||
false); | ||
labUserProvider.getUserPassword(labResponse.getUser()); | ||
|
||
return labResponse; | ||
} | ||
} |
83 changes: 83 additions & 0 deletions
83
src/integrationtest/java/com.microsoft.aad.msal4j/OkHttpClientAdapter.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
package com.microsoft.aad.msal4j; | ||
|
||
import okhttp3.Headers; | ||
import okhttp3.MediaType; | ||
import okhttp3.OkHttpClient; | ||
import okhttp3.Request; | ||
import okhttp3.RequestBody; | ||
import okhttp3.Response; | ||
import okhttp3.ResponseBody; | ||
|
||
import java.io.IOException; | ||
|
||
class OkHttpClientAdapter implements IHttpClient{ | ||
|
||
private OkHttpClient client; | ||
|
||
OkHttpClientAdapter(){ | ||
this.client = new OkHttpClient(); | ||
} | ||
|
||
@Override | ||
public IHttpResponse send(HttpRequest httpRequest) throws IOException { | ||
|
||
Request request = buildOkRequestFromMsalRequest(httpRequest); | ||
|
||
Response okHttpResponse= client.newCall(request).execute(); | ||
return buildMsalResponseFromOkResponse(okHttpResponse); | ||
} | ||
|
||
private Request buildOkRequestFromMsalRequest(HttpRequest httpRequest){ | ||
|
||
if(httpRequest.httpMethod() == HttpMethod.GET){ | ||
return buildGetRequest(httpRequest); | ||
} else if(httpRequest.httpMethod() == HttpMethod.POST){ | ||
return buildPostRequest(httpRequest); | ||
} else { | ||
throw new IllegalArgumentException("HttpRequest method should be either GET or POST"); | ||
} | ||
} | ||
|
||
private Request buildGetRequest(HttpRequest httpRequest){ | ||
Headers headers = Headers.of(httpRequest.headers()); | ||
|
||
return new Request.Builder() | ||
.url(httpRequest.url()) | ||
.headers(headers) | ||
.build(); | ||
} | ||
|
||
private Request buildPostRequest(HttpRequest httpRequest){ | ||
Headers headers = Headers.of(httpRequest.headers()); | ||
String contentType = httpRequest.headerValue("Content-Type"); | ||
MediaType type = MediaType.parse(contentType); | ||
|
||
RequestBody requestBody = RequestBody.create(type, httpRequest.body()); | ||
|
||
return new Request.Builder() | ||
.url(httpRequest.url()) | ||
.post(requestBody) | ||
.headers(headers) | ||
.build(); | ||
} | ||
|
||
private IHttpResponse buildMsalResponseFromOkResponse(Response okHttpResponse) throws IOException{ | ||
|
||
IHttpResponse httpResponse = new HttpResponse(); | ||
((HttpResponse) httpResponse).statusCode(okHttpResponse.code()); | ||
|
||
ResponseBody body = okHttpResponse.body(); | ||
if(body != null){ | ||
((HttpResponse) httpResponse).body(body.string()); | ||
} | ||
|
||
Headers headers = okHttpResponse.headers(); | ||
if(headers != null){ | ||
((HttpResponse) httpResponse).headers(headers.toMultimap()); | ||
} | ||
return httpResponse; | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.