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 sendHttpMessage()56 private void sendHttpMessage() { 57 try { 58 HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); 59 byte[] postData = new byte[0]; 60 if (message != null) { 61 postData = message.getBytes("UTF-8"); 62 } 63 connection.setRequestMethod(method); 64 connection.setUseCaches(false); 65 connection.setDoInput(true); 66 connection.setConnectTimeout(HTTP_TIMEOUT_MS); 67 connection.setReadTimeout(HTTP_TIMEOUT_MS); 68 // TODO(glaznev) - query request origin from pref_room_server_url_key preferences. 69 connection.addRequestProperty("origin", HTTP_ORIGIN); 70 boolean doOutput = false; 71 if (method.equals("POST")) { 72 doOutput = true; 73 connection.setDoOutput(true); 74 connection.setFixedLengthStreamingMode(postData.length); 75 } 76 if (contentType == null) { 77 connection.setRequestProperty("Content-Type", "text/plain; charset=utf-8"); 78 } else { 79 connection.setRequestProperty("Content-Type", contentType); 80 } 81 82 // Send POST request. 83 if (doOutput && postData.length > 0) { 84 OutputStream outStream = connection.getOutputStream(); 85 outStream.write(postData); 86 outStream.close(); 87 } 88 89 // Get response. 90 int responseCode = connection.getResponseCode(); 91 if (responseCode != 200) { 92 events.onHttpError("Non-200 response to " + method + " to URL: " + url + " : " 93 + connection.getHeaderField(null)); 94 connection.disconnect(); 95 return; 96 } 97 InputStream responseStream = connection.getInputStream(); 98 String response = drainStream(responseStream); 99 responseStream.close(); 100 connection.disconnect(); 101 events.onHttpComplete(response); 102 } catch (SocketTimeoutException e) { 103 events.onHttpError("HTTP " + method + " to " + url + " timeout"); 104 } catch (IOException e) { 105 events.onHttpError("HTTP " + method + " to " + url + " error: " + e.getMessage()); 106 } 107 } 108 109 // Return the contents of an InputStream as a String. drainStream(InputStream in)110 private static String drainStream(InputStream in) { 111 Scanner s = new Scanner(in, "UTF-8").useDelimiter("\\A"); 112 return s.hasNext() ? s.next() : ""; 113 } 114 } 115