Skip to content

Commit

Permalink
Merge pull request Azure#264 from Azure/ServiceResponseWithHeaders
Browse files Browse the repository at this point in the history
Add RestResponse classes
  • Loading branch information
Dan Schulte authored Oct 13, 2017
2 parents 843e573 + e488375 commit f8a07d0
Show file tree
Hide file tree
Showing 8 changed files with 304 additions and 37 deletions.
86 changes: 55 additions & 31 deletions client-runtime/src/main/java/com/microsoft/rest/RestProxy.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.google.common.reflect.TypeToken;
import com.microsoft.rest.http.ContentType;
import com.microsoft.rest.http.HttpHeaders;
import com.microsoft.rest.protocol.SerializerAdapter;
import com.microsoft.rest.http.HttpClient;
import com.microsoft.rest.http.HttpHeader;
Expand All @@ -20,7 +21,6 @@
import rx.exceptions.Exceptions;
import rx.functions.Func1;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
Expand Down Expand Up @@ -79,10 +79,13 @@ protected SerializerAdapter<?> serializer() {
* @param resultType The Type of the object to return.
* @param <T> The type of the object to return. This should be the same as the resultType parameter.
* @return The deserialized version of the provided String value.
* @throws IOException if there is an error deserializing.
*/
public <T> T deserialize(String value, Type resultType) throws IOException {
return serializer.deserialize(value, resultType);
public <T> T deserialize(String value, Type resultType) {
try {
return serializer.deserialize(value, resultType);
} catch (IOException e) {
throw Exceptions.propagate(e);
}
}

/**
Expand Down Expand Up @@ -229,7 +232,7 @@ public HttpResponse call(String responseBody) {
return asyncResult;
}

private Single<?> toProxyReturnValueAsync(HttpResponse response, final String httpMethod, final Type entityType) {
private Single<?> toProxyReturnValueAsync(final HttpResponse response, final String httpMethod, final Type entityType) {
final TypeToken entityTypeToken = TypeToken.of(entityType);
final int responseStatusCode = response.statusCode();
final Single<?> asyncResult;
Expand All @@ -247,41 +250,62 @@ private Single<?> toProxyReturnValueAsync(HttpResponse response, final String ht
asyncResult = response.bodyAsInputStreamAsync();
} else if (entityTypeToken.isSubtypeOf(byte[].class)) {
asyncResult = response.bodyAsByteArrayAsync();
} else if (entityTypeToken.isSubtypeOf(RestResponse.class)) {
if (!entityTypeToken.isSubtypeOf(RestResponseWithBody.class)) {
final Type deserializedHeadersType = ((ParameterizedType) entityType).getActualTypeArguments()[0];
final HttpHeaders responseHeaders = response.headers();
final Object deserializedHeaders = deserializeHeaders(responseHeaders, deserializedHeadersType);
asyncResult = Single.just(new RestResponse<>(responseStatusCode, deserializedHeaders));
}
else {
final Type[] deserializedTypes = ((ParameterizedType) entityType).getActualTypeArguments();

final Type deserializedHeadersType = deserializedTypes[0];
final HttpHeaders responseHeaders = response.headers();
final Object deserializedHeaders = deserializeHeaders(responseHeaders, deserializedHeadersType);

final Type deserializedBodyType = deserializedTypes[1];
final TypeToken deserializedBodyTypeToken = TypeToken.of(deserializedBodyType);
if (deserializedBodyTypeToken.isSubtypeOf(byte[].class)) {
asyncResult = response.bodyAsByteArrayAsync()
.map(new Func1<byte[], RestResponseWithBody<?, byte[]>>() {
@Override
public RestResponseWithBody<?, byte[]> call(byte[] responseBodyBytes) {
return new RestResponseWithBody<>(responseStatusCode, deserializedHeaders, responseBodyBytes);
}
});
}
else {
asyncResult = response.bodyAsStringAsync()
.map(new Func1<String, RestResponseWithBody<?, ?>>() {
@Override
public RestResponseWithBody<?, ?> call(String responseBodyString) {
final Object deserializedBody = deserialize(responseBodyString, deserializedBodyType);
return new RestResponseWithBody<>(responseStatusCode, deserializedHeaders, deserializedBody);
}
});
}
}
} else {
asyncResult = response
.bodyAsStringAsync()
.flatMap(new Func1<String, Single<Object>>() {
.map(new Func1<String, Object>() {
@Override
public Single<Object> call(String responseBodyString) {
try {
return Single.just(toProxyReturnValue(responseStatusCode, responseBodyString, httpMethod, entityType));
} catch (Throwable e) {
return Single.error(e);
}
}
});
public Object call(String responseBodyString) {
return deserialize(responseBodyString, entityType);
}
});
}
return asyncResult;
}

private Object toProxyReturnValue(int httpResponseStatusCode, String httpResponseBody, String httpMethod, Type entityType) throws IOException {
final TypeToken entityTypeToken = TypeToken.of(entityType);
Object result = null;
if (entityTypeToken.isSubtypeOf(void.class) || entityTypeToken.isSubtypeOf(Void.class)) {
result = null;
} else if (httpMethod.equalsIgnoreCase("HEAD")
&& (entityTypeToken.isSubtypeOf(boolean.class) || entityTypeToken.isSubtypeOf(Boolean.class))) {
result = httpResponseStatusCode / 100 == 2;
} else if (entityTypeToken.isSubtypeOf(InputStream.class)) {
result = new ByteArrayInputStream(httpResponseBody.getBytes());
} else if (entityTypeToken.isSubtypeOf(byte[].class)) {
result = httpResponseBody.getBytes();
} else {
if (httpResponseBody != null && !httpResponseBody.isEmpty()) {
result = serializer.deserialize(httpResponseBody, entityType);
}
private Object deserializeHeaders(HttpHeaders headers, Type deserializedHeadersType) {
try {
final String headersJsonString = serializer.serialize(headers);
return deserialize(headersJsonString, deserializedHeadersType);
} catch (IOException e) {
throw Exceptions.propagate(e);
}
return result;
}

protected Object handleAsyncHttpResponse(HttpRequest httpRequest, Single<HttpResponse> asyncHttpResponse, SwaggerMethodParser methodParser, Type returnType) {
Expand Down
42 changes: 42 additions & 0 deletions client-runtime/src/main/java/com/microsoft/rest/RestResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for
* license information.
*/

package com.microsoft.rest;

/**
* The response object that is a result of making a REST request.
* @param <THeaders> The deserialized type of the response headers.
*/
public class RestResponse<THeaders> {
private final int statusCode;
private final THeaders headers;

/**
* Create a new RestResponse object.
* @param statusCode The status code of the HTTP response.
* @param headers The deserialized headers of the HTTP response.
*/
public RestResponse(int statusCode, THeaders headers) {
this.statusCode = statusCode;
this.headers = headers;
}

/**
* The status code of the HTTP response.
* @return The status code of the HTTP response.
*/
public int statusCode() {
return statusCode;
}

/**
* The deserialized headers of the HTTP response.
* @return The deserialized headers of the HTTP response.
*/
public THeaders headers() {
return headers;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for
* license information.
*/

package com.microsoft.rest;

/**
* The REST response object that is a result of making a REST request.
* @param <TBody> The deserialized type of the response body.
* @param <THeaders> The deserialized type of the response headers.
*/
public class RestResponseWithBody<THeaders, TBody> extends RestResponse<THeaders> {
private final TBody body;

/**
* Create a new RestResponseWithBody object.
* @param statusCode The status code for the REST response.
* @param headers The deserialized headers.
* @param body The deserialized body.
*/
public RestResponseWithBody(int statusCode, THeaders headers, TBody body) {
super(statusCode, headers);

this.body = body;
}

/**
* The deserialized body of the HTTP response.
* @return The deserialized body of the HTTP response.
*/
public TBody body() {
return body;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,20 @@

package com.microsoft.rest.http;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializable;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
* A collection of headers that will be applied to a HTTP request.
*/
public class HttpHeaders implements Iterable<HttpHeader> {
public class HttpHeaders implements Iterable<HttpHeader>, JsonSerializable {
private final Map<String, HttpHeader> headers = new HashMap<>();

/**
Expand Down Expand Up @@ -107,8 +113,30 @@ private HttpHeader getHeader(String headerName) {
return headers.get(headerKey);
}

/**
* Convert this HttpHeaders collection to a Map.
* @return The Map representation of this HttpHeaders collection.
*/
public Map<String, String> toMap() {
final Map<String, String> result = new HashMap<>();
for (final HttpHeader header : headers.values()) {
result.put(header.name(), header.value());
}
return result;
}

@Override
public Iterator<HttpHeader> iterator() {
return headers.values().iterator();
}

@Override
public void serialize(JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeObject(toMap());
}

@Override
public void serializeWithType(JsonGenerator jsonGenerator, SerializerProvider serializerProvider, TypeSerializer typeSerializer) throws IOException {
serialize(jsonGenerator, serializerProvider);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for
* license information.
*
* Code generated by Microsoft (R) AutoRest Code Generator.
*/

package com.microsoft.rest;

import com.fasterxml.jackson.annotation.JsonProperty;

/**
* Defines headers for httpbin.org operations.
*/
public class HttpBinHeaders {
@JsonProperty(value = "Date")
public DateTimeRfc1123 date;

@JsonProperty(value = "Via")
public String via;

@JsonProperty(value = "Connection")
public String connection;

@JsonProperty(value = "X-Processed-Time")
public double xProcessedTime;

@JsonProperty(value = "Access-Control-Allow-Credentials")
public boolean accessControlAllowCredentials;
}
Loading

0 comments on commit f8a07d0

Please sign in to comment.