1e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller/*
2e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Copyright (C) 2014 Square, Inc.
3e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller *
4e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
5e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * you may not use this file except in compliance with the License.
6e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * You may obtain a copy of the License at
7e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller *
8e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
9e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller *
10e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Unless required by applicable law or agreed to in writing, software
11e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
12e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * See the License for the specific language governing permissions and
14e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * limitations under the License.
15e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */
16e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpackage com.squareup.okhttp.recipes;
17e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
18e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.google.gson.Gson;
19e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.Interceptor;
20e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.MediaType;
21e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.OkHttpClient;
22e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.Request;
23e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.RequestBody;
24e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport com.squareup.okhttp.Response;
25e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.IOException;
26e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.LinkedHashMap;
27e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.Map;
28e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport okio.BufferedSink;
29e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport okio.GzipSink;
30e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport okio.Okio;
31e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
32e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpublic final class RequestBodyCompression {
33e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /**
34e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * The Google API KEY for OkHttp recipes. If you're using Google APIs for anything other than
35e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   * running these examples, please request your own client ID!
36e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   *   https://console.developers.google.com/project
37e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller   */
38e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public static final String GOOGLE_API_KEY = "AIzaSyAx2WZYe0My0i-uGurpvraYJxO7XNbwiGs";
39e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json");
40e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
41e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private final OkHttpClient client = new OkHttpClient();
42e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
43e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public RequestBodyCompression() {
44e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    client.interceptors().add(new GzipRequestInterceptor());
45e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
46e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
47e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public void run() throws Exception {
48e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Map<String, String> requestBody = new LinkedHashMap<>();
49e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    requestBody.put("longUrl", "https://publicobject.com/2014/12/04/html-formatting-javadocs/");
50e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    RequestBody jsonRequestBody = RequestBody.create(
51e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        MEDIA_TYPE_JSON, new Gson().toJson(requestBody));
52e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Request request = new Request.Builder()
53e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        .url("https://www.googleapis.com/urlshortener/v1/url?key=" + GOOGLE_API_KEY)
54e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        .post(jsonRequestBody)
55e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        .build();
56e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
57e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Response response = client.newCall(request).execute();
58e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
59e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
60e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    System.out.println(response.body().string());
61e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
62e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
63e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public static void main(String... args) throws Exception {
64e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    new RequestBodyCompression().run();
65e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
66e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
67e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /** This interceptor compresses the HTTP request body. Many webservers can't handle this! */
68e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  static class GzipRequestInterceptor implements Interceptor {
69e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    @Override public Response intercept(Chain chain) throws IOException {
70e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      Request originalRequest = chain.request();
71e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
72e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        return chain.proceed(originalRequest);
73e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      }
74e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
75e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      Request compressedRequest = originalRequest.newBuilder()
76e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          .header("Content-Encoding", "gzip")
77e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          .method(originalRequest.method(), gzip(originalRequest.body()))
78e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          .build();
79e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      return chain.proceed(compressedRequest);
80e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
81e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
82e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    private RequestBody gzip(final RequestBody body) {
83e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      return new RequestBody() {
84e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        @Override public MediaType contentType() {
85e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          return body.contentType();
86e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        }
87e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
88e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        @Override public long contentLength() {
89e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          return -1; // We don't know the compressed length in advance!
90e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        }
91e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
92e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        @Override public void writeTo(BufferedSink sink) throws IOException {
93e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
94e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          body.writeTo(gzipSink);
95e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          gzipSink.close();
96e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        }
97e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      };
98e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
99e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
100e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller}
101