You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Andy Pont <an...@wonksw.tech> on 2023/08/11 07:52:04 UTC

Forwarding request to a different servlet

Hello!

We have a commercial application that runs under Tomcat 8.5.65 (on 
Windows Server 2019).  In the tomcat/webapps directory there are the 
following three directories (names changed):

backend
frontend
ROOT

The “frontend” directory contains the UI for the commercial application 
and is, as far as I can tell, all just HTML, JavaScript, etc.  The 
“backend” directory contains the parts of the system that do the bulk of 
the work and appear to be mainly .jsp files.

Amongst other things, the “backend” handles a URL 
https://<server_name>/backend/rest/abc/xx where “xx” represents a number 
that tells it what to act upon.

I have started developing a new servlet which handles POST requests to 
the URL: https://<server_name>/plugins/abc/xx.  In some cases (based on 
a values in the request body), the servlet will process things itself 
and generate its own response.   For certain cases it just needs to 
forward the request on to corresponding “backend” URL and then pass the 
response back.

I assumed that .forward(request, response) on a RequestDispatcher would 
be what I needed to use.  I have tried every combination of 
getServletContext() and getRequestDispatcher() I can think of or have 
found on the internet but it always fails with an HTTP error 404.  This 
is because the URL that it is being forwarded to always has a rogue 
“plugins” in it, i.e. https://<server_name>/plugins/backend/rest/abc/xx.

I suspect the solution is simple but I am new to Tomcat and developing 
servlets and probably missing something obvious.  Any guidance would be 
much appreciated.

-Andy.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Forwarding request to a different servlet

Posted by "Terence M. Bandoian" <te...@tmbsw.com>.
Hi, Andy-

I'd suggest looking at:
ServletContext.getContext

and comparing:
ServletContext.getRequestDispatcher with
ServletRequest.getRequestDispatcher

Hope that helps.

-Terence Bandoian

On 8/11/2023 2:52 AM, Andy Pont wrote:
> Hello!
>
> We have a commercial application that runs under Tomcat 8.5.65 (on 
> Windows Server 2019).  In the tomcat/webapps directory there are the 
> following three directories (names changed):
>
> backend
> frontend
> ROOT
>
> The “frontend” directory contains the UI for the commercial 
> application and is, as far as I can tell, all just HTML, JavaScript, 
> etc.  The “backend” directory contains the parts of the system that do 
> the bulk of the work and appear to be mainly .jsp files.
>
> Amongst other things, the “backend” handles a URL 
> https://<server_name>/backend/rest/abc/xx where “xx” represents a 
> number that tells it what to act upon.
>
> I have started developing a new servlet which handles POST requests to 
> the URL: https://<server_name>/plugins/abc/xx. In some cases (based on 
> a values in the request body), the servlet will process things itself 
> and generate its own response.   For certain cases it just needs to 
> forward the request on to corresponding “backend” URL and then pass 
> the response back.
>
> I assumed that .forward(request, response) on a RequestDispatcher 
> would be what I needed to use.  I have tried every combination of 
> getServletContext() and getRequestDispatcher() I can think of or have 
> found on the internet but it always fails with an HTTP error 404.  
> This is because the URL that it is being forwarded to always has a 
> rogue “plugins” in it, i.e. 
> https://<server_name>/plugins/backend/rest/abc/xx.
>
> I suspect the solution is simple but I am new to Tomcat and developing 
> servlets and probably missing something obvious.  Any guidance would 
> be much appreciated.
>
> -Andy.
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>

Re: Forwarding request to a different servlet

Posted by Andy Pont <an...@wonksw.tech>.
Chris wrote...

>So it looks like the backend service IS being called, but rejecting the request because of the "UserAgent" object complaining about it.
>
>I would log the User-Agent header from the request in your front-end before the RequestDispatcher.forward() call, and if possible, also log it in your backend service just before the "return false”.
I created (copied from the internet) a logging filter implementation for 
dumping the request and everything in that looked correct.  I then went 
for the option of potentially upsetting the user base by enabling all 
logging options on all of the backend’s classes.  It appears that it was 
down to me being an idiot!

In my servlet there is code that says:

ServletContext myContext = request.getServletContext();
ServletContext backendContext = myContext.getContext(“/backend”);

