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.http.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.RuntimeExchangeException; 030 import org.apache.camel.component.http.HttpConstants; 031 import org.apache.camel.component.http.HttpConverter; 032 import org.apache.camel.component.http.HttpEndpoint; 033 import org.apache.camel.component.http.HttpMethods; 034 import org.apache.camel.converter.IOConverter; 035 import org.apache.camel.converter.stream.CachedOutputStream; 036 import org.apache.camel.util.IOHelper; 037 038 public final class HttpHelper { 039 040 private HttpHelper() { 041 // Helper class 042 } 043 044 public static void setCharsetFromContentType(String contentType, Exchange exchange) { 045 if (contentType != null) { 046 // find the charset and set it to the Exchange 047 int index = contentType.indexOf("charset="); 048 if (index > 0) { 049 String charset = contentType.substring(index + 8); 050 exchange.setProperty(Exchange.CHARSET_NAME, IOConverter.normalizeCharset(charset)); 051 } 052 } 053 } 054 055 /** 056 * Writes the given object as response body to the servlet response 057 * <p/> 058 * The content type will be set to {@link HttpConstants#CONTENT_TYPE_JAVA_SERIALIZED_OBJECT} 059 * 060 * @param response servlet response 061 * @param target object to write 062 * @throws IOException is thrown if error writing 063 */ 064 public static void writeObjectToServletResponse(ServletResponse response, Object target) throws IOException { 065 response.setContentType(HttpConstants.CONTENT_TYPE_JAVA_SERIALIZED_OBJECT); 066 writeObjectToStream(response.getOutputStream(), target); 067 } 068 069 /** 070 * Writes the given object as response body to the output stream 071 * 072 * @param stream output stream 073 * @param target object to write 074 * @throws IOException is thrown if error writing 075 */ 076 public static void writeObjectToStream(OutputStream stream, Object target) throws IOException { 077 ObjectOutputStream oos = new ObjectOutputStream(stream); 078 oos.writeObject(target); 079 oos.flush(); 080 IOHelper.close(oos); 081 } 082 083 /** 084 * Deserializes the input stream to a Java object 085 * 086 * @param is input stream for the Java object 087 * @return the java object, or <tt>null</tt> if input stream was <tt>null</tt> 088 * @throws ClassNotFoundException is thrown if class not found 089 * @throws IOException can be thrown 090 */ 091 public static Object deserializeJavaObjectFromStream(InputStream is) throws ClassNotFoundException, IOException { 092 if (is == null) { 093 return null; 094 } 095 096 Object answer = null; 097 ObjectInputStream ois = new ObjectInputStream(is); 098 try { 099 answer = ois.readObject(); 100 } finally { 101 IOHelper.close(ois); 102 } 103 104 return answer; 105 } 106 107 /** 108 * Reads the response body from the given http servlet request. 109 * 110 * @param request http servlet request 111 * @param exchange the exchange 112 * @return the response body, can be <tt>null</tt> if no body 113 * @throws IOException is thrown if error reading response body 114 */ 115 public static Object readResponseBodyFromServletRequest(HttpServletRequest request, Exchange exchange) throws IOException { 116 InputStream is = HttpConverter.toInputStream(request, exchange); 117 return readResponseBodyFromInputStream(is, exchange); 118 } 119 120 /** 121 * Reads the response body from the given input stream. 122 * 123 * @param is the input stream 124 * @param exchange the exchange 125 * @return the response body, can be <tt>null</tt> if no body 126 * @throws IOException is thrown if error reading response body 127 */ 128 public static Object readResponseBodyFromInputStream(InputStream is, Exchange exchange) throws IOException { 129 if (is == null) { 130 return null; 131 } 132 133 // convert the input stream to StreamCache if the stream cache is not disabled 134 if (exchange.getProperty(Exchange.DISABLE_HTTP_STREAM_CACHE, Boolean.FALSE, Boolean.class)) { 135 return is; 136 } else { 137 CachedOutputStream cos = new CachedOutputStream(exchange); 138 IOHelper.copyAndCloseInput(is, cos); 139 return cos.getStreamCache(); 140 } 141 } 142 143 /** 144 * Creates the URL to invoke. 145 * 146 * @param exchange the exchange 147 * @param endpoint the endpoint 148 * @return the URL to invoke 149 */ 150 public static String createURL(Exchange exchange, HttpEndpoint endpoint) { 151 String uri = null; 152 if (!(endpoint.isBridgeEndpoint())) { 153 uri = exchange.getIn().getHeader(Exchange.HTTP_URI, String.class); 154 } 155 if (uri == null) { 156 uri = endpoint.getHttpUri().toASCIIString(); 157 } 158 159 // resolve placeholders in uri 160 try { 161 uri = exchange.getContext().resolvePropertyPlaceholders(uri); 162 } catch (Exception e) { 163 throw new RuntimeExchangeException("Cannot resolve property placeholders with uri: " + uri, exchange, e); 164 } 165 166 // append HTTP_PATH to HTTP_URI if it is provided in the header 167 String path = exchange.getIn().getHeader(Exchange.HTTP_PATH, String.class); 168 if (path != null) { 169 if (path.startsWith("/")) { 170 URI baseURI; 171 String baseURIString = exchange.getIn().getHeader(Exchange.HTTP_BASE_URI, String.class); 172 try { 173 if (baseURIString == null) { 174 if (exchange.getFromEndpoint() != null) { 175 baseURIString = exchange.getFromEndpoint().getEndpointUri(); 176 } else { 177 // will set a default one for it 178 baseURIString = "/"; 179 } 180 } 181 baseURI = new URI(baseURIString); 182 String basePath = baseURI.getRawPath(); 183 if (path.startsWith(basePath)) { 184 path = path.substring(basePath.length()); 185 if (path.startsWith("/")) { 186 path = path.substring(1); 187 } 188 } else { 189 throw new RuntimeExchangeException("Cannot analyze the Exchange.HTTP_PATH header, due to: cannot find the right HTTP_BASE_URI", exchange); 190 } 191 } catch (Throwable t) { 192 throw new RuntimeExchangeException("Cannot analyze the Exchange.HTTP_PATH header, due to: " + t.getMessage(), exchange, t); 193 } 194 195 } 196 if (path.length() > 0) { 197 // make sure that there is exactly one "/" between HTTP_URI and 198 // HTTP_PATH 199 if (!uri.endsWith("/")) { 200 uri = uri + "/"; 201 } 202 uri = uri.concat(path); 203 } 204 } 205 return uri; 206 } 207 208 /** 209 * Creates the HttpMethod to use to call the remote server, often either its GET or POST. 210 * 211 * @param exchange the exchange 212 * @return the created method 213 */ 214 public static HttpMethods createMethod(Exchange exchange, HttpEndpoint endpoint, boolean hasPayload) { 215 // is a query string provided in the endpoint URI or in a header (header 216 // overrules endpoint) 217 String queryString = exchange.getIn().getHeader(Exchange.HTTP_QUERY, String.class); 218 if (queryString == null) { 219 queryString = endpoint.getHttpUri().getQuery(); 220 } 221 222 // compute what method to use either GET or POST 223 HttpMethods answer; 224 HttpMethods m = exchange.getIn().getHeader(Exchange.HTTP_METHOD, HttpMethods.class); 225 if (m != null) { 226 // always use what end-user provides in a header 227 answer = m; 228 } else if (queryString != null) { 229 // if a query string is provided then use GET 230 answer = HttpMethods.GET; 231 } else { 232 // fallback to POST if we have payload, otherwise GET 233 answer = hasPayload ? HttpMethods.POST : HttpMethods.GET; 234 } 235 236 return answer; 237 } 238 }