001package com.pusher.client.util; 002 003import java.io.BufferedReader; 004import java.io.DataOutputStream; 005import java.io.IOException; 006import java.io.InputStream; 007import java.io.InputStreamReader; 008import java.net.HttpURLConnection; 009import java.net.MalformedURLException; 010import java.net.URL; 011import java.net.URLEncoder; 012import java.util.HashMap; 013import java.util.Map; 014 015import javax.net.ssl.HttpsURLConnection; 016 017import com.pusher.client.AuthorizationFailureException; 018import com.pusher.client.Authorizer; 019 020/** 021 * Used to authenticate a {@link com.pusher.client.channel.PrivateChannel 022 * private} or {@link com.pusher.client.channel.PresenceChannel presence} 023 * channel subscription. 024 * 025 * <p> 026 * Makes an HTTP request to a defined HTTP endpoint. Expects an authentication 027 * token to be returned. 028 * </p> 029 * 030 * <p> 031 * For more information see the <a 032 * href="http://pusher.com/docs/authenticating_users">Authenticating Users 033 * documentation</a>. 034 */ 035public class HttpAuthorizer implements Authorizer { 036 037 private final URL endPoint; 038 private Map<String, String> mHeaders = new HashMap<String, String>(); 039 private Map<String, String> mQueryStringParameters = new HashMap<String, String>(); 040 private final String ENCODING_CHARACTER_SET = "UTF-8"; 041 042 /** 043 * Creates a new authorizer. 044 * 045 * @param endPoint 046 * The endpoint to be called when authenticating. 047 */ 048 public HttpAuthorizer(final String endPoint) { 049 try { 050 this.endPoint = new URL(endPoint); 051 } 052 catch (final MalformedURLException e) { 053 throw new IllegalArgumentException("Could not parse authentication end point into a valid URL", e); 054 } 055 } 056 057 /** 058 * Set additional headers to be sent as part of the request. 059 * 060 * @param headers A map of headers 061 */ 062 public void setHeaders(final Map<String, String> headers) { 063 mHeaders = headers; 064 } 065 066 /** 067 * Identifies if the HTTP request will be sent over HTTPS. 068 * @return true if the endpoint protocol is 'https' 069 */ 070 public Boolean isSSL() { 071 return endPoint.getProtocol().equals("https"); 072 } 073 074 /** 075 * This methods is for passing extra parameters authentication that needs to 076 * be added to query string. 077 * 078 * @param queryStringParameters 079 * the query parameters 080 */ 081 public void setQueryStringParameters(final HashMap<String, String> queryStringParameters) { 082 mQueryStringParameters = queryStringParameters; 083 } 084 085 @Override 086 public String authorize(final String channelName, final String socketId) throws AuthorizationFailureException { 087 088 try { 089 final StringBuffer urlParameters = new StringBuffer(); 090 urlParameters.append("channel_name=").append(URLEncoder.encode(channelName, ENCODING_CHARACTER_SET)); 091 urlParameters.append("&socket_id=").append(URLEncoder.encode(socketId, ENCODING_CHARACTER_SET)); 092 093 // Adding extra parameters supplied to be added to query string. 094 for (final String parameterName : mQueryStringParameters.keySet()) { 095 urlParameters.append("&").append(parameterName).append("="); 096 urlParameters.append(URLEncoder.encode(mQueryStringParameters.get(parameterName), 097 ENCODING_CHARACTER_SET)); 098 } 099 100 HttpURLConnection connection; 101 if (isSSL()) { 102 connection = (HttpsURLConnection)endPoint.openConnection(); 103 } 104 else { 105 connection = (HttpURLConnection)endPoint.openConnection(); 106 } 107 connection.setDoOutput(true); 108 connection.setDoInput(true); 109 connection.setInstanceFollowRedirects(false); 110 connection.setRequestMethod("POST"); 111 connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 112 connection.setRequestProperty("charset", "utf-8"); 113 connection.setRequestProperty("Content-Length", 114 "" + Integer.toString(urlParameters.toString().getBytes().length)); 115 116 // Add in the user defined headers 117 for (final String headerName : mHeaders.keySet()) { 118 final String headerValue = mHeaders.get(headerName); 119 connection.setRequestProperty(headerName, headerValue); 120 } 121 122 connection.setUseCaches(false); 123 124 // Send request 125 final DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); 126 wr.writeBytes(urlParameters.toString()); 127 wr.flush(); 128 wr.close(); 129 130 // Read response 131 final InputStream is = connection.getInputStream(); 132 final BufferedReader rd = new BufferedReader(new InputStreamReader(is)); 133 String line; 134 final StringBuffer response = new StringBuffer(); 135 while ((line = rd.readLine()) != null) { 136 response.append(line); 137 } 138 rd.close(); 139 140 final int responseHttpStatus = connection.getResponseCode(); 141 if (responseHttpStatus != 200 && responseHttpStatus != 201) { 142 throw new AuthorizationFailureException(response.toString()); 143 } 144 145 return response.toString(); 146 147 } 148 catch (final IOException e) { 149 throw new AuthorizationFailureException(e); 150 } 151 } 152}