5

My requested path is:

localhost:8080/companies/12/accounts/35

My Rest Controller contains this function and I want to get companyId and accountId inside Filter.

@RequestMapping(value = "/companies/{companyId}/accounts/{accountId}", method = RequestMethod.PUT)
public Response editCompanyAccount(@PathVariable("companyId") long companyId, @PathVariable("accountId") long accountId,
@RequestBody @Validated CompanyAccountDto companyAccountDto,
                                       HttpServletRequest req) throws ErrorException, InvalidKeySpecException, NoSuchAlgorithmException

Is there any function that can be used in order to receive this information inside filter?

Ataur Rahman Munna
  • 3,887
  • 1
  • 23
  • 34
pik4
  • 1,283
  • 3
  • 21
  • 56
  • What does you mean by "inside Filter"? You already have them within the method. – dumitru Apr 20 '16 at 09:49
  • With this function you can get the whole path of URI. ((HttpServletRequest) req).getRequestURI() Is there any function that you can get only a PathVariable? – pik4 Apr 20 '16 at 09:54
  • Hi @pik4, please how where you able to solve this? – Enoobong Jun 22 '19 at 09:35
  • https://stackoverflow.com/questions/12249721/spring-mvc-3-how-to-get-path-variable-in-an-interceptor – David Apr 15 '20 at 16:27

4 Answers4

11
Map pathVariables = (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);  
String companyId = (String)pathVariables.get("companyId"); 
String accountId= (String)pathVariables.get("accountId");
Liam Mazy
  • 390
  • 3
  • 15
  • 3
    This is interesting, but only half the story. In order for your answer to work, the filter must have called `chain.doFilter(request, response);` already. Typically, http filters need to do things before getting to the controller. So while this answer has some merit, @ambwa has the right answer. – Ali H Nov 21 '18 at 14:44
5

If you are referring to the Spring web filter chain, you will have to manually parse the URL provided in the servlet request. This is due to the fact that filters are executed before the actual controller gets hold of the request, which then performs the mapping.

ambwa
  • 81
  • 4
  • 1
    Actually I want to get a PathVariable from HttpRequest. – pik4 Apr 20 '16 at 10:03
  • 1
    The PathVariable is included in your request URI and extracted when the controller maps it for further execution. If you really want the variable in the filter, you have to get it from the URI yourself. However, I do not see why you can't use the controller for handling the request. – ambwa Apr 20 '16 at 10:08
  • 1
    Because I want to call a function which check if user can access in this company. You can call this check function either into Controllers or into FIlter. I try to find an elegant way that can get a Path Variable, and if it is possible not with parsing. – pik4 Apr 20 '16 at 10:11
  • 1
    Maybe you should check out spring security then, which allows you to provide fine-grained access to resources based on user roles and various other authentication schemes. To me, it sounds like you are essentially trying to implement your own security. – ambwa Apr 20 '16 at 11:28
0

It's more suitable to do that inside a Spring Filter(an interceptor).To store the retrieved value in order to use it later in the controller or service part, consider using a Spring bean with the Scope request(request scope creates a bean instance for a single HTTP request). Below the interceptor code example:

@Component
public class RequestInterceptor implements Filter {

    private final RequestData requestData;

    public RequestInterceptor(RequestInfo requestInfo) {

        this.requestInfo = requestInfo;
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
            FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        //Get authorization
        var authorization = request.getHeader(HttpHeaders.AUTHORIZATION);

        //Get some path variables
        var pathVariables = request.getHttpServletMapping().getMatchValue();
        var partyId = pathVariables.substring(0, pathVariables.indexOf('/'));

        //Store in the scoped bean
        requestInfo.setPartyId(partyId);

        filterChain.doFilter(servletRequest, servletResponse);
    }
}

For safe access of the storing value in the RequestData bean, I advise to always use a ThreadLocal construct to hold the managed value:

@Component
@Scope(value = "request", proxyMode =  ScopedProxyMode.TARGET_CLASS)
public class RequestData {

    private final ThreadLocal<String> partyId = new ThreadLocal<>();

    public String getPartyId() {

        return partyId.get();
    }

    public void setPartyId(String partyId) {

        this.partyId.set(partyId);
    }
}
  • very nice, and you can also use `@RequestScope` annotation from `org.springframework.web.context.annotation.RequestScope` that already has `@Scope("request")` annotation :) – wkubasik Sep 09 '20 at 14:04
0

by adding Interceptor it would work. complete code to the problem : https://stackoverflow.com/a/65503332/2131816

Arun Pratap Singh
  • 3,428
  • 30
  • 23