HttpResponseDecoder.java
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package com.azure.core.implementation.serializer;
import com.azure.core.http.HttpResponse;
import com.azure.core.util.serializer.SerializerAdapter;
import reactor.core.publisher.Mono;
import java.io.Closeable;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
/**
* Decode {@link HttpResponse} to {@link HttpDecodedResponse}.
*/
public final class HttpResponseDecoder {
// The adapter for deserialization
private final SerializerAdapter serializer;
/**
* Creates HttpResponseDecoder.
*
* @param serializer the serializer
*/
public HttpResponseDecoder(SerializerAdapter serializer) {
this.serializer = serializer;
}
/**
* Asynchronously decodes a {@link HttpResponse}.
*
* @param response the publisher that emits response to be decoded
* @param decodeData the necessary data required to decode the response emitted by {@code response}
* @return a publisher that emits decoded HttpResponse upon subscription
*/
public Mono<HttpDecodedResponse> decode(Mono<HttpResponse> response, HttpResponseDecodeData decodeData) {
return response.map(r -> new HttpDecodedResponse(r, this.serializer, decodeData));
}
/**
* A decorated HTTP response which has subscribable body and headers that supports lazy decoding.
*
* Subscribing to body kickoff http content reading, it's decoding then emission of decoded object.
* Subscribing to header kickoff header decoding and emission of decoded object.
*/
public static final class HttpDecodedResponse implements Closeable {
private final HttpResponse response;
private final SerializerAdapter serializer;
private final HttpResponseDecodeData decodeData;
private Mono<Object> bodyCached;
private Mono<Object> headersCached;
/**
* Creates HttpDecodedResponse.
* Package private Ctr.
*
* @param response the publisher that emits the raw response upon subscription which needs to be decoded
* @param serializer the decoder
* @param decodeData the necessary data required to decode a Http response
*/
HttpDecodedResponse(final HttpResponse response, SerializerAdapter serializer,
HttpResponseDecodeData decodeData) {
this.response = response;
this.serializer = serializer;
this.decodeData = decodeData;
}
/**
* @return get the raw response that this decoded response based on
*/
public HttpResponse getSourceResponse() {
return this.response;
}
/**
* Gets the publisher when subscribed the http content gets read, decoded
* and emitted. {@code Mono.empty()} gets emitted if the content is not
* decodable.
*
* @param body the response body to decode, null for this parameter
* indicate read body from source response and decode it.
*
* @return publisher that emits decoded http content
*/
public Mono<Object> getDecodedBody(String body) {
return getDecodedBody(body.getBytes(StandardCharsets.UTF_8));
}
// TODO (jogiles) JavaDoc
public Mono<Object> getDecodedBody(byte[] body) {
if (this.bodyCached == null) {
this.bodyCached = HttpResponseBodyDecoder.decodeByteArray(body,
this.response,
this.serializer,
this.decodeData).cache();
}
return this.bodyCached;
}
/**
* Gets the publisher when subscribed the http header gets decoded and emitted.
* {@code Mono.empty()} gets emitted if the headers are not decodable.
*
* @return publisher that emits entity instance representing decoded http headers
*/
public Mono<Object> getDecodedHeaders() {
if (this.headersCached == null) {
this.headersCached = HttpResponseHeaderDecoder.decode(this.response,
this.serializer,
this.decodeData).cache();
}
return this.headersCached;
}
/**
* @return the {@code java.lang.reflect.Type} used to decode the response body,
* null if the body is not decodable
*/
public Type getDecodedType() {
return HttpResponseBodyDecoder.decodedType(this.response, this.decodeData);
}
/**
* @return true if the response status code is considered as error, false otherwise
*/
public boolean isErrorStatus() {
return HttpResponseBodyDecoder.isErrorStatus(this.response, this.decodeData);
}
@Override
public void close() {
this.response.close();
}
}
}