Why is my tomcat valve not being invoked?

北城以北 提交于 2019-12-02 05:17:47

Turns out it is caused by a missing ROOT-directory in Tomcat's webapps-dir. I think that Tomcat does filter incoming requests rather rigorously at a very early point in time, even before any valves can handle and mess with the request.
And if there's no default context (i.e. no ROOT-dir) then Tomcat (thinks to) know(s) that a request to non-existing-webapp cannot succeed and thus does not even call the valve(s). With a default context Tomcat cannot know what will happen to the request and thus the valve gets its chance to intercept the request.

In versions 6(not sure what happens in earlier versions) - 8 Tomcat does not call Valve if it determines that redirect is required, so suprisingly Valves work reliably only when context is determined during mapping phase.

You can check the source code(and attach a debugger if you wish) of org.apache.catalina.connector.CoyoteAdapter class where the action happens

    // Parse and set Catalina and configuration specific
    // request parameters
    req.getRequestProcessor().setWorkerThreadName(THREAD_NAME.get());
    boolean postParseSuccess = postParseRequest(req, request, res, response);
    if (postParseSuccess) {
        //check valves if we support async
        request.setAsyncSupported(connector.getService().getContainer().getPipeline().isAsyncSupported());
        // Calling the container
        connector.getService().getContainer().getPipeline().getFirst().invoke(request, response);

As you can see Valves are called only in case postParseRequest returned true, which does not happen for example if Tomcat determines that it should return redirect during postParseRequest. Code determining that redirect is required:

    // Possible redirect
    MessageBytes redirectPathMB = request.getMappingData().redirectPath;
    if (!redirectPathMB.isNull()) {
        String redirectPath = URLEncoder.DEFAULT.encode(redirectPathMB.toString());
        String query = request.getQueryString();
        if (request.isRequestedSessionIdFromURL()) {
            // This is not optimal, but as this is not very common, it
            // shouldn't matter
            redirectPath = redirectPath + ";" +
                    SessionConfig.getSessionUriParamName(
                        request.getContext()) +
                "=" + request.getRequestedSessionId();
        }
        if (query != null) {
            // This is not optimal, but as this is not very common, it
            // shouldn't matter
            redirectPath = redirectPath + "?" + query;
        }
        response.sendRedirect(redirectPath);
        request.getContext().logAccess(request, response, 0, true);
        return false;
    }

In my case redirect was set in org.apache.catalina.mapper.Mapper.internalMapWrapper(...)

This may become a nuisance if you use RemoteIpValve as it causes Tomcat to send redirects using the wrong schema.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!