1
2
3
4
5
6
7 package org.mule.transport.http;
8
9 import org.mule.DefaultMuleMessage;
10 import org.mule.MessageExchangePattern;
11 import org.mule.api.MuleContext;
12 import org.mule.api.MuleMessage;
13 import org.mule.api.transport.MessageTypeNotSupportedException;
14 import org.mule.transport.AbstractMuleMessageFactory;
15 import org.mule.util.CaseInsensitiveHashMap;
16 import org.mule.util.IOUtils;
17 import org.mule.util.PropertiesUtils;
18 import org.mule.util.StringUtils;
19
20 import java.io.IOException;
21 import java.io.InputStream;
22 import java.net.URI;
23 import java.net.URISyntaxException;
24 import java.util.HashMap;
25 import java.util.Map;
26
27 import org.apache.commons.httpclient.Cookie;
28 import org.apache.commons.httpclient.Header;
29 import org.apache.commons.httpclient.HeaderElement;
30 import org.apache.commons.httpclient.HttpMethod;
31 import org.apache.commons.httpclient.HttpVersion;
32 import org.apache.commons.httpclient.NameValuePair;
33 import org.apache.commons.httpclient.cookie.MalformedCookieException;
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36
37 public class HttpMuleMessageFactory extends AbstractMuleMessageFactory
38 {
39 private static Log log = LogFactory.getLog(HttpMuleMessageFactory.class);
40
41 private boolean enableCookies = false;
42 private String cookieSpec;
43 private MessageExchangePattern exchangePattern = MessageExchangePattern.REQUEST_RESPONSE;
44
45 public HttpMuleMessageFactory(MuleContext context)
46 {
47 super(context);
48 }
49
50 @Override
51 protected Class<?>[] getSupportedTransportMessageTypes()
52 {
53 return new Class[]{HttpRequest.class, HttpMethod.class};
54 }
55
56 @Override
57 protected Object extractPayload(Object transportMessage, String encoding) throws Exception
58 {
59 if (transportMessage instanceof HttpRequest)
60 {
61 return extractPayloadFromHttpRequest((HttpRequest) transportMessage);
62 }
63 else if (transportMessage instanceof HttpMethod)
64 {
65 return extractPayloadFromHttpMethod((HttpMethod) transportMessage);
66 }
67 else
68 {
69
70 throw new MessageTypeNotSupportedException(transportMessage, getClass());
71 }
72 }
73
74 protected Object extractPayloadFromHttpRequest(HttpRequest httpRequest) throws IOException
75 {
76 Object body = httpRequest.getBody();
77
78
79 if (body == null)
80 {
81 body = httpRequest.getRequestLine().getUri();
82 }
83 else
84 {
85
86
87
88
89 if (!exchangePattern.hasResponse())
90 {
91 log.debug("Reading HTTP POST InputStream into byte[] for asynchronous messaging.");
92 body = IOUtils.toByteArray((InputStream) body);
93 }
94 }
95
96 return body;
97 }
98
99 protected Object extractPayloadFromHttpMethod(HttpMethod httpMethod) throws IOException
100 {
101 InputStream body = httpMethod.getResponseBodyAsStream();
102 if (body != null)
103 {
104 return new ReleasingInputStream(body, httpMethod);
105 }
106 else
107 {
108 return StringUtils.EMPTY;
109 }
110 }
111
112 @Override
113 protected void addProperties(DefaultMuleMessage message, Object transportMessage) throws Exception
114 {
115 String method;
116 HttpVersion httpVersion;
117 String uri;
118 String statusCode = null;
119 Map<String, Object> headers;
120
121 if (transportMessage instanceof HttpRequest)
122 {
123 HttpRequest httpRequest = (HttpRequest) transportMessage;
124 method = httpRequest.getRequestLine().getMethod();
125 httpVersion = httpRequest.getRequestLine().getHttpVersion();
126 uri = httpRequest.getRequestLine().getUri();
127 headers = convertHeadersToMap(httpRequest.getHeaders(), uri);
128 convertMultiPartHeaders(headers);
129 }
130 else if (transportMessage instanceof HttpMethod)
131 {
132 HttpMethod httpMethod = (HttpMethod) transportMessage;
133 method = httpMethod.getName();
134 httpVersion = HttpVersion.parse(httpMethod.getStatusLine().getHttpVersion());
135 uri = httpMethod.getURI().toString();
136 statusCode = String.valueOf(httpMethod.getStatusCode());
137 headers = convertHeadersToMap(httpMethod.getResponseHeaders(), uri);
138 }
139 else
140 {
141
142 throw new MessageTypeNotSupportedException(transportMessage, getClass());
143 }
144
145 rewriteConnectionAndKeepAliveHeaders(headers);
146
147 headers = processIncomingHeaders(headers);
148
149
150 addUriParamsAsHeaders(headers, uri);
151
152 headers.put(HttpConnector.HTTP_METHOD_PROPERTY, method);
153 headers.put(HttpConnector.HTTP_REQUEST_PROPERTY, uri);
154 headers.put(HttpConnector.HTTP_VERSION_PROPERTY, httpVersion.toString());
155 if (enableCookies)
156 {
157 headers.put(HttpConnector.HTTP_COOKIE_SPEC_PROPERTY, cookieSpec);
158 }
159
160 if (statusCode != null)
161 {
162 headers.put(HttpConnector.HTTP_STATUS_PROPERTY, statusCode);
163 }
164
165 message.addInboundProperties(headers);
166
167
168
169 initEncoding(message, headers);
170 }
171
172 protected Map<String, Object> processIncomingHeaders(Map<String, Object> headers) throws Exception
173 {
174 Map<String, Object> outHeaders = new HashMap<String, Object>();
175
176 for (String headerName : headers.keySet())
177 {
178 Object headerValue = headers.get(headerName);
179
180
181 if (headerName.startsWith("X-MULE"))
182 {
183 headerName = headerName.substring(2);
184 }
185
186
187 outHeaders.put(headerName, headerValue);
188 }
189
190 return outHeaders;
191 }
192
193 Map<String, Object> convertHeadersToMap(Header[] headersArray, String uri)
194 throws URISyntaxException
195 {
196 Map<String, Object> headersMap = new CaseInsensitiveHashMap();
197 for (int i = 0; i < headersArray.length; i++)
198 {
199 final Header header = headersArray[i];
200
201
202 if (HttpConnector.HTTP_COOKIES_PROPERTY.equals(header.getName())
203 || HttpConstants.HEADER_COOKIE.equals(header.getName()))
204 {
205 putCookieHeaderInMapAsAServer(headersMap, header, uri);
206 }
207 else if (HttpConstants.HEADER_COOKIE_SET.equals(header.getName()))
208 {
209 putCookieHeaderInMapAsAClient(headersMap, header, uri);
210 }
211 else
212 {
213 if (headersMap.containsKey(header.getName()))
214 {
215 if (headersMap.get(header.getName()) instanceof String)
216 {
217
218 headersMap.put(header.getName(),
219 headersMap.get(header.getName()) + "," + header.getValue());
220 }
221 else
222 {
223
224 headersMap.put(header.getName(), header.getValue());
225 }
226 }
227 else
228 {
229 headersMap.put(header.getName(), header.getValue());
230 }
231 }
232 }
233 return headersMap;
234 }
235
236 private void putCookieHeaderInMapAsAClient(Map<String, Object> headersMap, final Header header, String uri)
237 throws URISyntaxException
238 {
239 try
240 {
241 final Cookie[] newCookies = CookieHelper.parseCookiesAsAClient(header.getValue(), cookieSpec,
242 new URI(uri));
243 final Object preExistentCookies = headersMap.get(HttpConstants.HEADER_COOKIE_SET);
244 final Object mergedCookie = CookieHelper.putAndMergeCookie(preExistentCookies, newCookies);
245 headersMap.put(HttpConstants.HEADER_COOKIE_SET, mergedCookie);
246 }
247 catch (MalformedCookieException e)
248 {
249 log.warn("Received an invalid cookie: " + header, e);
250 }
251 }
252
253 private void putCookieHeaderInMapAsAServer(Map<String, Object> headersMap, final Header header, String uri)
254 throws URISyntaxException
255 {
256 if (enableCookies)
257 {
258 Cookie[] newCookies = CookieHelper.parseCookiesAsAServer(header.getValue(), new URI(uri));
259 if (newCookies.length > 0)
260 {
261 Object oldCookies = headersMap.get(HttpConnector.HTTP_COOKIES_PROPERTY);
262 Object mergedCookies = CookieHelper.putAndMergeCookie(oldCookies, newCookies);
263 headersMap.put(HttpConnector.HTTP_COOKIES_PROPERTY, mergedCookies);
264 }
265 }
266 }
267
268 private void initEncoding(MuleMessage message, Map<String, Object> headers)
269 {
270 Object contentType = headers.get(HttpConstants.HEADER_CONTENT_TYPE);
271 if (contentType != null)
272 {
273
274
275 Header contentTypeHeader = new Header(HttpConstants.HEADER_CONTENT_TYPE,
276 contentType.toString());
277 HeaderElement values[] = contentTypeHeader.getElements();
278 if (values.length == 1)
279 {
280 NameValuePair param = values[0].getParameterByName("charset");
281 if (param != null)
282 {
283 message.setEncoding(param.getValue());
284 }
285 }
286 }
287 }
288
289 private void rewriteConnectionAndKeepAliveHeaders(Map<String, Object> headers)
290 {
291
292 String headerValue;
293 if (!isHttp11(headers))
294 {
295 String connection = (String) headers.get(HttpConstants.HEADER_CONNECTION);
296 if ((connection != null) && connection.equalsIgnoreCase("close"))
297 {
298 headerValue = Boolean.FALSE.toString();
299 }
300 else
301 {
302 headerValue = Boolean.TRUE.toString();
303 }
304 }
305 else
306 {
307 headerValue = (headers.get(HttpConstants.HEADER_CONNECTION) != null
308 ? Boolean.TRUE.toString()
309 : Boolean.FALSE.toString());
310 }
311
312 headers.put(HttpConstants.HEADER_CONNECTION, headerValue);
313 headers.put(HttpConstants.HEADER_KEEP_ALIVE, headerValue);
314 }
315
316 private boolean isHttp11(Map<String, Object> headers)
317 {
318 String httpVersion = (String) headers.get(HttpConnector.HTTP_VERSION_PROPERTY);
319 return !HttpConstants.HTTP10.equalsIgnoreCase(httpVersion);
320 }
321
322 protected void addUriParamsAsHeaders(Map headers, String uri)
323 {
324 int i = uri.indexOf("?");
325 if (i > -1)
326 {
327 headers.putAll(PropertiesUtils.getPropertiesFromQueryString(uri.substring(i + 1)));
328 }
329 }
330
331 protected void convertMultiPartHeaders(Map<String, Object> headers)
332 {
333
334 }
335
336 public void setEnableCookies(boolean enableCookies)
337 {
338 this.enableCookies = enableCookies;
339 }
340
341 public void setCookieSpec(String cookieSpec)
342 {
343 this.cookieSpec = cookieSpec;
344 }
345
346 public void setExchangePattern(MessageExchangePattern mep)
347 {
348 exchangePattern = mep;
349 }
350 }