001 package railo.commons.net.http.httpclient3; 002 003 import java.io.IOException; 004 import java.io.InputStream; 005 import java.net.MalformedURLException; 006 import java.net.URL; 007 008 import org.apache.commons.httpclient.HostConfiguration; 009 import org.apache.commons.httpclient.HttpClient; 010 import org.apache.commons.httpclient.HttpException; 011 import org.apache.commons.httpclient.HttpMethod; 012 import org.apache.commons.httpclient.HttpState; 013 import org.apache.commons.httpclient.UsernamePasswordCredentials; 014 import org.apache.commons.httpclient.methods.ByteArrayRequestEntity; 015 import org.apache.commons.httpclient.methods.DeleteMethod; 016 import org.apache.commons.httpclient.methods.EntityEnclosingMethod; 017 import org.apache.commons.httpclient.methods.GetMethod; 018 import org.apache.commons.httpclient.methods.HeadMethod; 019 import org.apache.commons.httpclient.methods.InputStreamRequestEntity; 020 import org.apache.commons.httpclient.methods.PostMethod; 021 import org.apache.commons.httpclient.methods.PutMethod; 022 import org.apache.commons.httpclient.methods.RequestEntity; 023 import org.apache.commons.httpclient.methods.StringRequestEntity; 024 025 import railo.commons.io.TemporaryStream; 026 import railo.commons.io.res.Resource; 027 import railo.commons.lang.ExceptionUtil; 028 import railo.commons.lang.StringUtil; 029 import railo.commons.net.http.Entity; 030 import railo.commons.net.http.HTTPEngine; 031 import railo.commons.net.http.HTTPResponse; 032 import railo.commons.net.http.Header; 033 import railo.commons.net.http.httpclient3.entity.EmptyRequestEntity; 034 import railo.commons.net.http.httpclient3.entity.ResourceRequestEntity; 035 import railo.commons.net.http.httpclient3.entity.TemporaryStreamRequestEntity; 036 import railo.commons.net.http.httpclient3.entity._ByteArrayRequestEntity; 037 import railo.runtime.exp.PageException; 038 import railo.runtime.net.proxy.ProxyData; 039 import railo.runtime.net.proxy.ProxyDataImpl; 040 import railo.runtime.op.Caster; 041 import railo.runtime.op.Decision; 042 043 /** 044 * 045 */ 046 public final class HTTPEngine3Impl { 047 048 049 050 public static HTTPResponse get(URL url, String username, String password, long timeout, int maxRedirect, 051 String charset, String useragent,ProxyData proxy, Header[] headers) throws IOException { 052 return _invoke(new GetMethod(url.toExternalForm()), url, username, password, timeout,maxRedirect, charset, useragent, proxy, headers,null); 053 } 054 055 public static HTTPResponse head(URL url, String username, String password, int timeout, int maxRedirect, 056 String charset, String useragent,ProxyData proxy, Header[] headers) throws IOException { 057 return _invoke(new HeadMethod(url.toExternalForm()), url, username, password, timeout,maxRedirect, charset, useragent, proxy, headers,null); 058 } 059 060 public static HTTPResponse post(URL url, String username, String password, long timeout, int maxRedirect, 061 String charset, String useragent, ProxyData proxy, Header[] headers) throws IOException { 062 return _invoke(new PostMethod(url.toExternalForm()), url, username, password, timeout,maxRedirect, charset, useragent, proxy, headers,null); 063 } 064 065 public static HTTPResponse put(URL url, String username, String password, int timeout, int maxRedirect, 066 String charset, String useragent,ProxyData proxy, Header[] headers, Object body) throws IOException { 067 return _invoke(new PutMethod(url.toExternalForm()), url, username, password, timeout,maxRedirect, charset, useragent, proxy, headers,body); 068 } 069 070 public static HTTPResponse delete(URL url, String username, String password, int timeout, int maxRedirect, 071 String charset, String useragent,ProxyData proxy, Header[] headers) throws IOException { 072 return _invoke(new DeleteMethod(url.toExternalForm()), url, username, password, timeout,maxRedirect, charset, useragent, proxy, headers,null); 073 } 074 075 076 private static HTTPResponse _invoke(HttpMethod httpMethod, URL url, String username, String password, long timeout, int maxRedirect, 077 String charset, String useragent, ProxyData proxy, Header[] headers, Object body) throws IOException { 078 079 HttpClient client = new HttpClient(); 080 HostConfiguration config = client.getHostConfiguration(); 081 HttpState state = client.getState(); 082 083 setHeader(httpMethod,headers); 084 setContentType(httpMethod,charset); 085 setUserAgent(httpMethod,useragent); 086 setTimeout(client,timeout); 087 setCredentials(client,httpMethod,username,password); 088 setProxy(config,state,proxy); 089 if(body!=null && httpMethod instanceof EntityEnclosingMethod)setBody((EntityEnclosingMethod)httpMethod,body); 090 return new HTTPResponse3Impl(execute(client,httpMethod,maxRedirect),url); 091 } 092 093 094 /** 095 * Execute a HTTTP Client and follow redirect over different hosts 096 * @param client 097 * @param method 098 * @param doRedirect 099 * @return 100 * @throws IOException 101 * @throws HttpException 102 */ 103 public static HttpMethod execute(HttpClient client, HttpMethod method, int maxRedirect) throws HttpException, IOException { 104 short count=0; 105 method.setFollowRedirects(false); 106 107 while(isRedirect(client.executeMethod(method)) && count++ < maxRedirect) { 108 method=rewrite(method); 109 } 110 return method; 111 } 112 113 /** 114 * rewrite request method 115 * @param method 116 * @return 117 * @throws MalformedURLException 118 */ 119 private static HttpMethod rewrite(HttpMethod method) throws MalformedURLException { 120 org.apache.commons.httpclient.Header location = method.getResponseHeader("location"); 121 if(location==null) return method; 122 123 HostConfiguration config = method.getHostConfiguration(); 124 URL url; 125 try { 126 url = new URL(location.getValue()); 127 } 128 catch (MalformedURLException e) { 129 130 url=new URL(config.getProtocol().getScheme(), 131 config.getHost(), 132 config.getPort(), 133 mergePath(method.getPath(),location.getValue())); 134 } 135 136 method= clone(method,url); 137 138 return method; 139 } 140 141 /** 142 * FUNKTIONIERT NICHT, HOST WIRD NICHT マBERNOMMEN 143 * Clones a http method and sets a new url 144 * @param src 145 * @param url 146 * @return 147 */ 148 private static HttpMethod clone(HttpMethod src, URL url) { 149 HttpMethod trg = HttpMethodCloner.clone(src); 150 HostConfiguration trgConfig = trg.getHostConfiguration(); 151 trgConfig.setHost(url.getHost(),url.getPort(),url.getProtocol()); 152 trg.setPath(url.getPath()); 153 trg.setQueryString(url.getQuery()); 154 155 return trg; 156 } 157 158 /** 159 * merge to pathes to one 160 * @param current 161 * @param realPath 162 * @return 163 * @throws MalformedURLException 164 */ 165 private static String mergePath(String current, String realPath) throws MalformedURLException { 166 167 // get current directory 168 String currDir; 169 if(current==null || current.indexOf('/')==-1)currDir="/"; 170 else if(current.endsWith("/"))currDir=current; 171 else currDir=current.substring(0,current.lastIndexOf('/')+1); 172 173 // merge together 174 String path; 175 if(realPath.startsWith("./"))path=currDir+realPath.substring(2); 176 else if(realPath.startsWith("/"))path=realPath; 177 else if(!realPath.startsWith("../"))path=currDir+realPath; 178 else { 179 while(realPath.startsWith("../") || currDir.length()==0) { 180 realPath=realPath.substring(3); 181 currDir=currDir.substring(0,currDir.length()-1); 182 int index = currDir.lastIndexOf('/'); 183 if(index==-1)throw new MalformedURLException("invalid realpath definition for URL"); 184 currDir=currDir.substring(0,index+1); 185 } 186 path=currDir+realPath; 187 } 188 189 return path; 190 } 191 192 /** 193 * checks if status code is a redirect 194 * @param status 195 * @return is redirect 196 */ 197 private static boolean isRedirect(int status) { 198 return 199 status==HTTPEngine.STATUS_REDIRECT_FOUND || 200 status==HTTPEngine.STATUS_REDIRECT_MOVED_PERMANENTLY || 201 status==HTTPEngine.STATUS_REDIRECT_SEE_OTHER; 202 } 203 204 205 206 private static void setBody(EntityEnclosingMethod httpMethod, Object body) throws IOException { 207 if(body!=null) 208 try { 209 httpMethod.setRequestEntity(toRequestEntity(body)); 210 } catch (PageException e) { 211 throw ExceptionUtil.toIOException(e); 212 } 213 } 214 215 private static void setProxy(HostConfiguration config, HttpState state, ProxyData data) { 216 // set Proxy 217 if(ProxyDataImpl.isValid(data)) { 218 config.setProxy(data.getServer(),data.getPort()<=0?80:data.getPort()); 219 if(ProxyDataImpl.hasCredentials(data)) { 220 state.setProxyCredentials(null,null,new UsernamePasswordCredentials(data.getUsername(),StringUtil.emptyIfNull(data.getPassword()))); 221 } 222 } 223 } 224 225 private static void setCredentials(HttpClient client, HttpMethod httpMethod, String username,String password) { 226 // set Username and Password 227 if(username!=null) { 228 if(password==null)password=""; 229 client.getState().setCredentials(null,null,new UsernamePasswordCredentials(username, password)); 230 httpMethod.setDoAuthentication( true ); 231 } 232 } 233 234 private static void setTimeout(HttpClient client, long timeout) { 235 if(timeout>0){ 236 client.setConnectionTimeout((int)timeout); 237 client.setTimeout((int)timeout); 238 } 239 } 240 241 private static void setUserAgent(HttpMethod httpMethod, String useragent) { 242 if(useragent!=null)httpMethod.setRequestHeader("User-Agent",useragent); 243 } 244 245 private static void setContentType(HttpMethod httpMethod, String charset) { 246 if(charset!=null)httpMethod.addRequestHeader("Content-type", "text/html; charset="+charset ); 247 } 248 249 private static void setHeader(HttpMethod httpMethod,Header[] headers) { 250 if(headers!=null) { 251 for(int i=0;i<headers.length;i++) 252 httpMethod.addRequestHeader(headers[i].getName(), headers[i].getValue()); 253 } 254 } 255 256 private static RequestEntity toRequestEntity(Object value) throws PageException { 257 if(value instanceof RequestEntity) return (RequestEntity) value; 258 259 else if(value instanceof InputStream) { 260 return new InputStreamRequestEntity((InputStream)value,"application/octet-stream"); 261 } 262 else if(Decision.isCastableToBinary(value,false)){ 263 return new ByteArrayRequestEntity(Caster.toBinary(value)); 264 } 265 else { 266 return new StringRequestEntity(Caster.toString(value)); 267 } 268 } 269 270 public static Header header(String name, String value) { 271 return new HeaderImpl(name, value); 272 } 273 274 public static Entity getEmptyEntity(String contentType) { 275 return new EmptyRequestEntity(contentType); 276 } 277 278 public static Entity getByteArrayEntity(byte[] barr, String contentType) { 279 return new _ByteArrayRequestEntity(barr, contentType); 280 } 281 282 public static Entity getTemporaryStreamEntity(TemporaryStream ts, String contentType) { 283 return new TemporaryStreamRequestEntity(ts,contentType); 284 } 285 286 public static Entity getResourceEntity(Resource res, String contentType) { 287 return new ResourceRequestEntity(res,contentType); 288 } 289 }