com.google.api.client.http.HttpResponse Maven / Gradle / Ivy
Show all versions of google-api-client Show documentation
/*
* Copyright (c) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.api.client.http;
import com.google.api.client.util.ArrayValueMap;
import com.google.api.client.util.ClassInfo;
import com.google.api.client.util.Data;
import com.google.api.client.util.FieldInfo;
import com.google.api.client.util.Strings;
import com.google.api.client.util.Types;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;
/**
* HTTP response.
*
* @since 1.0
* @author Yaniv Inbar
*/
public final class HttpResponse {
/** HTTP response content or {@code null} before {@link #getContent()}. */
private InputStream content;
/** Content encoding or {@code null}. */
public final String contentEncoding;
/**
* Content length or less than zero if not known. May be reset by {@link #getContent()} if
* response had GZip compression.
*/
private long contentLength;
/** Content type or {@code null} for none. */
public final String contentType;
/**
* HTTP headers.
*
* If a header name is used for multiple headers, only the last one is retained. The value is
* initialized to {@link HttpRequest#responseHeaders} before being parsed from the actual HTTP
* response headers.
*
*/
public final HttpHeaders headers;
/** Whether received a successful status code {@code >= 200 && < 300}. */
public final boolean isSuccessStatusCode;
/** Low-level HTTP response. */
private LowLevelHttpResponse response;
/** Status code. */
public final int statusCode;
/** Status message or {@code null}. */
public final String statusMessage;
/** HTTP transport. */
public final HttpTransport transport;
/**
* HTTP request.
*
* @since 1.4
*/
public final HttpRequest request;
/**
* Whether to disable response content logging during {@link #getContent()} (unless
* {@link Level#ALL} is loggable which forces all logging).
*
* Useful for example if content has sensitive data such as an authentication token. Defaults to
* {@code false}.
*/
public boolean disableContentLogging;
HttpResponse(HttpRequest request, LowLevelHttpResponse response) {
this.request = request;
transport = request.transport;
headers = request.headers;
this.response = response;
contentLength = response.getContentLength();
contentType = response.getContentType();
contentEncoding = response.getContentEncoding();
int code = response.getStatusCode();
statusCode = code;
isSuccessStatusCode = isSuccessStatusCode(code);
String message = response.getReasonPhrase();
statusMessage = message;
Logger logger = HttpTransport.LOGGER;
boolean loggable = logger.isLoggable(Level.CONFIG);
StringBuilder logbuf = null;
if (loggable) {
logbuf = new StringBuilder();
logbuf.append("-------------- RESPONSE --------------").append(Strings.LINE_SEPARATOR);
String statusLine = response.getStatusLine();
if (statusLine != null) {
logbuf.append(statusLine);
} else {
logbuf.append(code);
if (message != null) {
logbuf.append(' ').append(message);
}
}
logbuf.append(Strings.LINE_SEPARATOR);
}
// headers
int size = response.getHeaderCount();
Class extends HttpHeaders> headersClass = headers.getClass();
List context = Arrays.asList(headersClass);
ClassInfo classInfo = ClassInfo.of(headersClass);
HashMap fieldNameMap = HttpHeaders.getFieldNameMap(headersClass);
ArrayValueMap arrayValueMap = new ArrayValueMap(headers);
for (int i = 0; i < size; i++) {
String headerName = response.getHeaderName(i);
String headerValue = response.getHeaderValue(i);
if (loggable) {
logbuf.append(headerName + ": " + headerValue).append(Strings.LINE_SEPARATOR);
}
String fieldName = fieldNameMap.get(headerName);
if (fieldName == null) {
fieldName = headerName;
}
// use field information if available
FieldInfo fieldInfo = classInfo.getFieldInfo(fieldName);
if (fieldInfo != null) {
Type type = Data.resolveWildcardTypeOrTypeVariable(context, fieldInfo.getGenericType());
// type is now class, parameterized type, or generic array type
if (Types.isArray(type)) {
// array that can handle repeating values
Class> rawArrayComponentType =
Types.getRawArrayComponentType(context, Types.getArrayComponentType(type));
arrayValueMap.put(fieldInfo.getField(), rawArrayComponentType,
parseValue(rawArrayComponentType, context, headerValue));
} else if (Types.isAssignableToOrFrom(
Types.getRawArrayComponentType(context, type), Iterable.class)) {
// iterable that can handle repeating values
@SuppressWarnings("unchecked")
Collection