"First request in session" problem and a bug in WOComponentRequestHandler
"First request in session" problem and a bug in WOComponentRequestHandler
- Subject: "First request in session" problem and a bug in WOComponentRequestHandler
- From: Wiktor Moskwa <email@hidden>
- Date: Thu, 17 Apr 2008 15:30:06 +0200
Hello wo-dev,
Maybe the following problems are known to you or maybe they're even
fixed in 5.4.
I hope that someone much more experienced in WebObjects can comment on this.
Our environment is WebObjects 5.3.3 with Wonder 4.0 deployed on Gentoo Linux.
The problem:
1. An application recevies the first request in session, by which
I mean a request without "wosid" cookie or SID in URL
(request.isSessionIDInRequest() == false)
For example an URL bookmarked by a user in her browser.
2. The request's handler key is "wo", so this is a component action
i.e.: .../cgi-bin/WebObjects/ifirma.woa/wo/2.0.0.15.1.11.3.1
or direct component access
i.e.: .../cgi-bin/WebObjects/ifirma.woa/wo/FakturaBrowse.wo
Second one little or no sense in production because it would be a nice
backdoor so we reject it of course.
But first one is handled by WO in a weird way.
3. Before WOApplication.dispatchRequest calls a proper request handler
- in this case WOComponentRequestHandler it creates a new session
completely ignoring the fact that it makes no sense :)
If by a coincidence elementID in the request is equal to one of elementIDs
on a default (Main.wo) page in the application, invokeAction is called
on this element usually resulting in a weird exception being thrown.
Strange for me is that contextID is ignored in this case, in my opinion
a new session should expect contextID==0.
In our case, the following URL bookmarked by one of our users
https://www.ifirma.pl/cgi-bin/WebObjects/ifirma.woa/wo/7.0.0.15.5
caused an application to throw the following exception:
java.lang.IllegalStateException: <er.extensions.ERXHyperlink> : Missing page name.
at invokeAction(WOHyperlink.java:78)
at invokeAction(ERXHyperlink.java:56)
...
(there was no improper WOHyperlink on this page, I can assure you)
Our solution:
The following code is put into Application class,
(descriptionForRequest method is not important here).
==================================================================
private boolean isRequestForRedirect(WORequest request) {
// Only component requests are filtered
if (componentRequestHandlerKey().equals(request.requestHandlerKey())) {
// First direct component access attempts are blocked
// i.e.: /wo/FirmaBrowse.wo or /wo/oWHEMIojtbvC0evhGU1Dt0/FirmaBrowse.wo
if (request.requestHandlerPathArray() != null) {
String senderID = (String) request.requestHandlerPathArray().lastObject();
if (senderID.endsWith(".wo")) {
pmLog.info("Redirecting request with direct component access attempt: " + descriptionForRequest(request, false));
return true;
}
}
// Then requests with too many elements in requestHandlerPath are blocked
// i.e.: /wo/SomethingElse/oWHEMIojtbvC0evhGU1Dt0/0.0.21.1.1.4.2.0.0
if ((request.requestHandlerPathArray() != null) && (request.requestHandlerPathArray().count() > 2)) {
pmLog.warn("Redirecting request with handler path array too long: " + descriptionForRequest(request, true));
return true;
}
// Finally block all component action requests without session information
// i.e.: bookmarked URLs like /wo/7.0.0.15.5
if (request.isSessionIDInRequest() == false) {
pmLog.info("Redirecting request without session information: " + descriptionForRequest(request, true));
return true;
}
}
return false;
}
@Override
public WOResponse dispatchRequest(WORequest request) {
boolean requestForRedirect = isRequestForRedirect(request);
// Redirect broken requests to default direct action
if (requestForRedirect) {
WOContext context = createContextForRequest(request);
WORedirect redirect = new WORedirect(context);
String redirectUrl = context.directActionURLForActionNamed("default", null);
redirect.setUrl(redirectUrl);
return redirect.generateResponse();
} else {
return super.dispatchRequest(request);
}
}
===================================================================
During research on this topic I encountered a bug in
com.webobjects.appserver._private.WOComponentRequestHandler
If the above handler receives a request with requestHandlerPath longer then
2 elements and this is a direct component access, it throws
ArrayIndexOutOfBoundsException from line 108 in the above class.
And the user will see: "An Internal Server Error Has Occurred."
Just try following URLs on your applications:
.../cgi-bin/WebObjects/APP.woa/wo/xxx/yyy/Something.wo
for example:
http://www.dyned.com/cgi-bin/WebObjects/WOShowcase.woa/wo/xxx/yyy/Error.wo
(xxx, yyy and Error can be of course any strings)
My code above does not solve this bug because invoking
createContextForRequest(request) triggers this error too.
Thanks for your comments.
Regards,
Wiktor Moskwa
--
Power Media S.A.
Wroclaw, Poland
http://www.power.com.pl
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden