1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.cms.util;
35
36 import java.io.IOException;
37 import java.net.MalformedURLException;
38 import java.net.URL;
39
40 import javax.servlet.http.HttpServletRequest;
41 import javax.servlet.http.HttpServletResponse;
42
43 import org.apache.commons.lang3.ClassUtils;
44 import org.apache.commons.lang3.StringUtils;
45 import org.apache.http.HttpEntity;
46 import org.apache.http.client.methods.CloseableHttpResponse;
47 import org.apache.http.client.methods.HttpGet;
48 import org.apache.http.impl.client.CloseableHttpClient;
49 import org.apache.http.impl.client.HttpClients;
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53
54
55
56
57 public class RequestDispatchUtil {
58
59 private static final Logger log = LoggerFactory.getLogger(RequestDispatchUtil.class);
60
61 public static final String REDIRECT_PREFIX = "redirect:";
62 public static final String PERMANENT_PREFIX = "permanent:";
63 public static final String FORWARD_PREFIX = "forward:";
64 public static final String PROXY_PREFIX = "proxy:";
65
66
67
68
69 public static boolean dispatch(String targetUri, HttpServletRequest request, HttpServletResponse response) {
70
71 if (targetUri == null) {
72 return false;
73 }
74
75 if (targetUri.startsWith(REDIRECT_PREFIX)) {
76 String redirectUrl = StringUtils.substringAfter(targetUri, REDIRECT_PREFIX);
77 try {
78
79 if (isInternal(redirectUrl) && !StringUtils.startsWith(redirectUrl, request.getContextPath())) {
80 redirectUrl = request.getContextPath() + redirectUrl;
81 }
82
83 response.sendRedirect(response.encodeRedirectURL(redirectUrl));
84
85 } catch (IOException e) {
86 log.error("Failed to redirect to {}:{}", targetUri, e.getMessage());
87 }
88 return true;
89 }
90
91 if (targetUri.startsWith(PERMANENT_PREFIX)) {
92 String permanentUrl = StringUtils.substringAfter(targetUri, PERMANENT_PREFIX);
93 try {
94
95 if (isInternal(permanentUrl)) {
96 if (isUsingStandardPort(request)) {
97 permanentUrl = new URL(
98 request.getScheme(),
99 request.getServerName(),
100 request.getContextPath() + permanentUrl).toExternalForm();
101 } else {
102 permanentUrl = new URL(
103 request.getScheme(),
104 request.getServerName(),
105 request.getServerPort(),
106 request.getContextPath() + permanentUrl).toExternalForm();
107 }
108 }
109
110 response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
111 response.setHeader("Location", permanentUrl);
112
113 } catch (MalformedURLException e) {
114 log.error("Failed to create permanent url to redirect to {}:{}", targetUri, e.getMessage());
115 }
116 return true;
117 }
118
119 if (targetUri.startsWith(FORWARD_PREFIX)) {
120 String forwardUrl = StringUtils.substringAfter(targetUri, FORWARD_PREFIX);
121 try {
122 request.getRequestDispatcher(forwardUrl).forward(request, response);
123 } catch (Exception e) {
124 log.error("Failed to forward to {} - {}:{}", forwardUrl, ClassUtils.getShortClassName(e.getClass()), e.getMessage());
125 }
126 return true;
127 }
128
129 if (targetUri.startsWith(PROXY_PREFIX)) {
130 String forwardUrl = StringUtils.substringAfter(targetUri, PROXY_PREFIX);
131 forwardToExternalURL(response, forwardUrl);
132 return true;
133 }
134
135 return false;
136 }
137
138 private static void forwardToExternalURL(HttpServletResponse response, String forwardUrl) {
139 CloseableHttpClient httpClient = HttpClients.createDefault();
140
141 try {
142 HttpGet req = new HttpGet(forwardUrl);
143
144 CloseableHttpResponse resp = httpClient.execute(req);
145 try {
146 HttpEntity entity = resp.getEntity();
147 response.setStatus(resp.getStatusLine().getStatusCode());
148 if (entity != null) {
149 response.setContentType(entity.getContentType().getValue());
150 entity.writeTo(response.getOutputStream());
151 }
152 } finally {
153 resp.close();
154 }
155 } catch (Exception e) {
156 log.error("Failed to forward to external URL {} - {}:{}", forwardUrl, ClassUtils.getShortClassName(e.getClass()), e.getMessage());
157 } finally {
158 try {
159 httpClient.close();
160 } catch (IOException e) {
161 }
162 }
163 }
164
165 private static boolean isUsingStandardPort(HttpServletRequest request) {
166 String requestScheme = request.getScheme();
167 int serverPort = request.getServerPort();
168 return (serverPort == 80 && "http".equals(requestScheme)) || (serverPort == 443 && "https".equals(requestScheme));
169 }
170
171 private static boolean isInternal(String url) {
172 return !url.startsWith("http://") && !url.startsWith("https://");
173 }
174 }