1 package nginx.unit;
2 
3 import java.util.List;
4 import java.util.Map;
5 
6 import javax.servlet.DispatcherType;
7 import javax.servlet.MultipartConfigElement;
8 import javax.servlet.RequestDispatcher;
9 import javax.servlet.ServletRequest;
10 import javax.servlet.http.HttpServletRequest;
11 
12 import org.eclipse.jetty.util.MultiMap;
13 import org.eclipse.jetty.util.UrlEncoded;
14 
15 public class ForwardRequestWrapper implements DynamicPathRequest
16 {
17     private final Request request_;
18 
19     private final boolean keep_attrs;
20 
21     private final String orig_filter_path;
22     private final String orig_servlet_path;
23     private final String orig_path_info;
24     private final String orig_uri;
25     private final String orig_context_path;
26     private final String orig_query;
27 
28     private final MultipartConfigElement orig_multipart_config;
29 
30     private final DispatcherType orig_dtype;
31 
32     private MultiMap<String> orig_parameters;
33 
ForwardRequestWrapper(ServletRequest request)34     public ForwardRequestWrapper(ServletRequest request)
35     {
36         if (request instanceof Request) {
37             request_ = (Request) request;
38         } else {
39             request_ = (Request) request.getAttribute(Request.BARE);
40         }
41 
42         keep_attrs = request_.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI) != null;
43 
44         orig_dtype = request_.getDispatcherType();
45 
46         orig_filter_path = request_.getFilterPath();
47         orig_servlet_path = request_.getServletPath();
48         orig_path_info = request_.getPathInfo();
49         orig_uri = request_.getRequestURI();
50         orig_context_path = request_.getContextPath();
51         orig_query = request_.getQueryString();
52 
53         orig_multipart_config = request_.getMultipartConfig();
54     }
55 
56     @Override
setDispatcherType(DispatcherType type)57     public void setDispatcherType(DispatcherType type)
58     {
59         request_.setDispatcherType(type);
60 
61         /*
62             9.4.2 Forwarded Request Parameters
63             ...
64             Note that these attributes must always reflect the information in
65             the original request even under the situation that multiple
66             forwards and subsequent includes are called.
67          */
68 
69         if (keep_attrs) {
70             return;
71         }
72 
73         /*
74             9.4.2 Forwarded Request Parameters
75             ...
76             The values of these attributes must be equal to the return values
77             of the HttpServletRequest methods getRequestURI, getContextPath,
78             getServletPath, getPathInfo, getQueryString respectively, invoked
79             on the request object passed to the first servlet object in the
80             call chain that received the request from the client.
81          */
82 
83         request_.setAttribute_(RequestDispatcher.FORWARD_SERVLET_PATH, orig_servlet_path);
84         request_.setAttribute_(RequestDispatcher.FORWARD_PATH_INFO, orig_path_info);
85         request_.setAttribute_(RequestDispatcher.FORWARD_REQUEST_URI, orig_uri);
86         request_.setAttribute_(RequestDispatcher.FORWARD_CONTEXT_PATH, orig_context_path);
87         request_.setAttribute_(RequestDispatcher.FORWARD_QUERY_STRING, orig_query);
88     }
89 
90     @Override
setServletPath(String servlet_path, String path_info)91     public void setServletPath(String servlet_path, String path_info)
92     {
93         request_.setServletPath(servlet_path, path_info);
94     }
95 
96     @Override
setServletPath(String filter_path, String servlet_path, String path_info)97     public void setServletPath(String filter_path, String servlet_path, String path_info)
98     {
99         request_.setServletPath(filter_path, servlet_path, path_info);
100     }
101 
102     @Override
setRequestURI(String uri)103     public void setRequestURI(String uri)
104     {
105         request_.setRequestURI(uri);
106     }
107 
108     @Override
setQueryString(String query)109     public void setQueryString(String query)
110     {
111         if (query != null) {
112             orig_parameters = request_.getParameters();
113 
114             MultiMap<String> parameters = new MultiMap<>();
115             UrlEncoded.decodeUtf8To(query, parameters);
116 
117             for (Map.Entry<String, List<String>> e: orig_parameters.entrySet()) {
118                 parameters.addValues(e.getKey(), e.getValue());
119             }
120 
121             request_.setParameters(parameters);
122 
123             request_.setQueryString(query);
124         }
125     }
126 
127     @Override
getFilterPath()128     public String getFilterPath()
129     {
130         return request_.getFilterPath();
131     }
132 
setMultipartConfig(MultipartConfigElement mce)133     public void setMultipartConfig(MultipartConfigElement mce)
134     {
135         request_.setMultipartConfig(mce);
136     }
137 
close()138     public void close()
139     {
140         request_.setDispatcherType(orig_dtype);
141 
142         request_.setRequestURI(orig_uri);
143         request_.setServletPath(orig_filter_path, orig_servlet_path, orig_path_info);
144         request_.setQueryString(orig_query);
145 
146         if (orig_parameters != null) {
147             request_.setParameters(orig_parameters);
148         }
149 
150         request_.setMultipartConfig(orig_multipart_config);
151 
152         if (keep_attrs) {
153             return;
154         }
155 
156         request_.setAttribute_(RequestDispatcher.FORWARD_SERVLET_PATH, null);
157         request_.setAttribute_(RequestDispatcher.FORWARD_PATH_INFO, null);
158         request_.setAttribute_(RequestDispatcher.FORWARD_REQUEST_URI, null);
159         request_.setAttribute_(RequestDispatcher.FORWARD_CONTEXT_PATH, null);
160         request_.setAttribute_(RequestDispatcher.FORWARD_QUERY_STRING, null);
161     }
162 }
163