When I was creating the RequestDispatcher to forward the request I was 
including the “/backend” on the front of the URL.  Turns out it wasn’t 
needed and was upsetting some URL filtering!

-Andy.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Forwarding request to a different servlet

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Andy,

On 8/15/23 03:32, Andy Pont wrote:
> Chris wrote…
> 
>> The .forward() should keep all request headers (and many other things) 
>> in-tact. You might want to log some things in plugins/whatever to see 
>> what is being done.
>>
>> You should be using the *same objects* your servlet got for the 
>> request and response when calling RequestDispatcher.forward(). You can 
>> "wrap" them if necessary to make certain modifications.
> I have put the relevant parts of the source code onto PasteBin [1].  If 
> anyone spots any stupid mistakes then please do let me know!
> 
> My code has some logging output in it but it doesn’t appear to be being 
> added into the log files which are owned and created by the existing 
> “backend”.  That is probably just down to me not having the correct 
> logger context.
> 
>> Yes, but I think you should not have to. What are the possible reasons 
>> for that specific 302 response? Are you *sure* it's complaining about 
>> the User-Agent string?
> The log file from the backend records which Java class the mesage has 
> come from so I am fairly confident I am looking in the correct class. 
> There appear to be two functions that output the error in the log and 
> which endup redirecting to permissionDenied.do [2].  I’m not sure which 
> one is being called but the check and end result appear to be the same 
> in both.
> 
> The UserAgent class that it references is complex (IMO) but as far as I 
> can tell it is only looking at the “user-agent” header.

So it looks like the backend service IS being called, but rejecting the 
request because of the "UserAgent" object complaining about it.

I would log the User-Agent header from the request in your front-end 
before the RequestDispatcher.forward() call, and if possible, also log 
it in your backend service just before the "return false".

-chris

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Forwarding request to a different servlet

Posted by Andy Pont <an...@wonksw.tech>.
Chris wrote…

>The .forward() should keep all request headers (and many other things) in-tact. You might want to log some things in plugins/whatever to see what is being done.
>
>You should be using the *same objects* your servlet got for the request and response when calling RequestDispatcher.forward(). You can "wrap" them if necessary to make certain modifications.
I have put the relevant parts of the source code onto PasteBin [1].  If 
anyone spots any stupid mistakes then please do let me know!

My code has some logging output in it but it doesn’t appear to be being 
added into the log files which are owned and created by the existing 
“backend”.  That is probably just down to me not having the correct 
logger context.

>Yes, but I think you should not have to. What are the possible reasons for that specific 302 response? Are you *sure* it's complaining about the User-Agent string?
The log file from the backend records which Java class the mesage has 
come from so I am fairly confident I am looking in the correct class.  
There appear to be two functions that output the error in the log and 
which endup redirecting to permissionDenied.do [2].  I’m not sure which 
one is being called but the check and end result appear to be the same 
in both.

The UserAgent class that it references is complex (IMO) but as far as I 
can tell it is only looking at the “user-agent” header.

-Andy.


1 - https://pastebin.com/yGmxtx6V
2 - https://pastebin.com/4q88V7Pp


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Forwarding request to a different servlet

Posted by Christopher Schultz <ch...@christopherschultz.net>.
Andy,

On 8/13/23 04:24, Andy Pont wrote:
> I wrote...
> 
>> Progress of sorts!  The request is now returning 302 instead of 404!
>>
>> Looking in the log files for the backend, it has a message that says 
>> “Robot requests must be rejected” and the 302 response is due to a 
>> redirect to a permission denied page.
>>
>> My understanding was the .forward() method didn’t change anything on 
>> route in either direction.
 >
> Using JD-GUI I have looked at the class that is generates the above 
> error message and it appears as the result of a check on the 
> “user-agent” setting.  I am now puzzled as what is being received by the 
> backend servlet is the same as if it is called directly without me 
> intercepting it.

The .forward() should keep all request headers (and many other things) 
in-tact. You might want to log some things in plugins/whatever to see 
what is being done.

You should be using the *same objects* your servlet got for the request 
and response when calling RequestDispatcher.forward(). You can "wrap" 
them if necessary to make certain modifications.

> The class I looked at contains a definition of a valid non-robot 
> user-agent string.  Is it possible to modify the request to use this 
> before forwarding it?

Yes, but I think you should not have to. What are the possible reasons 
for that specific 302 response? Are you *sure* it's complaining about 
the User-Agent string?

