-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathUngzippingInterceptor.java
151 lines (120 loc) · 4.66 KB
/
UngzippingInterceptor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import androidx.annotation.NonNull;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PushbackInputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class UngzippingInterceptor implements Interceptor {
private static final String HEADER_CONTENT_ENCODING = "Content-Encoding";
private static final String HEADER_GZIP = "gzip";
public Response intercept(@NonNull Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return this.ungzip(response);
}
private Response ungzip(Response response) throws IOException {
if (response.body() != null && this.isGzipped(response)) {
try{
InputStream inputFormtGZIP = maybeDecompress(response.body().source().inputStream());
String data = StringGZipper.ungzip(readBytes(inputFormtGZIP));
MediaType contentType = response.body().contentType();
ResponseBody body = ResponseBody.create(contentType, data);
return response.newBuilder().body(body).build();
}catch (Exception err){
return response;
}
} else {
return response;
}
}
private boolean isGzipped(Response response) {
Headers headers = response.headers();
for (int i = 0; i < headers.size(); ++i) {
String name = headers.name(i);
String value = headers.value(i);
if (HEADER_CONTENT_ENCODING.equalsIgnoreCase(name) && HEADER_GZIP.equalsIgnoreCase(value)) {
return true;
}
}
return false;
}
public static boolean isGZIPStream(byte[] bytes) {
return bytes[0] == (byte) GZIPInputStream.GZIP_MAGIC
&& bytes[1] == (byte) (GZIPInputStream.GZIP_MAGIC >>> 8);
}
private enum StringGZipper {
;
private static String ungzip(byte[] bytes) throws IOException{
InputStreamReader isr = new InputStreamReader(new GZIPInputStream(new ByteArrayInputStream(bytes)), StandardCharsets.UTF_8);
StringWriter sw = new StringWriter();
char[] chars = new char[bytes.length];
for (int len; (len = isr.read(chars)) > 0; ) {
sw.write(chars, 0, len);
}
return sw.toString();
}
private static byte[] gzip(String s) throws IOException{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
GZIPOutputStream gzip = new GZIPOutputStream(bos);
OutputStreamWriter osw = new OutputStreamWriter(gzip, StandardCharsets.UTF_8);
osw.write(s);
osw.close();
return bos.toByteArray();
}
}
private static byte[] readBytes( InputStream stream ) throws IOException {
if (stream == null) return new byte[] {};
byte[] buffer = new byte[stream.available()];
ByteArrayOutputStream output = new ByteArrayOutputStream();
boolean error = false;
try {
int numRead = 0;
while ((numRead = stream.read(buffer)) > -1) {
output.write(buffer, 0, numRead);
}
} catch (IOException e) {
error = true; // this error should be thrown, even if there is an error closing stream
throw e;
} catch (RuntimeException e) {
error = true; // this error should be thrown, even if there is an error closing stream
throw e;
} finally {
try {
stream.close();
} catch (IOException e) {
if (!error) throw e;
}
}
output.flush();
return output.toByteArray();
}
private static InputStream maybeDecompress(InputStream input) throws IOException {
final PushbackInputStream pb = new PushbackInputStream(input, 2);
int header = pb.read();
if(header == -1) {
return pb;
}
int b = pb.read();
if(b == -1) {
pb.unread(header);
return pb;
}
pb.unread(new byte[]{(byte)header, (byte)b});
header = (b << 8) | header;
if(header == GZIPInputStream.GZIP_MAGIC) {
return new GZIPInputStream(pb);
} else {
return pb;
}
}
}