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 }