All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.signalfx.shaded.jetty.client.util.BufferingResponseListener Maven / Gradle / Ivy

//
//  ========================================================================
//  Copyright (c) 1995-2022 Mort Bay Consulting Pty Ltd and others.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package com.signalfx.shaded.jetty.client.util;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Locale;

import com.signalfx.shaded.jetty.client.api.Request;
import com.signalfx.shaded.jetty.client.api.Response;
import com.signalfx.shaded.jetty.client.api.Response.Listener;
import com.signalfx.shaded.jetty.client.api.Result;
import com.signalfx.shaded.jetty.http.HttpFields;
import com.signalfx.shaded.jetty.http.HttpHeader;
import com.signalfx.shaded.jetty.http.HttpMethod;
import com.signalfx.shaded.jetty.util.BufferUtil;

/**
 * 

Implementation of {@link Listener} that buffers the content up to a maximum length * specified to the constructors.

*

The content may be retrieved from {@link #onSuccess(Response)} or {@link #onComplete(Result)} * via {@link #getContent()} or {@link #getContentAsString()}.

*

Instances of this class are not reusable, so one must be allocated for each request.

*/ public abstract class BufferingResponseListener extends Listener.Adapter { private final int maxLength; private ByteBuffer buffer; private String mediaType; private String encoding; /** * Creates an instance with a default maximum length of 2 MiB. */ public BufferingResponseListener() { this(2 * 1024 * 1024); } /** * Creates an instance with the given maximum length * * @param maxLength the maximum length of the content */ public BufferingResponseListener(int maxLength) { if (maxLength < 0) throw new IllegalArgumentException("Invalid max length " + maxLength); this.maxLength = maxLength; } @Override public void onHeaders(Response response) { super.onHeaders(response); Request request = response.getRequest(); HttpFields headers = response.getHeaders(); long length = headers.getLongField(HttpHeader.CONTENT_LENGTH.asString()); if (HttpMethod.HEAD.is(request.getMethod())) length = 0; if (length > maxLength) { response.abort(new IllegalArgumentException("Buffering capacity " + maxLength + " exceeded")); return; } String contentType = headers.get(HttpHeader.CONTENT_TYPE); if (contentType != null) { String media = contentType; String charset = "charset="; int index = contentType.toLowerCase(Locale.ENGLISH).indexOf(charset); if (index > 0) { media = contentType.substring(0, index); String encoding = contentType.substring(index + charset.length()); // Sometimes charsets arrive with an ending semicolon. int semicolon = encoding.indexOf(';'); if (semicolon > 0) encoding = encoding.substring(0, semicolon).trim(); // Sometimes charsets are quoted. int lastIndex = encoding.length() - 1; if (encoding.charAt(0) == '"' && encoding.charAt(lastIndex) == '"') encoding = encoding.substring(1, lastIndex).trim(); this.encoding = encoding; } int semicolon = media.indexOf(';'); if (semicolon > 0) media = media.substring(0, semicolon).trim(); this.mediaType = media; } } @Override public void onContent(Response response, ByteBuffer content) { int length = content.remaining(); if (length > BufferUtil.space(buffer)) { int remaining = buffer == null ? 0 : buffer.remaining(); if (remaining + length > maxLength) response.abort(new IllegalArgumentException("Buffering capacity " + maxLength + " exceeded")); int requiredCapacity = buffer == null ? length : buffer.capacity() + length; int newCapacity = Math.min(Integer.highestOneBit(requiredCapacity) << 1, maxLength); buffer = BufferUtil.ensureCapacity(buffer, newCapacity); } BufferUtil.append(buffer, content); } @Override public abstract void onComplete(Result result); public String getMediaType() { return mediaType; } public String getEncoding() { return encoding; } /** * @return the content as bytes * @see #getContentAsString() */ public byte[] getContent() { if (buffer == null) return new byte[0]; return BufferUtil.toArray(buffer); } /** * @return the content as a string, using the "Content-Type" header to detect the encoding * or defaulting to UTF-8 if the encoding could not be detected. * @see #getContentAsString(String) */ public String getContentAsString() { String encoding = this.encoding; if (encoding == null) return getContentAsString(StandardCharsets.UTF_8); return getContentAsString(encoding); } /** * @param encoding the encoding of the content bytes * @return the content as a string, with the specified encoding * @see #getContentAsString() */ public String getContentAsString(String encoding) { if (buffer == null) return null; return BufferUtil.toString(buffer, Charset.forName(encoding)); } /** * @param encoding the encoding of the content bytes * @return the content as a string, with the specified encoding * @see #getContentAsString() */ public String getContentAsString(Charset encoding) { if (buffer == null) return null; return BufferUtil.toString(buffer, encoding); } /** * @return Content as InputStream */ public InputStream getContentAsInputStream() { if (buffer == null) return new ByteArrayInputStream(new byte[0]); return new ByteArrayInputStream(buffer.array(), buffer.arrayOffset(), buffer.remaining()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy