1 /* 2 * Copyright 2008 Netflix, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package net.oauth.client; 18 19 import java.io.IOException; 20 import java.io.InputStream; 21 import java.io.OutputStream; 22 import java.net.HttpURLConnection; 23 import java.net.URL; 24 import java.net.URLConnection; 25 import java.util.Collection; 26 import java.util.List; 27 import java.util.Map; 28 import net.oauth.http.HttpClient; 29 import net.oauth.http.HttpMessage; 30 import net.oauth.http.HttpResponseMessage; 31 32 /** 33 * An HttpClient based on HttpURLConnection. 34 * <p> 35 * HttpClient3 or HttpClient4 perform better than this class, as a rule; since 36 * they do things like connection pooling. They also support reading the body 37 * of an HTTP response whose status code isn't 200 (OK), which can enable your 38 * application to handle problems better. 39 * 40 * @author John Kristian 41 * @hide 42 */ 43 public class URLConnectionClient implements HttpClient { 44 45 /** Send a message to the service provider and get the response. */ 46 public HttpResponseMessage execute(HttpMessage request) throws IOException { 47 final String httpMethod = request.method; 48 final Collection<Map.Entry<String, String>> addHeaders = request.headers; 49 final URL url = request.url; 50 final URLConnection connection = url.openConnection(); 51 connection.setDoInput(true); 52 if (connection instanceof HttpURLConnection) { 53 HttpURLConnection http = (HttpURLConnection) connection; 54 http.setRequestMethod(httpMethod); 55 http.setInstanceFollowRedirects(false); 56 } 57 StringBuilder headers = new StringBuilder(httpMethod); 58 { 59 headers.append(" ").append(url.getPath()); 60 String query = url.getQuery(); 61 if (query != null && query.length() > 0) { 62 headers.append("?").append(query); 63 } 64 headers.append(EOL); 65 for (Map.Entry<String, List<String>> header : connection 66 .getRequestProperties().entrySet()) { 67 String key = header.getKey(); 68 for (String value : header.getValue()) { 69 headers.append(key).append(": ").append(value).append(EOL); 70 } 71 } 72 } 73 String contentLength = null; 74 for (Map.Entry<String, String> header : addHeaders) { 75 String key = header.getKey(); 76 if (HttpMessage.CONTENT_LENGTH.equalsIgnoreCase(key) 77 && connection instanceof HttpURLConnection) { 78 contentLength = header.getValue(); 79 } else { 80 connection.setRequestProperty(key, header.getValue()); 81 } 82 headers.append(key).append(": ").append(header.getValue()).append(EOL); 83 } 84 byte[] excerpt = null; 85 final InputStream body = request.getBody(); 86 if (body != null) { 87 try { 88 if (contentLength != null) { 89 ((HttpURLConnection) connection) 90 .setFixedLengthStreamingMode(Integer.parseInt(contentLength)); 91 } 92 connection.setDoOutput(true); 93 OutputStream output = connection.getOutputStream(); 94 try { 95 final ExcerptInputStream ex = new ExcerptInputStream(body); 96 byte[] b = new byte[1024]; 97 for (int n; 0 < (n = ex.read(b));) { 98 output.write(b, 0, n); 99 } 100 excerpt = ex.getExcerpt(); 101 } finally { 102 output.close(); 103 } 104 } finally { 105 body.close(); 106 } 107 } 108 return new URLConnectionResponse(request, headers.toString(), excerpt, connection); 109 } 110 111 private static final String EOL = HttpResponseMessage.EOL; 112 113 } 114