Expand my Community achievements bar.

Don’t miss the AEM Skill Exchange in SF on Nov 14—hear from industry leaders, learn best practices, and enhance your AEM strategy with practical tips.

@SlingServletPaths, is there a way to specify wild card?

Avatar

Level 9

We want to build a single proxy servlet which will serve a number of different paths, such as

/api/register

/api/player/1234/

/api/player/12312/transactions

 

Basically, any and every path below /api/

 

Currently we are using this pattern, which only allows a single fixed path:

@Slf4j
@Component(service = { Servlet.class })
@SlingServletPaths(value="/bin/somepath")
private class MyServlet extends SlingAllMethodsServlet

 

Any suggestions on how to do this?

We are using AEM cloud, so try to avoid anything which would require CRXDE

 

I found a potential solution here, but it wont compile unfortunately (the annotations etc are no longer available):

https://stackoverflow.com/a/41990177/1072187

 

9 Replies

Avatar

Level 9

you can put comma separated path (make sure, its absolute path) there as it process as string array.

Avatar

Level 9

Thanks for the reply, but there are random IDs in the URLs, so its not possible to list them all out.

Avatar

Community Advisor

@TB3dock we cannot register a servlet using pattern. It accepts String or Array of Strings or Vector of Strings.
you can refer to this documentation https://sling.apache.org/documentation/the-sling-engine/servlets.html#servlet-registration 
If you want multiple paths to be registered try to make use of selectors and extensions while registering servlet.

Hope this helps,
Krishna

Avatar

Level 5

In Sling servlets cannot accept the patterns. It is not similar to Spring boot APIs, Here we need to have single or multiple paths and utilize the selectors and suffixes

Please find the official documentation on sling and the properties that can be used while registering servlet.

https://sling.apache.org/documentation/the-sling-engine/servlets.html

Avatar

Level 9

So it looks like AEM doesnt have a way to support a servlet which can handle URLs with IDs in them, a very common pattern for REST APIs. we cant change the API, its used from a 3rd party.

 

We can think of one workaround this limitation, by using apache rewrite rules to take the api we need to honour, and rewriting it with a dummy extension. 

 

So /api/3435534/player becomes /api/3435534/player.apihack, then we can create a servlet which uses .apihack as an extension.

 

There doesn't seem to be an annotation for this:

     @SlingServletSelectors("apihack")  nor

      @SlingServletExtensions("apihack")

seem to exist?

Avatar

Employee Advisor

As already mentioned, Sling Servlets are mounted to a single path, and even that does not fit into the "resource first" approach of Sling.

 

But you can register your servlet to /api and then read the remaining "parameters" via suffixes. Check the documentation at https://sling.apache.org/documentation/the-sling-engine/url-decomposition.html

Avatar

Level 9

Thanks Jorg.  "you can register your servlet to /api"

are you saying we can use

 

@SlingServletPaths(value="/api")

 

And this will match /api/123/something/345345 ?  I.e. its actually matching "/api.*"?

If so, problem solved!  

 

I dont need selectors, I just need to take the entire URL and pass it on as a proxy, using filters to modify the request/response as needed.

 

Thinking of using a semaphore to limit number of active requests in case of DDoS. Usually, we would use a proper WAF like DataDome, but unfortunately AEM cloud does not allow this to be used.

Avatar

Level 9

Hmm, this doesnt seem to work.

MyProxy.java

 

 

(service = {Servlet.class})
@SlingServletPaths(value = "/bin/myProxy")
public class MyProxy extends SlingAllMethodsServlet {

 

 

 

filters.any

 

 

/0200 { /type "allow" /url "/bin/myProxy/*"}

 

 

 

URL

GET http://localhost:4503/bin/myProxy/core/connect/tokenvalidation?token=xx

 

response:

<h1>Resource at '/bin/myProxy/core/connect/tokenValidation' not found: No resource found</h1>
 
however, If I do this:
 
 
Then the servlet does get called, but this is not what we need.  We need to write a proxy which can take any trailing path and its params, so we can proxy it.  e.g. we might have /someting/23423/something?asdf=asdf were 23423 is different every call.