/*
* Copyright 2016 LINE Corporation
*
* LINE Corporation licenses this file to you 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.linecorp.armeria.server.http.encoding;
import java.io.IOException;
import java.io.OutputStream;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPOutputStream;
import javax.annotation.Nullable;
import com.linecorp.armeria.common.http.HttpHeaderNames;
import com.linecorp.armeria.common.http.HttpRequest;
/**
* Support utilities for dealing with HTTP encoding (e.g., gzip).
*/
final class HttpEncoders {
@Nullable
static HttpEncodingType getWrapperForRequest(HttpRequest request) {
String acceptEncoding = request.headers().get(HttpHeaderNames.ACCEPT_ENCODING);
if (acceptEncoding == null) {
return null;
}
return determineEncoding(acceptEncoding);
}
static DeflaterOutputStream getEncodingOutputStream(HttpEncodingType encodingType, OutputStream out) {
switch (encodingType) {
case GZIP:
try {
return new GZIPOutputStream(out, true);
} catch (IOException e) {
throw new IllegalStateException(
"Error writing gzip header. This should not happen with byte arrays.", e);
}
case DEFLATE:
return new DeflaterOutputStream(out, true);
default:
throw new IllegalArgumentException("Unexpected zlib type, this is a programming bug.");
}
}
// Copied from netty's HttpContentCompressor.
private static HttpEncodingType determineEncoding(String acceptEncoding) {
float starQ = -1.0f;
float gzipQ = -1.0f;
float deflateQ = -1.0f;
for (String encoding : acceptEncoding.split(",")) {
float q = 1.0f;
int equalsPos = encoding.indexOf('=');
if (equalsPos != -1) {
try {
q = Float.parseFloat(encoding.substring(equalsPos + 1));
} catch (NumberFormatException e) {
// Ignore encoding
q = 0.0f;
}
}
if (encoding.contains("*")) {
starQ = q;
} else if (encoding.contains("gzip") && q > gzipQ) {
gzipQ = q;
} else if (encoding.contains("deflate") && q > deflateQ) {
deflateQ = q;
}
}
if (gzipQ > 0.0f || deflateQ > 0.0f) {
if (gzipQ >= deflateQ) {
return HttpEncodingType.GZIP;
} else {
return HttpEncodingType.DEFLATE;
}
}
if (starQ > 0.0f) {
if (gzipQ == -1.0f) {
return HttpEncodingType.GZIP;
}
if (deflateQ == -1.0f) {
return HttpEncodingType.DEFLATE;
}
}
return null;
}
private HttpEncoders() {}
}