41
41
import javax .servlet .http .HttpServletRequest ;
42
42
import javax .servlet .http .HttpServletResponse ;
43
43
import javax .servlet .http .HttpSession ;
44
+ import javax .ws .rs .core .MultivaluedHashMap ;
44
45
46
+ import org .apache .cxf .jaxrs .model .URITemplate ;
45
47
import org .apache .ofbiz .base .location .FlexibleLocation ;
46
48
import org .apache .ofbiz .base .util .Debug ;
47
49
import org .apache .ofbiz .base .util .SSLUtil ;
@@ -183,7 +185,7 @@ public ConfigXMLReader.ControllerConfig getControllerConfig() {
183
185
}
184
186
185
187
/**
186
- * Find a collection of request maps in {@code ccfg} matching {@code req}.
188
+ * Finds a collection of request maps in {@code ccfg} matching {@code req}.
187
189
* Otherwise fall back to matching the {@code defaultReq} field in {@code ccfg}.
188
190
*
189
191
* @param ccfg The controller containing the current configuration
@@ -192,20 +194,23 @@ public ConfigXMLReader.ControllerConfig getControllerConfig() {
192
194
*/
193
195
static Collection <RequestMap > resolveURI (ControllerConfig ccfg , HttpServletRequest req ) {
194
196
Map <String , List <RequestMap >> requestMapMap = ccfg .getRequestMapMap ();
195
- Map <String , ConfigXMLReader .ViewMap > viewMapMap = ccfg .getViewMapMap ();
196
- String defaultRequest = ccfg .getDefaultRequest ();
197
- String path = req .getPathInfo ();
198
- String requestUri = getRequestUri (path );
199
- String viewUri = getOverrideViewUri (path );
200
- Collection <RequestMap > rmaps ;
201
- if (requestMapMap .containsKey (requestUri )
202
- // Ensure that overridden view exists.
203
- && (viewUri == null || viewMapMap .containsKey (viewUri ))) {
204
- rmaps = requestMapMap .get (requestUri );
205
- } else if (defaultRequest != null ) {
206
- rmaps = requestMapMap .get (defaultRequest );
207
- } else {
208
- rmaps = null ;
197
+ Collection <RequestMap > rmaps = resolveTemplateURI (requestMapMap , req );
198
+ if (rmaps .isEmpty ()) {
199
+ Map <String , ConfigXMLReader .ViewMap > viewMapMap = ccfg .getViewMapMap ();
200
+ String defaultRequest = ccfg .getDefaultRequest ();
201
+ String path = req .getPathInfo ();
202
+ String requestUri = getRequestUri (path );
203
+ String overrideViewUri = getOverrideViewUri (path );
204
+ if (requestMapMap .containsKey (requestUri )
205
+ // Ensure that overridden view exists.
206
+ && (overrideViewUri == null || viewMapMap .containsKey (overrideViewUri ))) {
207
+ rmaps = requestMapMap .get (requestUri );
208
+ req .setAttribute ("overriddenView" , overrideViewUri );
209
+ } else if (defaultRequest != null ) {
210
+ rmaps = requestMapMap .get (defaultRequest );
211
+ } else {
212
+ rmaps = null ;
213
+ }
209
214
}
210
215
return rmaps != null ? rmaps : Collections .emptyList ();
211
216
}
@@ -234,6 +239,33 @@ static Optional<RequestMap> resolveMethod(String method, Collection<RequestMap>
234
239
}
235
240
}
236
241
242
+ /**
243
+ * Finds the request maps matching a segmented path.
244
+ *
245
+ * <p>A segmented path can match request maps where the {@code uri} attribute
246
+ * contains an URI template like in the {@code foo/bar/{baz}} example.
247
+ *
248
+ * @param rMapMap the map associating URIs to a list of request maps corresponding to different HTTP methods
249
+ * @param request the HTTP request to match
250
+ * @return a collection of request maps which might be empty but not {@code null}
251
+ */
252
+ private static Collection <RequestMap > resolveTemplateURI (Map <String , List <RequestMap >> rMapMap ,
253
+ HttpServletRequest request ) {
254
+ // Retrieve the request path without the leading '/' character.
255
+ String path = request .getPathInfo ().substring (1 );
256
+ MultivaluedHashMap <String , String > vars = new MultivaluedHashMap <>();
257
+ for (Map .Entry <String , List <RequestMap >> entry : rMapMap .entrySet ()) {
258
+ URITemplate uriTemplate = URITemplate .createExactTemplate (entry .getKey ());
259
+ // Check if current path the URI template exactly.
260
+ if (uriTemplate .match (path , vars ) && vars .getFirst ("FINAL_MATCH_GROUP" ).equals ("/" )) {
261
+ // Set attributes from template variables to be used in context.
262
+ uriTemplate .getVariables ().forEach (var -> request .setAttribute (var , vars .getFirst (var )));
263
+ return entry .getValue ();
264
+ }
265
+ }
266
+ return Collections .emptyList ();
267
+ }
268
+
237
269
public void doRequest (HttpServletRequest request , HttpServletResponse response , String chain ,
238
270
GenericValue userLogin , Delegator delegator ) throws RequestHandlerException , RequestHandlerExceptionAllowExternalRequests {
239
271
@@ -269,7 +301,6 @@ public void doRequest(HttpServletRequest request, HttpServletResponse response,
269
301
270
302
String path = request .getPathInfo ();
271
303
String requestUri = getRequestUri (path );
272
- String overrideViewUri = getOverrideViewUri (path );
273
304
274
305
Collection <RequestMap > rmaps = resolveURI (ccfg , request );
275
306
if (rmaps .isEmpty ()) {
@@ -287,8 +318,11 @@ public void doRequest(HttpServletRequest request, HttpServletResponse response,
287
318
throw new RequestHandlerExceptionAllowExternalRequests ();
288
319
}
289
320
}
321
+ // The "overriddenView" attribute is set by resolveURI when necessary.
322
+ String overrideViewUri = (String ) request .getAttribute ("overriddenView" );
290
323
291
- String method = request .getMethod ();
324
+ String restMethod = request .getParameter ("restMethod" );
325
+ String method = (restMethod != null ) ? restMethod : request .getMethod ();
292
326
RequestMap requestMap = resolveMethod (method , rmaps ).orElseThrow (() -> {
293
327
String msg = UtilProperties .getMessage ("WebappUiLabels" , "RequestMethodNotMatchConfig" ,
294
328
UtilMisc .toList (requestUri , method ), UtilHttp .getLocale (request ));
0 commit comments