001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.component.http4.helper; 018 019 import java.io.IOException; 020 import java.io.InputStream; 021 import java.io.ObjectInputStream; 022 import java.io.ObjectOutputStream; 023 import java.io.OutputStream; 024 import java.net.URI; 025 import javax.servlet.ServletResponse; 026 import javax.servlet.http.HttpServletRequest; 027 028 import org.apache.camel.Exchange; 029 import org.apache.camel.RuntimeCamelException; 030 import org.apache.camel.component.http4.HttpConstants; 031 import org.apache.camel.component.http4.HttpConverter; 032 import org.apache.camel.component.http4.HttpEndpoint; 033 import org.apache.camel.component.http4.HttpMethods; 034 import org.apache.camel.converter.IOConverter; 035 import org.apache.camel.converter.stream.CachedOutputStream; 036 import org.apache.camel.util.IOHelper; 037 import org.apache.http.HttpVersion; 038 import org.apache.http.ProtocolException; 039 040 public final class HttpHelper { 041 042 private HttpHelper() { 043 // Helper class 044 } 045 046 public static void setCharsetFromContentType(String contentType, Exchange exchange) { 047 if (contentType != null) { 048 // find the charset and set it to the Exchange 049 int index = contentType.indexOf("charset="); 050 if (index > 0) { 051 String charset = contentType.substring(index + 8); 052 exchange.setProperty(Exchange.CHARSET_NAME, IOConverter.normalizeCharset(charset)); 053 } 054 } 055 } 056 057 /** 058 * Writes the given object as response body to the servlet response 059 * <p/> 060 * The content type will be set to {@link HttpConstants#CONTENT_TYPE_JAVA_SERIALIZED_OBJECT} 061 * 062 * @param response servlet response 063 * @param target object to write 064 * @throws IOException is thrown if error writing 065 */ 066 public static void writeObjectToServletResponse(ServletResponse response, Object target) throws IOException { 067 response.setContentType(HttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT); 068 ObjectOutputStream oos = new ObjectOutputStream(response.getOutputStream()); 069 writeObjectToStream(response.getOutputStream(), target); 070 } 071 072 /** 073 * Writes the given object as response body to the output stream 074 * 075 * @param stream output stream 076 * @param target object to write 077 * @throws IOException is thrown if error writing 078 */ 079 public static void writeObjectToStream(OutputStream stream, Object target) throws IOException { 080 ObjectOutputStream oos = new ObjectOutputStream(stream); 081 oos.writeObject(target); 082 oos.flush(); 083 IOHelper.close(oos); 084 } 085 086 /** 087 * Deserializes the input stream to a Java object 088 * 089 * @param is input stream for the Java object 090 * @return the java object, or <tt>null</tt> if input stream was <tt>null</tt> 091 * @throws ClassNotFoundException is thrown if class not found 092 * @throws IOException can be thrown 093 */ 094 public static Object deserializeJavaObjectFromStream(InputStream is) throws ClassNotFoundException, IOException { 095 if (is == null) { 096 return null; 097 } 098 099 Object answer = null; 100 ObjectInputStream ois = new ObjectInputStream(is); 101 try { 102 answer = ois.readObject(); 103 } finally { 104 IOHelper.close(ois); 105 } 106 107 return answer; 108 } 109 110 /** 111 * Reads the response body from the given http servlet request. 112 * 113 * @param request http servlet request 114 * @param exchange the exchange 115 * @return the response body, can be <tt>null</tt> if no body 116 * @throws IOException is thrown if error reading response body 117 */ 118 public static Object readResponseBodyFromServletRequest(HttpServletRequest request, Exchange exchange) throws IOException { 119 InputStream is = HttpConverter.toInputStream(request, exchange); 120 return readResponseBodyFromInputStream(is, exchange); 121 } 122 123 /** 124 * Reads the response body from the given input stream. 125 * 126 * @param is the input stream 127 * @param exchange the exchange 128 * @return the response body, can be <tt>null</tt> if no body 129 * @throws IOException is thrown if error reading response body 130 */ 131 public static Object readResponseBodyFromInputStream(InputStream is, Exchange exchange) throws IOException { 132 if (is == null) { 133 return null; 134 } 135 136 // convert the input stream to StreamCache if the stream cache is not disabled 137 if (exchange.getProperty(Exchange.DISABLE_HTTP_STREAM_CACHE, Boolean.FALSE, Boolean.class)) { 138 return is; 139 } else { 140 CachedOutputStream cos = new CachedOutputStream(exchange); 141 IOHelper.copyAndCloseInput(is, cos); 142 return cos.getStreamCache(); 143 } 144 } 145 146 /** 147 * Creates the URL to invoke. 148 * 149 * @param exchange the exchange 150 * @param endpoint the endpoint 151 * @return the URL to invoke 152 */ 153 public static String createURL(Exchange exchange, HttpEndpoint endpoint) { 154 String uri = null; 155 if (!(endpoint.isBridgeEndpoint())) { 156 uri = exchange.getIn().getHeader(Exchange.HTTP_URI, String.class); 157 } 158 if (uri == null) { 159 uri = endpoint.getHttpUri().toASCIIString(); 160 } 161 162 // append HTTP_PATH to HTTP_URI if it is provided in the header 163 String path = exchange.getIn().getHeader(Exchange.HTTP_PATH, String.class); 164 if (path != null) { 165 if (path.startsWith("/")) { 166 URI baseURI; 167 String baseURIString = exchange.getIn().getHeader(Exchange.HTTP_BASE_URI, String.class); 168 try { 169 if (baseURIString == null) { 170 if (exchange.getFromEndpoint() != null) { 171 baseURIString = exchange.getFromEndpoint().getEndpointUri(); 172 } else { 173 // will set a default one for it 174 baseURIString = "/"; 175 } 176 } 177 baseURI = new URI(baseURIString); 178 String basePath = baseURI.getRawPath(); 179 if (path.startsWith(basePath)) { 180 path = path.substring(basePath.length()); 181 if (path.startsWith("/")) { 182 path = path.substring(1); 183 } 184 } else { 185 throw new RuntimeCamelException("Cannot analyze the Exchange.HTTP_PATH header, due to: cannot find the right HTTP_BASE_URI"); 186 } 187 } catch (Throwable t) { 188 throw new RuntimeCamelException("Cannot analyze the Exchange.HTTP_PATH header, due to: " 189 + t.getMessage(), t); 190 } 191 192 } 193 if (path.length() > 0) { 194 // make sure that there is exactly one "/" between HTTP_URI and 195 // HTTP_PATH 196 if (!uri.endsWith("/")) { 197 uri = uri + "/"; 198 } 199 uri = uri.concat(path); 200 } 201 } 202 return uri; 203 } 204 205 /** 206 * Creates the HttpMethod to use to call the remote server, often either its GET or POST. 207 * 208 * @param exchange the exchange 209 * @return the created method 210 */ 211 public static HttpMethods createMethod(Exchange exchange, HttpEndpoint endpoint, boolean hasPayload) { 212 // is a query string provided in the endpoint URI or in a header (header 213 // overrules endpoint) 214 String queryString = exchange.getIn().getHeader(Exchange.HTTP_QUERY, String.class); 215 if (queryString == null) { 216 queryString = endpoint.getHttpUri().getRawQuery(); 217 } 218 219 // compute what method to use either GET or POST 220 HttpMethods answer; 221 HttpMethods m = exchange.getIn().getHeader(Exchange.HTTP_METHOD, HttpMethods.class); 222 if (m != null) { 223 // always use what end-user provides in a header 224 answer = m; 225 } else if (queryString != null) { 226 // if a query string is provided then use GET 227 answer = HttpMethods.GET; 228 } else { 229 // fallback to POST if we have payload, otherwise GET 230 answer = hasPayload ? HttpMethods.POST : HttpMethods.GET; 231 } 232 233 return answer; 234 } 235 236 public static HttpVersion parserHttpVersion(String s) throws ProtocolException { 237 int major; 238 int minor; 239 if (s == null) { 240 throw new IllegalArgumentException("String may not be null"); 241 } 242 if (!s.startsWith("HTTP/")) { 243 throw new ProtocolException("Invalid HTTP version string: " + s); 244 } 245 int i1 = "HTTP/".length(); 246 int i2 = s.indexOf(".", i1); 247 if (i2 == -1) { 248 throw new ProtocolException("Invalid HTTP version number: " + s); 249 } 250 try { 251 major = Integer.parseInt(s.substring(i1, i2)); 252 } catch (NumberFormatException e) { 253 throw new ProtocolException("Invalid HTTP major version number: " + s); 254 } 255 i1 = i2 + 1; 256 i2 = s.length(); 257 try { 258 minor = Integer.parseInt(s.substring(i1, i2)); 259 } catch (NumberFormatException e) { 260 throw new ProtocolException("Invalid HTTP minor version number: " + s); 261 } 262 return new HttpVersion(major, minor); 263 264 } 265 }