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.RuntimeCamelException; 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 // append HTTP_PATH to HTTP_URI if it is provided in the header 160 String path = exchange.getIn().getHeader(Exchange.HTTP_PATH, String.class); 161 if (path != null) { 162 if (path.startsWith("/")) { 163 URI baseURI; 164 String baseURIString = exchange.getIn().getHeader(Exchange.HTTP_BASE_URI, String.class); 165 try { 166 if (baseURIString == null) { 167 if (exchange.getFromEndpoint() != null) { 168 baseURIString = exchange.getFromEndpoint().getEndpointUri(); 169 } else { 170 // will set a default one for it 171 baseURIString = "/"; 172 } 173 } 174 baseURI = new URI(baseURIString); 175 String basePath = baseURI.getRawPath(); 176 if (path.startsWith(basePath)) { 177 path = path.substring(basePath.length()); 178 if (path.startsWith("/")) { 179 path = path.substring(1); 180 } 181 } else { 182 throw new RuntimeCamelException("Cannot analyze the Exchange.HTTP_PATH header, due to: cannot find the right HTTP_BASE_URI"); 183 } 184 } catch (Throwable t) { 185 throw new RuntimeCamelException("Cannot analyze the Exchange.HTTP_PATH header, due to: " 186 + t.getMessage(), t); 187 } 188 189 } 190 if (path.length() > 0) { 191 // make sure that there is exactly one "/" between HTTP_URI and 192 // HTTP_PATH 193 if (!uri.endsWith("/")) { 194 uri = uri + "/"; 195 } 196 uri = uri.concat(path); 197 } 198 } 199 return uri; 200 } 201 202 /** 203 * Creates the HttpMethod to use to call the remote server, often either its GET or POST. 204 * 205 * @param exchange the exchange 206 * @return the created method 207 */ 208 public static HttpMethods createMethod(Exchange exchange, HttpEndpoint endpoint, boolean hasPayload) { 209 // is a query string provided in the endpoint URI or in a header (header 210 // overrules endpoint) 211 String queryString = exchange.getIn().getHeader(Exchange.HTTP_QUERY, String.class); 212 if (queryString == null) { 213 queryString = endpoint.getHttpUri().getQuery(); 214 } 215 216 // compute what method to use either GET or POST 217 HttpMethods answer; 218 HttpMethods m = exchange.getIn().getHeader(Exchange.HTTP_METHOD, HttpMethods.class); 219 if (m != null) { 220 // always use what end-user provides in a header 221 answer = m; 222 } else if (queryString != null) { 223 // if a query string is provided then use GET 224 answer = HttpMethods.GET; 225 } else { 226 // fallback to POST if we have payload, otherwise GET 227 answer = hasPayload ? HttpMethods.POST : HttpMethods.GET; 228 } 229 230 return answer; 231 } 232 }