Skip to content

Commit

Permalink
Use URL objects instead of Strings (Azure#344)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Schulte authored Jan 10, 2018
1 parent 54ffc65 commit e8c95af
Show file tree
Hide file tree
Showing 27 changed files with 214 additions and 117 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void refreshToken() throws IOException {
final HttpRequest request = httpClient.requests().get(0);
assertEquals(HttpMethod.POST, request.httpMethod());
assertEquals("com.microsoft.azure.v2.credentials.RefreshTokenClient$RefreshTokenService.refreshToken", request.callerMethod());
assertEquals("http://my.base.url/mockTenant/oauth2/token", request.url());
assertEquals("http://my.base.url/mockTenant/oauth2/token", request.url().toString());

String receivedContent = new String(FlowableUtil.collectBytes(request.body().content()).blockingGet(), Charsets.UTF_8);
assertEquals("client_id=mockClientId&grant_type=refresh_token&resource=mockResource&refresh_token=mockRefreshToken", receivedContent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,16 @@
import io.reactivex.functions.Function;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

/**
* A PollStrategy type that uses the Azure-AsyncOperation header value to check the status of a long
* running operation.
*/
public final class AzureAsyncOperationPollStrategy extends PollStrategy {
private final String operationResourceUrl;
private final String originalResourceUrl;
private final URL operationResourceUrl;
private final URL originalResourceUrl;

private boolean pollingCompleted;
private boolean pollingSucceeded;
Expand All @@ -43,7 +45,7 @@ public final class AzureAsyncOperationPollStrategy extends PollStrategy {
* @param delayInMilliseconds The delay (in milliseconds) that the pollStrategy will use when
* polling.
*/
private AzureAsyncOperationPollStrategy(RestProxy restProxy, SwaggerMethodParser methodParser, String operationResourceUrl, String originalResourceUrl, long delayInMilliseconds) {
private AzureAsyncOperationPollStrategy(RestProxy restProxy, SwaggerMethodParser methodParser, URL operationResourceUrl, URL originalResourceUrl, long delayInMilliseconds) {
super(restProxy, methodParser, delayInMilliseconds);

this.operationResourceUrl = operationResourceUrl;
Expand All @@ -52,7 +54,7 @@ private AzureAsyncOperationPollStrategy(RestProxy restProxy, SwaggerMethodParser

@Override
public HttpRequest createPollRequest() {
String pollUrl;
URL pollUrl;
if (!pollingCompleted) {
pollUrl = operationResourceUrl;
}
Expand Down Expand Up @@ -147,8 +149,14 @@ public boolean isDone() {
* use when polling.
*/
static PollStrategy tryToCreate(RestProxy restProxy, SwaggerMethodParser methodParser, HttpRequest originalHttpRequest, HttpResponse httpResponse, long delayInMilliseconds) {
final String azureAsyncOperationUrl = getHeader(httpResponse);
return azureAsyncOperationUrl != null && !azureAsyncOperationUrl.isEmpty()
URL azureAsyncOperationUrl = null;

try {
azureAsyncOperationUrl = new URL(getHeader(httpResponse));
} catch (MalformedURLException ignored) {
}

return azureAsyncOperationUrl != null
? new AzureAsyncOperationPollStrategy(restProxy, methodParser, azureAsyncOperationUrl, originalHttpRequest.url(), delayInMilliseconds)
: null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* operation.
*/
public final class LocationPollStrategy extends PollStrategy {
private String locationUrl;
private URL locationUrl;
private boolean done;

/**
Expand All @@ -31,7 +31,7 @@ public final class LocationPollStrategy extends PollStrategy {
*/
public static final String HEADER_NAME = "Location";

private LocationPollStrategy(RestProxy restProxy, SwaggerMethodParser methodParser, String locationUrl, long delayInMilliseconds) {
private LocationPollStrategy(RestProxy restProxy, SwaggerMethodParser methodParser, URL locationUrl, long delayInMilliseconds) {
super(restProxy, methodParser, delayInMilliseconds);

this.locationUrl = locationUrl;
Expand All @@ -47,15 +47,15 @@ public Single<HttpResponse> updateFromAsync(HttpResponse httpPollResponse) {
return ensureExpectedStatus(httpPollResponse, new int[] {202})
.map(new Function<HttpResponse, HttpResponse>() {
@Override
public HttpResponse apply(HttpResponse response) {
public HttpResponse apply(HttpResponse response) throws MalformedURLException {
final int httpStatusCode = response.statusCode();

updateDelayInMillisecondsFrom(response);

if (httpStatusCode == 202) {
String newLocationUrl = response.headerValue(HEADER_NAME);
String newLocationUrl = getHeader(response);
if (newLocationUrl != null) {
locationUrl = newLocationUrl;
locationUrl = new URL(newLocationUrl);
}
}
else {
Expand Down Expand Up @@ -86,19 +86,22 @@ public boolean isDone() {
static PollStrategy tryToCreate(RestProxy restProxy, SwaggerMethodParser methodParser, HttpRequest originalHttpRequest, HttpResponse httpResponse, long delayInMilliseconds) {
final String locationUrl = getHeader(httpResponse);

String pollUrl = null;
URL pollUrl = null;
if (locationUrl != null && !locationUrl.isEmpty()) {
if (locationUrl.startsWith("/")) {
try {
final URL originalRequestUrl = new URL(originalHttpRequest.url());
pollUrl = new URL(originalRequestUrl, locationUrl).toString();
final URL originalRequestUrl = originalHttpRequest.url();
pollUrl = new URL(originalRequestUrl, locationUrl);
} catch (MalformedURLException ignored) {
}
}
else {
final String locationUrlLower = locationUrl.toLowerCase();
if (locationUrlLower.startsWith("http://") || locationUrlLower.startsWith("https://")) {
pollUrl = locationUrl;
try {
pollUrl = new URL(locationUrl);
} catch (MalformedURLException ignored) {
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

Expand Down Expand Up @@ -66,7 +67,7 @@ public Single<HttpResponse> sendRequestAsync(HttpRequest request) {
MockAzureHttpResponse response = null;

try {
final URI requestUrl = new URI(request.url());
final URL requestUrl = request.url();
final String requestHost = requestUrl.getHost();
final String requestPath = requestUrl.getPath();
final String requestPathLower = requestPath.toLowerCase();
Expand All @@ -76,7 +77,7 @@ public Single<HttpResponse> sendRequestAsync(HttpRequest request) {
response = new MockAzureHttpResponse(200, responseHeaders(), "");
} else {
final HttpBinJSON json = new HttpBinJSON();
json.url = request.url()
json.url = request.url().toString()
// This is just to mimic the behavior we've seen with httpbin.org.
.replace("%20", " ");
json.headers = toMap(request.headers());
Expand All @@ -90,31 +91,31 @@ else if (requestPathLower.startsWith("/bytes/")) {
}
else if (requestPathLower.equals("/delete")) {
final HttpBinJSON json = new HttpBinJSON();
json.url = request.url();
json.url = request.url().toString();
json.data = bodyToString(request);
response = new MockAzureHttpResponse(200, responseHeaders(), json);
}
else if (requestPathLower.equals("/get")) {
final HttpBinJSON json = new HttpBinJSON();
json.url = request.url();
json.url = request.url().toString();
json.headers = toMap(request.headers());
response = new MockAzureHttpResponse(200, responseHeaders(), json);
}
else if (requestPathLower.equals("/patch")) {
final HttpBinJSON json = new HttpBinJSON();
json.url = request.url();
json.url = request.url().toString();
json.data = bodyToString(request);
response = new MockAzureHttpResponse(200, responseHeaders(), json);
}
else if (requestPathLower.equals("/post")) {
final HttpBinJSON json = new HttpBinJSON();
json.url = request.url();
json.url = request.url().toString();
json.data = bodyToString(request);
response = new MockAzureHttpResponse(200, responseHeaders(), json);
}
else if (requestPathLower.equals("/put")) {
final HttpBinJSON json = new HttpBinJSON();
json.url = request.url();
json.url = request.url().toString();
json.data = bodyToString(request);
response = new MockAzureHttpResponse(200, responseHeaders(), json);
}
Expand Down Expand Up @@ -167,7 +168,7 @@ else if (pollType.equalsIgnoreCase(LocationPollStrategy.HEADER_NAME)) {
else {
--pollsRemaining;
response = new MockAzureHttpResponse(202, responseHeaders())
.withHeader(LocationPollStrategy.HEADER_NAME, request.url());
.withHeader(LocationPollStrategy.HEADER_NAME, request.url().toString());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -276,7 +277,7 @@ private HttpRequest createHttpRequest(SwaggerMethodParser methodParser, Object[]
urlBuilder.addQueryParameter(queryParameter.name(), queryParameter.encodedValue());
}

final String url = urlBuilder.toString();
final URL url = urlBuilder.toURL();
final HttpRequest request = new HttpRequest(methodParser.fullyQualifiedMethodName(), methodParser.httpMethod(), url);

for (final HttpHeader header : methodParser.headers(args)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@
import io.reactivex.Flowable;

import java.io.IOException;
import java.net.URL;

/**
* This class contains all of the details necessary for sending a HTTP request through a HttpClient.
*/
public class HttpRequest {
private String callerMethod;
private HttpMethod httpMethod;
private String url;
private URL url;
private HttpHeaders headers;
private HttpRequestBody body;

Expand All @@ -28,7 +29,7 @@ public class HttpRequest {
* @param httpMethod The HTTP method to use with this request.
* @param url The URL where this HTTP request should be sent to.
*/
public HttpRequest(String callerMethod, HttpMethod httpMethod, String url) {
public HttpRequest(String callerMethod, HttpMethod httpMethod, URL url) {
this.callerMethod = callerMethod;
this.httpMethod = httpMethod;
this.url = url;
Expand All @@ -44,7 +45,7 @@ public HttpRequest(String callerMethod, HttpMethod httpMethod, String url) {
* @param headers The HTTP headers to use with this request.
* @param body The body of this HTTP request.
*/
public HttpRequest(String callerMethod, HttpMethod httpMethod, String url, HttpHeaders headers, HttpRequestBody body) {
public HttpRequest(String callerMethod, HttpMethod httpMethod, URL url, HttpHeaders headers, HttpRequestBody body) {
this.callerMethod = callerMethod;
this.httpMethod = httpMethod;
this.url = url;
Expand Down Expand Up @@ -92,7 +93,7 @@ public HttpRequest withHttpMethod(HttpMethod httpMethod) {
* Get the URL that this request will be sent to.
* @return The URL that this request will be sent to.
*/
public String url() {
public URL url() {
return url;
}

Expand All @@ -101,7 +102,7 @@ public String url() {
* @param url The new URL that this request will be sent to.
* @return This HttpRequest so that multiple operations can be chained together.
*/
public HttpRequest withUrl(String url) {
public HttpRequest withUrl(URL url) {
this.url = url;
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ private Single<HttpResponse> sendRequestInternalAsync(final HttpRequest request,
final URI channelAddress;
try {
if (proxy == null) {
channelAddress = new URI(request.url());
channelAddress = request.url().toURI();
} else if (proxy.address() instanceof InetSocketAddress) {
InetSocketAddress address = (InetSocketAddress) proxy.address();
String scheme = address.getPort() == 443
Expand Down Expand Up @@ -261,7 +261,7 @@ public boolean isDisposed() {

final DefaultHttpRequest raw = new DefaultHttpRequest(HttpVersion.HTTP_1_1,
HttpMethod.valueOf(request.httpMethod().toString()),
request.url());
request.url().toString());

for (HttpHeader header : request.headers()) {
raw.headers().add(header.name(), header.value());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

package com.microsoft.rest.v2.http;

import java.net.MalformedURLException;
import java.net.URL;

/**
* A builder class that is used to create URLs.
*/
Expand Down Expand Up @@ -196,6 +199,15 @@ private UrlBuilder with(String text, UrlTokenizerState startState) {
return this;
}

/**
* Get the URL that is being built.
* @return The URL that is being built.
* @throws MalformedURLException if the URL is not fully formed.
*/
public URL toURL() throws MalformedURLException {
return new URL(toString());
}

/**
* Get the string representation of the URL that is being built.
* @return The string representation of the URL that is being built.
Expand Down Expand Up @@ -251,6 +263,44 @@ public static UrlBuilder parse(String url) {
return result;
}

/**
* Parse a UrlBuilder from the provided URL object.
* @param url The URL object to parse.
* @return The UrlBuilder that was parsed from the URL object.
*/
public static UrlBuilder parse(URL url) {
final UrlBuilder result = new UrlBuilder();

if (url != null) {
final String protocol = url.getProtocol();
if (protocol != null && !protocol.isEmpty()) {
result.withScheme(protocol);
}

final String host = url.getHost();
if (host != null && !host.isEmpty()) {
result.withHost(host);
}

final int port = url.getPort();
if (port != -1) {
result.withPort(port);
}

final String path = url.getPath();
if (path != null && !path.isEmpty()) {
result.withPath(path);
}

final String query = url.getQuery();
if (query != null && !query.isEmpty()) {
result.withQuery(query);
}
}

return result;
}

private static String emptyToNull(String value) {
return value == null || value.isEmpty() ? null : value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ private AddCookiesPolicy(CookieHandler cookies, RequestPolicy next) {
@Override
public Single<HttpResponse> sendAsync(HttpRequest request) {
try {
final URI uri = new URI(request.url());
final URI uri = request.url().toURI();

Map<String, List<String>> cookieHeaders = new HashMap<>();
for (HttpHeader header : request.headers()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ private CredentialsPolicy(ServiceClientCredentials credentials, RequestPolicy ne
@Override
public Single<HttpResponse> sendAsync(HttpRequest request) {
try {
String token = credentials.authorizationHeaderValue(request.url());
String token = credentials.authorizationHeaderValue(request.url().toString());
request.headers().set("Authorization", token);
return next.sendAsync(request);
} catch (IOException e) {
Expand Down
Loading

0 comments on commit e8c95af

Please sign in to comment.