1 /* 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 package org.appspot.apprtc.util; 12 13 import java.io.IOException; 14 import java.io.InputStream; 15 import java.io.OutputStream; 16 import java.net.HttpURLConnection; 17 import java.net.SocketTimeoutException; 18 import java.net.URL; 19 import java.util.Scanner; 20 21 /** 22 * Asynchronous http requests implementation. 23 */ 24 public class AsyncHttpURLConnection { 25 private static final int HTTP_TIMEOUT_MS = 8000; 26 private static final String HTTP_ORIGIN = "https://appr.tc"; 27 private final String method; 28 private final String url; 29 private final String message; 30 private final AsyncHttpEvents events; 31 private String contentType; 32 33 /** 34 * Http requests callbacks. 35 */ 36 public interface AsyncHttpEvents { onHttpError(String errorMessage)37 void onHttpError(String errorMessage); onHttpComplete(String response)38 void onHttpComplete(String response); 39 } 40 AsyncHttpURLConnection(String method, String url, String message, AsyncHttpEvents events)41 public AsyncHttpURLConnection(String method, String url, String message, AsyncHttpEvents events) { 42 this.method = method; 43 this.url = url; 44 this.message = message; 45 this.events = events; 46 } 47 setContentType(String contentType)48 public void setContentType(String contentType) { 49 this.contentType = contentType; 50 } 51 send()52 public void send() { 53 new Thread(this ::sendHttpMessage).start(); 54 } 55 56 @SuppressWarnings("UseNetworkAnnotations") sendHttpMessage()57 private void sendHttpMessage() { 58 try { 59 HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); 60 byte[] postData = new byte[0]; 61 if (message != null) { 62 postData = message.getBytes("UTF-8"); 63 } 64 connection.setRequestMethod(method); 65 connection.setUseCaches(false); 66 connection.setDoInput(true); 67 connection.setConnectTimeout(HTTP_TIMEOUT_MS); 68 connection.setReadTimeout(HTTP_TIMEOUT_MS); 69 // TODO(glaznev) - query request origin from pref_room_server_url_key preferences. 70 connection.addRequestProperty("origin", HTTP_ORIGIN); 71 boolean doOutput = false; 72 if (method.equals("POST")) { 73 doOutput = true; 74 connection.setDoOutput(true); 75 connection.setFixedLengthStreamingMode(postData.length); 76 } 77 if (contentType == null) { 78 connection.setRequestProperty("Content-Type", "text/plain; charset=utf-8"); 79 } else { 80 connection.setRequestProperty("Content-Type", contentType); 81 } 82 83 // Send POST request. 84 if (doOutput && postData.length > 0) { 85 OutputStream outStream = connection.getOutputStream(); 86 outStream.write(postData); 87 outStream.close(); 88 } 89 90 // Get response. 91 int responseCode = connection.getResponseCode(); 92 if (responseCode != 200) { 93 events.onHttpError("Non-200 response to " + method + " to URL: " + url + " : " 94 + connection.getHeaderField(null)); 95 connection.disconnect(); 96 return; 97 } 98 InputStream responseStream = connection.getInputStream(); 99 String response = drainStream(responseStream); 100 responseStream.close(); 101 connection.disconnect(); 102 events.onHttpComplete(response); 103 } catch (SocketTimeoutException e) { 104 events.onHttpError("HTTP " + method + " to " + url + " timeout"); 105 } catch (IOException e) { 106 events.onHttpError("HTTP " + method + " to " + url + " error: " + e.getMessage()); 107 } 108 } 109 110 // Return the contents of an InputStream as a String. drainStream(InputStream in)111 private static String drainStream(InputStream in) { 112 Scanner s = new Scanner(in, "UTF-8").useDelimiter("\\A"); 113 return s.hasNext() ? s.next() : ""; 114 } 115 } 116