> If not, am I better creating a new request for 
> the backend and copy HTTP header and body content around as needed?

That will be a giant pain in the neck. Could this possibly be done with 
a redirect back through the client?

-chris

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Forwarding request to a different servlet

Posted by Andy Pont <an...@wonksw.tech>.
I wrote...

>Progress of sorts!  The request is now returning 302 instead of 404!
>
>Looking in the log files for the backend, it has a message that says “Robot requests must be rejected” and the 302 response is due to a redirect to a permission denied page.
>
>My understanding was the .forward() method didn’t change anything on route in either direction.
Using JD-GUI I have looked at the class that is generates the above 
error message and it appears as the result of a check on the 
“user-agent” setting.  I am now puzzled as what is being received by the 
backend servlet is the same as if it is called directly without me 
intercepting it.

The class I looked at contains a definition of a valid non-robot 
user-agent string.  Is it possible to modify the request to use this 
before forwarding it?  If not, am I better creating a new request for 
the backend and copy HTTP header and body content around as needed?
-Andy.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Forwarding request to a different servlet

Posted by Andy Pont <an...@wonksw.tech>.
Mark wrote...

>RequestDispatcher operates within a given ServletContext (web application).
>
>You are trying to do a cross-context dispatch - i.e. to another web application. To do this you will need to:
>
>- enable cross-context dispatch for the /plugins web application
>https://tomcat.apache.org/tomcat-8.5-doc/config/context.html
>   look for crossContext
>
>- then use code something like this:
>
>ServletContext current = request.getServletContext();
>ServletContext backend = current.getContext("/backend");
>RequestDispatcher rd = backend.getRequestDispatcher("/rest/abc/xx");
>rd.forward(request,response);
>
Progress of sorts!  The request is now returning 302 instead of 404!

Looking in the log files for the backend, it has a message that says 
“Robot requests must be rejected” and the 302 response is due to a 
redirect to a permission denied page.

My understanding was the .forward() method didn’t change anything on 
route in either direction.

-Andy.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Forwarding request to a different servlet

Posted by Mark Thomas <ma...@apache.org>.
RequestDispatcher operates within a given ServletContext (web application).

You are trying to do a cross-context dispatch - i.e. to another web 
application. To do this you will need to:

- enable cross-context dispatch for the /plugins web application
   https://tomcat.apache.org/tomcat-8.5-doc/config/context.html
   look for crossContext

- then use code something like this:

ServletContext current = request.getServletContext();
ServletContext backend = current.getContext("/backend");
RequestDispatcher rd = backend.getRequestDispatcher("/rest/abc/xx");
rd.forward(request,response);

HTH,

Mark


On 11/08/2023 08:52, Andy Pont wrote:
> Hello!
> 
> We have a commercial application that runs under Tomcat 8.5.65 (on 
> Windows Server 2019).  In the tomcat/webapps directory there are the 
> following three directories (names changed):
> 
> backend
> frontend
> ROOT
> 
> The “frontend” directory contains the UI for the commercial application 
> and is, as far as I can tell, all just HTML, JavaScript, etc.  The 
> “backend” directory contains the parts of the system that do the bulk of 
> the work and appear to be mainly .jsp files.
> 
> Amongst other things, the “backend” handles a URL 
> https://<server_name>/backend/rest/abc/xx where “xx” represents a number 
> that tells it what to act upon.
> 
> I have started developing a new servlet which handles POST requests to 
> the URL: https://<server_name>/plugins/abc/xx.  In some cases (based on 
> a values in the request body), the servlet will process things itself 
> and generate its own response.   For certain cases it just needs to 
> forward the request on to corresponding “backend” URL and then pass the 
> response back.
> 
> I assumed that .forward(request, response) on a RequestDispatcher would 
> be what I needed to use.  I have tried every combination of 
> getServletContext() and getRequestDispatcher() I can think of or have 
> found on the internet but it always fails with an HTTP error 404.  This 
> is because the URL that it is being forwarded to always has a rogue 
> “plugins” in it, i.e. https://<server_name>/plugins/backend/rest/abc/xx.
> 
> I suspect the solution is simple but I am new to Tomcat and developing 
> servlets and probably missing something obvious.  Any guidance would be 
> much appreciated.
> 
> -Andy.
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org