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