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