mirror of
https://github.com/gnustep/libs-gsweb.git
synced 2025-04-23 23:48:46 +00:00
GSWAdaptors/Apache2/mod_gsw.c
* make load-balancing work * add refusing to app status GSWeb.framework/... * rewrote GSWComponentRequestHandler to make refusing work git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gsweb/trunk@26404 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
fe4f1484fc
commit
a24b60e6f4
11 changed files with 603 additions and 655 deletions
16
ChangeLog
16
ChangeLog
|
@ -1,3 +1,19 @@
|
|||
2008-03-31 David Wetzel <dave@turbocat.de>
|
||||
GSWAdaptors/Apache2/mod_gsw.c
|
||||
* make load-balancing work
|
||||
* add refusing to app status
|
||||
|
||||
GSWeb.framework/GSWApplication.m
|
||||
GSWeb.framework/GSWRequestHandler.h
|
||||
GSWeb.framework/GSWComponentRequestHandler.h
|
||||
GSWeb.framework/GSWComponentRequestHandler.m
|
||||
GSWeb.framework/GSWResponse.m
|
||||
GSWeb.framework/GSWConstants.h
|
||||
GSWeb.framework/GSWConstants.m
|
||||
GSWeb.framework/GSWPrivate.h
|
||||
GSWeb.framework/GSWApplication.h
|
||||
* rewrote GSWComponentRequestHandler to make refusing work
|
||||
|
||||
2008-03-17 David Wetzel <dave@turbocat.de>
|
||||
GSWeb.framework/GSWAssociation.h/m
|
||||
+ bindingInComponent
|
||||
|
|
|
@ -111,6 +111,7 @@ typedef struct gsw_app_conf {
|
|||
|
||||
} gsw_app_conf;
|
||||
|
||||
|
||||
#define GSW_INST_CACHE "gsw_inst_cache"
|
||||
#define X_WO_VERSION_HEADER "x-webobjects-adaptor-version: 20071201\r\n"
|
||||
#define SERVER_SOFTWARE "SERVER_SOFTWARE"
|
||||
|
@ -170,10 +171,11 @@ char *mutexfilename;
|
|||
|
||||
|
||||
typedef struct exipc_data {
|
||||
apr_time_t last_response_time; // in sec since January 1, 1970
|
||||
apr_time_t last_response_time; // in sec since January 1, 1970
|
||||
apr_time_t last_request_time; // in sec since January 1, 1970
|
||||
u_int32_t load;
|
||||
u_int8_t unreachable; // 0=online 1=unreachable
|
||||
u_int8_t unreachable; // 0=online 1=unreachable
|
||||
u_int8_t refusing; // 0=serving new sessions 1=refusing
|
||||
} exipc_data;
|
||||
|
||||
/*
|
||||
|
@ -302,6 +304,21 @@ void mark_unreachable(gsw_app_conf * app)
|
|||
apr_global_mutex_unlock(exipc_mutex);
|
||||
}
|
||||
|
||||
void mark_refusing(gsw_app_conf * app)
|
||||
{
|
||||
exipc_data * mem = NULL;
|
||||
apr_time_t now = apr_time_now();
|
||||
u_int16_t index = app->total_index;
|
||||
|
||||
apr_global_mutex_lock(exipc_mutex);
|
||||
mem = (exipc_data *) apr_shm_baseaddr_get(exipc_shm);
|
||||
|
||||
mem[index].last_request_time = now;
|
||||
mem[index].refusing = 1;
|
||||
|
||||
apr_global_mutex_unlock(exipc_mutex);
|
||||
}
|
||||
|
||||
void update_app_statistics(gsw_app_conf * app, apr_time_t last_request_time, apr_time_t last_response_time, u_int32_t load)
|
||||
{
|
||||
exipc_data * mem = NULL;
|
||||
|
@ -314,6 +331,7 @@ void update_app_statistics(gsw_app_conf * app, apr_time_t last_request_time, apr
|
|||
mem[index].last_request_time = last_request_time;
|
||||
mem[index].last_response_time = last_response_time;
|
||||
mem[index].load = load;
|
||||
mem[index].unreachable = 0;
|
||||
|
||||
apr_global_mutex_unlock(exipc_mutex);
|
||||
}
|
||||
|
@ -359,13 +377,15 @@ gsw_app_conf * find_app_by_name(char * name, gsw_cfg *cfg, request_rec *r)
|
|||
|
||||
if ((strcasecmp(appconf->app_name, name) == 0)) {
|
||||
// enable unreachable instances after some time
|
||||
if ((mem[i].unreachable == 1) && (mem[i].last_request_time < t)) {
|
||||
if (mem[i].last_request_time < t) {
|
||||
mem[i].unreachable = 0;
|
||||
mem[i].refusing = 0;
|
||||
}
|
||||
|
||||
if (mem[i].unreachable == 0) {
|
||||
if ((mem[i].unreachable == 0) && (mem[i].refusing == 0)) {
|
||||
if (mem[i].load <= lastload) {
|
||||
lastindex = i;
|
||||
lastindex = i;
|
||||
lastload = mem[i].load;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -399,20 +419,20 @@ gsw_app_conf * find_app(request_rec *r)
|
|||
|
||||
|
||||
strncpy(app_name, appName, sizeof(app_name));
|
||||
|
||||
// ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "app_name '%s'", app_name);
|
||||
|
||||
if ((appName = index(app_name, '.'))) {
|
||||
*appName = '\0';
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
appName++;
|
||||
|
||||
// now get the instance number if any
|
||||
appName++;
|
||||
|
||||
if ((instance_str = index(appName, '/'))) {
|
||||
// ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "instance_str '%s'", instance_str);
|
||||
instance_str++;
|
||||
if (appName = index(instance_str, '/')) {
|
||||
*appName = '\0';
|
||||
// ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "appName '%s'", appName);
|
||||
instance_nr = atoi(instance_str);
|
||||
// parse error?
|
||||
if (instance_nr == 0) {
|
||||
|
@ -421,9 +441,16 @@ gsw_app_conf * find_app(request_rec *r)
|
|||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// return NULL;
|
||||
|
||||
}
|
||||
|
||||
cfg = our_dconfig(r);
|
||||
|
||||
// ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "instance_nr '%d'", instance_nr);
|
||||
|
||||
|
||||
if (instance_nr != -1) {
|
||||
char tmp_key[128];
|
||||
|
||||
|
@ -436,7 +463,7 @@ gsw_app_conf * find_app(request_rec *r)
|
|||
}
|
||||
|
||||
app_conf = find_app_by_name(app_name, cfg, r);
|
||||
|
||||
|
||||
return app_conf;
|
||||
}
|
||||
|
||||
|
@ -594,7 +621,64 @@ static int send_header_string(int soc, const char * key, const char * value, req
|
|||
retval = write_sock(soc, tmpStr, strlen(tmpStr), r);
|
||||
}
|
||||
|
||||
static int send_headers(int soc, request_rec *r)
|
||||
const char * fixRequestString(request_rec *r, gsw_app_conf *app)
|
||||
{
|
||||
char * req_str = r->the_request;
|
||||
size_t len = strlen(req_str);
|
||||
char * appName = apr_palloc(r->pool,len+5);
|
||||
char * spaceStr;
|
||||
char * instanceStr;
|
||||
char * restStr = NULL;
|
||||
int instance_nr = -1;
|
||||
char * newString = NULL;
|
||||
|
||||
strncpy(appName, req_str, len);
|
||||
|
||||
// GET /wo/PBX HTTP/1.1
|
||||
|
||||
if (appName = index(appName, '/')) {
|
||||
appName++;
|
||||
if (appName = index(appName, '/')) {
|
||||
appName++;
|
||||
if (spaceStr = index(appName, ' ')) {
|
||||
*spaceStr = '\0';
|
||||
instanceStr = appName;
|
||||
instanceStr++;
|
||||
if (instanceStr = index(appName, '/')) {
|
||||
*instanceStr = '\0';
|
||||
instanceStr++;
|
||||
if (spaceStr = index(instanceStr, '/')) {
|
||||
*spaceStr = '\0';
|
||||
restStr = spaceStr;
|
||||
restStr++;
|
||||
}
|
||||
// ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "instanceStr:'%s'", instanceStr);
|
||||
}
|
||||
// ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "appName:'%s'", appName);
|
||||
// ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "restStr:'%s'", restStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!restStr) {
|
||||
restStr = "";
|
||||
}
|
||||
|
||||
if (spaceStr = index(appName, '.')) {
|
||||
*spaceStr = '\0';
|
||||
}
|
||||
|
||||
|
||||
newString = apr_psprintf(r->pool, "%s %s%s.woa/%d/%s HTTP/1.1\r\n", r->method, ADAPTOR_PREFIX, appName, app->instance_number
|
||||
,restStr);
|
||||
|
||||
// ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "newString:'%s'", newString);
|
||||
|
||||
|
||||
return newString;
|
||||
}
|
||||
|
||||
static int send_headers(int soc, gsw_app_conf *app, request_rec *r)
|
||||
{
|
||||
apr_array_header_t * hdrs_arr = NULL;
|
||||
apr_table_entry_t * hdrs = NULL;
|
||||
|
@ -607,9 +691,16 @@ static int send_headers(int soc, request_rec *r)
|
|||
|
||||
hdrs_arr = (apr_array_header_t*) apr_table_elts(r->headers_in);
|
||||
hdrs = (apr_table_entry_t *) hdrs_arr->elts;
|
||||
|
||||
snprintf(tmpStr, sizeof(tmpStr), "%s\r\n", r->the_request);
|
||||
|
||||
// GET /wo/PBX HTTP/1.1
|
||||
|
||||
|
||||
//snprintf(tmpStr, sizeof(tmpStr), "%s\r\n", r->the_request);
|
||||
strncpy(tmpStr, fixRequestString(r,app), sizeof(tmpStr));
|
||||
|
||||
retval = write_sock(soc,tmpStr,strlen(tmpStr), r);
|
||||
// ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "send_headers:'%s'", tmpStr);
|
||||
|
||||
if (retval != 0) {
|
||||
return retval;
|
||||
}
|
||||
|
@ -746,7 +837,7 @@ static int handle_request(request_rec *r, gsw_app_conf * app, void * postdata, u
|
|||
soc = connect_host(app->host_name, app->port);
|
||||
|
||||
if (soc != -1) {
|
||||
if (send_headers(soc, r) == 0) {
|
||||
if (send_headers(soc, app, r) == 0) {
|
||||
int headers_done = 0;
|
||||
|
||||
request_time = apr_time_now();
|
||||
|
@ -768,13 +859,15 @@ static int handle_request(request_rec *r, gsw_app_conf * app, void * postdata, u
|
|||
http_status = atoi(newBuf+9);
|
||||
if (http_status==200) {
|
||||
http_status=OK;
|
||||
}
|
||||
}
|
||||
if (http_status == 302) {
|
||||
r->status = http_status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (headers_done == 0) {
|
||||
newBuf = read_sock_line(soc, r, sub_pool);
|
||||
|
||||
if (newBuf != NULL) {
|
||||
if (load_avr_seen == 0) {
|
||||
if (strncmp(newBuf, "x-webobjects-loadaverage: ", 26) == 0) {
|
||||
|
@ -802,9 +895,11 @@ static int handle_request(request_rec *r, gsw_app_conf * app, void * postdata, u
|
|||
}
|
||||
}
|
||||
if (location == NULL) {
|
||||
if (strncmp(newBuf, "location: ", 10) == 0) {
|
||||
// Apple has a bug, giving us a 'L', so we do that too but accept a 'l' too -- dw
|
||||
if (strncasecmp(newBuf, "location: ", 10) == 0) {
|
||||
location = newBuf+10;
|
||||
apr_table_set(r->headers_out, "location", location);
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "location '%s'", location);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -813,14 +908,16 @@ static int handle_request(request_rec *r, gsw_app_conf * app, void * postdata, u
|
|||
} // while
|
||||
|
||||
// do the request
|
||||
if ((content_type != NULL) && (content_length > 0)) {
|
||||
if ((content_length > 0)) {
|
||||
size_t bytesDone = 0;
|
||||
size_t blockSize = 1024;
|
||||
size_t rval=1;
|
||||
char * transferBuf = NULL;
|
||||
|
||||
ap_set_content_type(r, content_type);
|
||||
|
||||
if (content_type != NULL) {
|
||||
ap_set_content_type(r, content_type);
|
||||
}
|
||||
|
||||
if (content_length < blockSize) {
|
||||
blockSize = content_length;
|
||||
}
|
||||
|
@ -844,7 +941,11 @@ static int handle_request(request_rec *r, gsw_app_conf * app, void * postdata, u
|
|||
|
||||
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Request took %d ms", apr_time_msec(done_time - request_time));
|
||||
|
||||
update_app_statistics(app, request_time, done_time, newload);
|
||||
if (http_status==302) {
|
||||
mark_refusing(app);
|
||||
} else {
|
||||
update_app_statistics(app, request_time, done_time, newload);
|
||||
}
|
||||
|
||||
} else { // -1
|
||||
http_status = UNREACHABLE;
|
||||
|
@ -1075,6 +1176,8 @@ static int gsw_handler(request_rec *r)
|
|||
break;
|
||||
case OK:
|
||||
return handle_status;
|
||||
case HTTP_MOVED_TEMPORARILY:
|
||||
return OK; // otherwise, we get a apache error doc!
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1122,7 +1225,7 @@ static int gsw_handler(request_rec *r)
|
|||
|
||||
if (mem) {
|
||||
ap_rputs("<table border=1>\n",r);
|
||||
ap_rputs("<tr><td>Name</td><td>Instance</td><td>Host</td><td>Port</td><td>Load</td><td> Unreachable</td><td>Last Request</td><td>Last Response</td></tr>\n",r);
|
||||
ap_rputs("<tr><td>Name</td><td>Instance</td><td>Host</td><td>Port</td><td>Load</td><td> Unreachable</td><td>Refusing</td><td>Last Request</td><td>Last Response</td></tr>\n",r);
|
||||
|
||||
for (i = 0; i < tarr->nelts; i++) {
|
||||
gsw_app_conf *appconf = (gsw_app_conf *) telts[i].val;
|
||||
|
@ -1136,6 +1239,7 @@ static int gsw_handler(request_rec *r)
|
|||
ap_rprintf(r, "<td>%u</td>", appconf->port);
|
||||
ap_rprintf(r, "<td>%u</td>", mem[i].load);
|
||||
ap_rprintf(r, "<td>%s</td>", (mem[i].unreachable == 1) ? "YES": "NO");
|
||||
ap_rprintf(r, "<td>%s</td>", (mem[i].refusing == 1) ? "YES": "NO");
|
||||
apr_ctime(timestr, mem[i].last_request_time);
|
||||
ap_rprintf(r, "<td>%s</td>", timestr);
|
||||
apr_ctime(timestr, mem[i].last_response_time);
|
||||
|
@ -1437,6 +1541,7 @@ void init_shared_mem(const apr_shm_t * xxx, int count, server_rec * s)
|
|||
currentRecord[i].last_response_time = 0;
|
||||
currentRecord[i].load = 0;
|
||||
currentRecord[i].unreachable = 0;
|
||||
currentRecord[i].refusing = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -123,6 +123,7 @@ GSWEB_EXPORT BOOL WOStrictFlag;
|
|||
BOOL _isTracingObjectiveCMessagesEnabled;
|
||||
BOOL _isTracingScriptedMessagesEnabled;
|
||||
BOOL _isTracingStatementsEnabled;
|
||||
BOOL _allowsConcurrentRequestHandling;
|
||||
NSRunLoop* _currentRunLoop;
|
||||
NSDate* _runLoopDate;
|
||||
NSTimer* _initialTimer;
|
||||
|
@ -135,10 +136,11 @@ GSWEB_EXPORT BOOL WOStrictFlag;
|
|||
-(void)dealloc;
|
||||
-(id)init;
|
||||
|
||||
|
||||
-(BOOL) shouldRestoreSessionOnCleanEntry:(GSWRequest*) aRequest;
|
||||
-(BOOL)allowsConcurrentRequestHandling;
|
||||
-(BOOL)adaptorsDispatchRequestsConcurrently;
|
||||
-(BOOL)isConcurrentRequestHandlingEnabled;
|
||||
-(NSLock *) requestHandlingLock;
|
||||
-(BOOL)isRequestHandlingLocked;
|
||||
-(void)lockRequestHandling;
|
||||
-(void)unlockRequestHandling;
|
||||
|
@ -163,6 +165,8 @@ GSWEB_EXPORT BOOL WOStrictFlag;
|
|||
|
||||
-(NSString*)defaultRequestHandlerClassName;
|
||||
-(Class)defaultRequestHandlerClass;
|
||||
- (NSString*) sessionIdKey;
|
||||
- (NSString*) instanceIdKey;
|
||||
@end
|
||||
//
|
||||
////====================================================================
|
||||
|
|
|
@ -301,6 +301,7 @@ int GSWApplicationMain(NSString* applicationClassName,
|
|||
_minimumActiveSessionsCount = 0; // 0 is default
|
||||
_dynamicLoadingEnabled=YES;
|
||||
_printsHTMLParserDiagnostics=YES;
|
||||
_allowsConcurrentRequestHandling = NO;
|
||||
|
||||
[[self class] _setApplication:self];
|
||||
[self _touchPrincipalClasses];
|
||||
|
@ -453,6 +454,12 @@ int GSWApplicationMain(NSString* applicationClassName,
|
|||
return dscr;
|
||||
};
|
||||
|
||||
-(BOOL) shouldRestoreSessionOnCleanEntry:(GSWRequest*) aRequest
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// allowsConcurrentRequestHandling
|
||||
-(BOOL)allowsConcurrentRequestHandling
|
||||
|
@ -464,21 +471,24 @@ int GSWApplicationMain(NSString* applicationClassName,
|
|||
// adaptorsDispatchRequestsConcurrently
|
||||
-(BOOL)adaptorsDispatchRequestsConcurrently
|
||||
{
|
||||
//TODO: use isMultiThreaded ?
|
||||
BOOL adaptorsDispatchRequestsConcurrently=NO;
|
||||
int i=0;
|
||||
int adaptorsCount=[_adaptors count];
|
||||
for(i=0;!adaptorsDispatchRequestsConcurrently && i<adaptorsCount;i++)
|
||||
adaptorsDispatchRequestsConcurrently=[[_adaptors objectAtIndex:i]dispatchesRequestsConcurrently];
|
||||
return adaptorsDispatchRequestsConcurrently;
|
||||
};
|
||||
return _isMultiThreaded;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// isConcurrentRequestHandlingEnabled
|
||||
-(BOOL)isConcurrentRequestHandlingEnabled
|
||||
{
|
||||
return [self allowsConcurrentRequestHandling];
|
||||
};
|
||||
return (_isMultiThreaded && _allowsConcurrentRequestHandling);
|
||||
}
|
||||
|
||||
- (NSLock *) requestHandlingLock
|
||||
{
|
||||
if (_isMultiThreaded && (!_allowsConcurrentRequestHandling)) {
|
||||
return _globalLock;
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// calls the class because on MacOSX KVC does not support "application.class.isDebuggingEnabled"
|
||||
|
@ -2294,7 +2304,7 @@ to another instance **/
|
|||
//terminate
|
||||
-(void)terminate
|
||||
{
|
||||
NSTimer* timer=nil;
|
||||
// NSTimer* timer=nil;
|
||||
_terminating = YES;
|
||||
/*
|
||||
timer=[NSTimer timerWithTimeInterval:0
|
||||
|
@ -2456,120 +2466,37 @@ to another instance **/
|
|||
};
|
||||
|
||||
|
||||
-(GSWResponse*)checkAppIfRefused:(GSWRequest*)aRequest
|
||||
{
|
||||
NSDictionary* requestHandlerValues=nil;
|
||||
GSWResponse* response=nil;
|
||||
NSString* sessionID=nil;
|
||||
BOOL refuseRequest = NO;
|
||||
|
||||
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
// NSLog(@"Application : checkAppIfRefused");
|
||||
// NSLog(@"Application : allSessionIDs = %@", [_sessionStore allSessionIDs]);
|
||||
requestHandlerValues=[GSWComponentRequestHandler _requestHandlerValuesForRequest:aRequest];
|
||||
if (requestHandlerValues)
|
||||
{
|
||||
// NSLog(@"Application : requestHandlerValues is set");
|
||||
|
||||
sessionID=[requestHandlerValues objectForKey:GSWKey_SessionID[GSWebNamingConv]];
|
||||
if (!sessionID)
|
||||
{
|
||||
if ([self isRefusingNewSessions])
|
||||
{
|
||||
NSLog(@"refuseRequest !");
|
||||
refuseRequest = YES;
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
// NSLog(@"Application : sessionID found : %@", sessionID);
|
||||
// NSLog(@"Application : allSessionIDs = %@", [_sessionStore allSessionIDs]);
|
||||
// check for existing session ID
|
||||
if (![_sessionStore containsSessionID:sessionID])
|
||||
{
|
||||
// NSLog(@"Application : sessionStore does not contain _sessionID");
|
||||
if ([self isRefusingNewSessions])
|
||||
refuseRequest = YES;
|
||||
}
|
||||
}
|
||||
if (refuseRequest)
|
||||
{
|
||||
NSLog(@"Application : refuseRequest == YES ,generate Response");
|
||||
// generate response, to refuse the request
|
||||
response=[GSWResponse generateRefusingResponseInContext:nil
|
||||
forRequest:aRequest];
|
||||
if (response)
|
||||
[response _finalizeInContext:nil]; //DO Call _finalizeInContext: !
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
-(GSWResponse*)dispatchRequest:(GSWRequest*)aRequest
|
||||
{
|
||||
//OK
|
||||
GSWResponse* response=nil;
|
||||
GSWRequestHandler* requestHandler=nil;
|
||||
GSWResponse * response=nil;
|
||||
GSWRequestHandler * requestHandler=nil;
|
||||
NSNotificationCenter * noteCenter = [NSNotificationCenter defaultCenter];
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
[self lock];
|
||||
GSWeb_ApplicationDebugSetChange();
|
||||
[self unlock];
|
||||
#endif
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
ASSIGN(_lastAccessDate,[NSDate date]);
|
||||
|
||||
[[NSNotificationCenter defaultCenter]postNotificationName:@"ApplicationWillDispatchRequestNotification"
|
||||
object:aRequest];
|
||||
|
||||
response = [self checkAppIfRefused:aRequest];
|
||||
if (!response)
|
||||
{
|
||||
NSDebugMLLog(@"requests",@"aRequest=%@",aRequest);
|
||||
|
||||
requestHandler=[self handlerForRequest:aRequest];
|
||||
NSDebugMLLog(@"requests",@"requestHandler=%@",requestHandler);
|
||||
|
||||
if (!requestHandler)
|
||||
requestHandler=[self defaultRequestHandler];
|
||||
|
||||
NSDebugMLLog(@"requests",@"requestHandler=%@",requestHandler);
|
||||
|
||||
if (!requestHandler)
|
||||
{
|
||||
NSDebugMLLog0(@"application",@"GSWApplication dispatchRequest: no request handler");
|
||||
//TODO error
|
||||
}
|
||||
else
|
||||
{
|
||||
NSDebugMLLog(@"requests",@"sessionStore=%@",_sessionStore);
|
||||
response=[requestHandler handleRequest:aRequest];
|
||||
NSDebugMLLog(@"requests",@"sessionStore=%@",_sessionStore);
|
||||
[self _resetCache];
|
||||
NSDebugMLLog(@"requests",@"sessionStore=%@",_sessionStore);
|
||||
};
|
||||
if (!response)
|
||||
{
|
||||
//TODO RESPONSE_PB
|
||||
};
|
||||
[[NSNotificationCenter defaultCenter]postNotificationName:@"ApplicationDidDispatchRequestNotification"
|
||||
object:response];
|
||||
[aRequest _setContext:nil];
|
||||
};
|
||||
{
|
||||
ASSIGN(_lastAccessDate,[NSDate date]);
|
||||
|
||||
[noteCenter postNotificationName:@"ApplicationWillDispatchRequestNotification"
|
||||
object:aRequest];
|
||||
|
||||
requestHandler = [self handlerForRequest:aRequest];
|
||||
|
||||
if (!requestHandler)
|
||||
requestHandler = [self defaultRequestHandler];
|
||||
|
||||
response = [requestHandler handleRequest:aRequest];
|
||||
if (!response) {
|
||||
NSDebugLog(@"%s !!! Response is null !!!", __PRETTY_FUNCTION__);
|
||||
response = [self createResponseInContext:nil];
|
||||
}
|
||||
|
||||
[self _resetCache];
|
||||
|
||||
[noteCenter postNotificationName:@"ApplicationDidDispatchRequestNotification"
|
||||
object:response];
|
||||
[aRequest _setContext:nil];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
NSLog(@"EXCEPTION: %@",localException);
|
||||
|
@ -2577,7 +2504,7 @@ to another instance **/
|
|||
NS_ENDHANDLER;
|
||||
|
||||
return response;
|
||||
};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
//awake
|
||||
|
@ -4210,5 +4137,15 @@ to another instance **/
|
|||
return languages;
|
||||
};
|
||||
|
||||
- (NSString*) sessionIdKey
|
||||
{
|
||||
return @"wosid";
|
||||
}
|
||||
|
||||
- (NSString*) instanceIdKey
|
||||
{
|
||||
return @"woinst";
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -38,26 +38,8 @@
|
|||
}
|
||||
|
||||
-(GSWResponse*)handleRequest:(GSWRequest*)aRequest;
|
||||
-(GSWResponse*)lockedHandleRequest:(GSWRequest*)aRequest;
|
||||
-(GSWResponse*)lockedDispatchWithPreparedApplication:(GSWApplication*)application
|
||||
inContext:(GSWContext*)aContext
|
||||
elements:(NSDictionary*)elements;
|
||||
-(GSWResponse*)lockedDispatchWithPreparedSession:(GSWSession*)aSession
|
||||
inContext:(GSWContext*)aContext
|
||||
elements:(NSDictionary*)elements;
|
||||
-(GSWResponse*)lockedDispatchWithPreparedPage:(GSWComponent*)_component
|
||||
inSession:(GSWSession*)aSession
|
||||
inContext:(GSWContext*)aContext
|
||||
elements:(NSDictionary*)elements;
|
||||
-(GSWComponent*)lockedRestorePageForContextID:(NSString*)aContextID
|
||||
inSession:(GSWSession*)aSession;
|
||||
|
||||
@end
|
||||
|
||||
//====================================================================
|
||||
@interface GSWComponentRequestHandler (GSWRequestHandlerClassA)
|
||||
+(id)handler;
|
||||
+(NSDictionary*)_requestHandlerValuesForRequest:(GSWRequest*)aRequest;
|
||||
@end
|
||||
|
||||
#endif //_GSWComponentRequestHandler_h__
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
Copyright (C) 1999-2004 Free Software Foundation, Inc.
|
||||
|
||||
Written by: Manuel Guesdon <mguesdon@orange-concept.com>
|
||||
Date: Feb 1999
|
||||
Written by: David Wetzel <dave@turbocat.de>
|
||||
Date: Mar 2008
|
||||
|
||||
$Revision$
|
||||
$Date$
|
||||
|
@ -32,506 +32,390 @@
|
|||
RCS_ID("$Id$")
|
||||
|
||||
#include "GSWeb.h"
|
||||
#include "GSWPrivate.h"
|
||||
|
||||
//====================================================================
|
||||
@implementation GSWComponentRequestHandler
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// note: we are NOT looking at [WORequest _lookForIDsInCookiesFirst] since it is always NO -- dw
|
||||
|
||||
- (NSDictionary*) requestHandlerValuesForRequest:(GSWRequest *) aRequest
|
||||
{
|
||||
NSMutableDictionary * aDictionary = [NSMutableDictionary dictionary];
|
||||
NSArray * pathArray = [aRequest requestHandlerPathArray];
|
||||
NSString * lastObject = nil;
|
||||
NSString * penultElement = nil;
|
||||
NSString * aSessionID = nil;
|
||||
NSString * aContextID = nil;
|
||||
NSString * aSenderID = nil;
|
||||
NSMutableString * pageName = nil;
|
||||
NSString * sessionIdKey = [GSWApp sessionIdKey];
|
||||
int p = 0;
|
||||
int count = 0;
|
||||
int length = 0;
|
||||
int pageNameLocation = 0;
|
||||
int pageNameLength = 0;
|
||||
|
||||
if ((pathArray))
|
||||
{
|
||||
count = [pathArray count];
|
||||
}
|
||||
|
||||
if (count != 0)
|
||||
{
|
||||
lastObject = [pathArray lastObject];
|
||||
if(count > 1)
|
||||
{
|
||||
penultElement = [pathArray objectAtIndex:count - 2];
|
||||
}
|
||||
|
||||
for (length = [lastObject length]; ((p < length) && (isdigit([lastObject characterAtIndex:p]) != 0)); p++) { }
|
||||
|
||||
if ((p < length) && ([lastObject characterAtIndex:p] == '.')) {
|
||||
aContextID = [lastObject substringToIndex:p];
|
||||
p++;
|
||||
aSenderID = [lastObject substringFromIndex:p];
|
||||
|
||||
if ((penultElement != nil) && ([penultElement hasSuffix:GSWPagePSuffix[GSWebNamingConv]])) {
|
||||
if (GSWebNamingConv == 1) {
|
||||
pageNameLength = count - 2; // .wo
|
||||
} else {
|
||||
pageNameLength = count - 4; // .gswc
|
||||
}
|
||||
} else {
|
||||
if (penultElement != nil) {
|
||||
aSessionID = penultElement;
|
||||
pageNameLength = count - 2; // TODO:check if that works with GSWNAMES.
|
||||
} else {
|
||||
pageNameLength = 0;
|
||||
}
|
||||
}
|
||||
if (aContextID != nil)
|
||||
{
|
||||
[aDictionary setObject:aContextID forKey:GSWKey_ContextID[GSWebNamingConv]]; // wocid
|
||||
[aDictionary setObject:aSenderID forKey:GSWKey_ElementID[GSWebNamingConv]]; // woeid
|
||||
}
|
||||
} else {
|
||||
if ([lastObject hasSuffix:GSWPagePSuffix[GSWebNamingConv]]) {
|
||||
pageNameLength = count;
|
||||
} else {
|
||||
aSessionID = lastObject;
|
||||
pageNameLength = count - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (pageNameLength != 0) {
|
||||
if (pageNameLength == 1) {
|
||||
pageName = [pathArray objectAtIndex:0];
|
||||
} else {
|
||||
int i;
|
||||
pageName = [[NSMutableString alloc] initWithCapacity:256];
|
||||
[pageName autorelease];
|
||||
|
||||
for (i = pageNameLocation; i < pageNameLength - pageNameLocation; i++) {
|
||||
[pageName appendString:[pathArray objectAtIndex:i]];
|
||||
[pageName appendString:@"/"];
|
||||
}
|
||||
[pageName appendString:[pathArray objectAtIndex:i]];
|
||||
}
|
||||
if ([pageName hasSuffix:GSWPagePSuffix[GSWebNamingConv]]) {
|
||||
if (GSWebNamingConv == 1) {
|
||||
pageName = (NSMutableString*) [pageName substringToIndex:[pageName length] - 3]; // .wo
|
||||
} else {
|
||||
pageName = (NSMutableString*) [pageName substringToIndex:[pageName length] - 5]; // .gswc
|
||||
}
|
||||
}
|
||||
[aDictionary setObject:pageName
|
||||
forKey:GSWKey_PageName[GSWebNamingConv]];
|
||||
}
|
||||
|
||||
if (aSessionID == nil) {
|
||||
aSessionID = [aRequest stringFormValueForKey:sessionIdKey];
|
||||
|
||||
if(aSessionID == nil) {
|
||||
aSessionID = [aRequest cookieValueForKey:sessionIdKey];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ([GSWApp shouldRestoreSessionOnCleanEntry:aRequest]) {
|
||||
aSessionID = [aRequest cookieValueForKey:sessionIdKey];
|
||||
}
|
||||
}
|
||||
|
||||
if ((aSessionID != nil) && ([aSessionID length] > 0)) {
|
||||
[aDictionary setObject:aSessionID forKey:sessionIdKey];
|
||||
}
|
||||
return aDictionary;
|
||||
}
|
||||
|
||||
GSWResponse * _dispatchWithPreparedPage(GSWComponent * aPage, GSWSession * aSession, GSWContext * aContext, NSDictionary * someElements)
|
||||
{
|
||||
GSWRequest * aRequest = [aContext request];
|
||||
GSWApplication * anApplication = GSWApp;
|
||||
GSWResponse * aResponse = [anApplication createResponseInContext:aContext];
|
||||
NSString * aSenderID = [aContext senderID];
|
||||
NSString * oldContextID = [aSession _contextIDMatchingIDsInContext:aContext];
|
||||
BOOL didPageChange = NO;
|
||||
|
||||
[aResponse setHTTPVersion:[aRequest httpVersion]];
|
||||
[aResponse setHeader:@"text/html"
|
||||
forKey:@"content-type"];
|
||||
[aContext _setResponse:aResponse];
|
||||
|
||||
if (oldContextID == nil) {
|
||||
if ((aSenderID != nil) && ([aRequest _hasFormValues])) {
|
||||
[anApplication takeValuesFromRequest:aRequest inContext:aContext];
|
||||
}
|
||||
[aContext _setPageChanged:NO];
|
||||
|
||||
if (aSenderID != nil) {
|
||||
GSWElement * anActionResults = [anApplication invokeActionForRequest:aRequest inContext:aContext];
|
||||
|
||||
if ((anActionResults == nil) || ([anActionResults isKindOfClass: [GSWComponent class]])) {
|
||||
GSWComponent * aResultComponent = (GSWComponent*) anActionResults;
|
||||
|
||||
if ((aResultComponent != nil) && ([aResultComponent context] != aContext)) {
|
||||
[aResultComponent _awakeInContext:aContext];
|
||||
}
|
||||
|
||||
if ((aResultComponent != nil) && (aResultComponent != [aContext _pageElement])) {
|
||||
didPageChange = YES;
|
||||
}
|
||||
|
||||
[aContext _setPageChanged:didPageChange];
|
||||
|
||||
if (didPageChange) {
|
||||
[aContext _setPageElement:aResultComponent];
|
||||
}
|
||||
} else {
|
||||
GSWResponse * theResponse = [anActionResults generateResponse];
|
||||
return theResponse;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
GSWComponent * responsePage = [aSession restorePageForContextID:oldContextID];
|
||||
[aContext _setPageElement:responsePage];
|
||||
}
|
||||
|
||||
[anApplication appendToResponse:aResponse inContext: aContext];
|
||||
|
||||
return aResponse;
|
||||
}
|
||||
|
||||
GSWResponse * _dispatchWithPreparedSession(GSWSession * aSession, GSWContext * aContext, NSDictionary * someElements)
|
||||
{
|
||||
GSWComponent * aPage = nil;
|
||||
GSWResponse * aResponse = nil;
|
||||
NSString * aPageName = [someElements objectForKey:GSWKey_PageName[GSWebNamingConv]]; // "wopage"
|
||||
NSString * oldContextID = [aContext _requestContextID];
|
||||
GSWApplication * anApplication = GSWApp;
|
||||
NSString * sessionIdKey = [anApplication sessionIdKey];
|
||||
NSString * oldSessionID = [someElements objectForKey:sessionIdKey];
|
||||
BOOL clearIDsInCookies = NO;
|
||||
BOOL storesIDsInCookies = [aSession storesIDsInCookies];
|
||||
|
||||
if ((oldSessionID == nil) || (oldContextID == nil)) {
|
||||
if ((aPageName == nil) && (!storesIDsInCookies))
|
||||
{
|
||||
GSWRequest * request = [aContext request];
|
||||
NSString * cookieHeader = [request headerForKey:GSWHTTPHeader_Cookie]; //"cookie"
|
||||
if ((cookieHeader != nil) && ([cookieHeader length] > 0)) {
|
||||
NSDictionary * cookieDict = [request cookieValues];
|
||||
|
||||
if (([cookieDict objectForKey:sessionIdKey] != nil) ||
|
||||
([cookieDict objectForKey:[anApplication instanceIdKey]] != nil)) {
|
||||
clearIDsInCookies = YES;
|
||||
}
|
||||
}
|
||||
}
|
||||
aPage = [anApplication pageWithName:aPageName inContext:aContext];
|
||||
} else {
|
||||
aPage = [aSession restorePageForContextID:oldContextID];
|
||||
|
||||
if (aPage == nil) {
|
||||
if ([anApplication _isPageRecreationEnabled]) {
|
||||
aPage = [anApplication pageWithName:aPageName inContext: aContext];
|
||||
} else {
|
||||
return [anApplication handlePageRestorationErrorInContext:aContext];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[aContext _setPageElement:aPage];
|
||||
aResponse = _dispatchWithPreparedPage(aPage, aSession, aContext, someElements);
|
||||
|
||||
if ([anApplication isPageRefreshOnBacktrackEnabled]) {
|
||||
[aResponse disableClientCaching];
|
||||
}
|
||||
|
||||
[aSession _saveCurrentPage];
|
||||
|
||||
if ((clearIDsInCookies) && (!storesIDsInCookies)) {
|
||||
[aSession _clearCookieFromResponse:aResponse];
|
||||
}
|
||||
|
||||
return aResponse;
|
||||
}
|
||||
|
||||
|
||||
GSWResponse * _dispatchWithPreparedApplication(GSWApplication *app, GSWContext * aContext, NSDictionary * requestHandlerDict)
|
||||
{
|
||||
GSWSession * session = nil;
|
||||
GSWResponse * response = nil;
|
||||
GSWRequest * request = [aContext request];
|
||||
NSString * sessionID;
|
||||
|
||||
sessionID = [requestHandlerDict objectForKey:GSWKey_SessionID[GSWebNamingConv]]; //@"wosid"
|
||||
if ((!sessionID)) {
|
||||
session = [app _initializeSessionInContext:aContext];
|
||||
} else {
|
||||
session = [app restoreSessionWithID:sessionID inContext:aContext];
|
||||
}
|
||||
|
||||
if (session == nil) {
|
||||
response = [app handleSessionCreationErrorInContext:aContext];
|
||||
} else {
|
||||
response = _dispatchWithPreparedSession(session, aContext, requestHandlerDict);
|
||||
}
|
||||
|
||||
[aContext _putAwakeComponentsToSleep];
|
||||
[app saveSessionForContext:aContext];
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
- (GSWResponse*) _handleRequest:(GSWRequest*) aRequest
|
||||
{
|
||||
GSWContext * aContext = nil;
|
||||
NSDictionary * requestHandlerValues;
|
||||
NSString * aSessionID;
|
||||
NSString * aSenderID;
|
||||
NSString * oldContextID;
|
||||
GSWStatisticsStore * aStatisticsStore;
|
||||
GSWResponse * aResponse;
|
||||
GSWApplication * app = GSWApp; // is there any reason not to use the global var? -- dw
|
||||
|
||||
requestHandlerValues = [self requestHandlerValuesForRequest:aRequest];
|
||||
aSessionID = [requestHandlerValues objectForKey:[app sessionIdKey]];
|
||||
|
||||
if ((aSessionID == nil) && [app isRefusingNewSessions])
|
||||
{
|
||||
NSString * newLocationURL = [app _newLocationForRequest:aRequest];
|
||||
NSString * msgString = [NSString stringWithFormat:@"Sorry, your request could not immediately be processed. Please try this URL: <a href=\"%@\">%@</a>",
|
||||
newLocationURL, newLocationURL];
|
||||
|
||||
aResponse = [app createResponseInContext:nil];
|
||||
[aResponse _redirectResponse:newLocationURL contentString:msgString];
|
||||
[aResponse _finalizeInContext:nil];
|
||||
|
||||
return aResponse;
|
||||
}
|
||||
|
||||
aSenderID = [requestHandlerValues objectForKey:GSWKey_ElementID[GSWebNamingConv]];
|
||||
oldContextID = [requestHandlerValues objectForKey:GSWKey_ContextID[GSWebNamingConv]];
|
||||
|
||||
if ((aStatisticsStore = [app statisticsStore]))
|
||||
{
|
||||
[aStatisticsStore applicationWillHandleComponentActionRequest];
|
||||
}
|
||||
|
||||
NS_DURING {
|
||||
aContext = [app createContextForRequest:aRequest];
|
||||
[aContext _setRequestContextID:oldContextID];
|
||||
[aContext _setSenderID:aSenderID];
|
||||
|
||||
[app awake];
|
||||
aResponse = _dispatchWithPreparedApplication(app, aContext, requestHandlerValues);
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:DidHandleRequestNotification
|
||||
object:aContext];
|
||||
|
||||
[app sleep];
|
||||
} NS_HANDLER {
|
||||
GSWSession * aSession = nil;
|
||||
|
||||
NSLog(@"%s: Exception occurred while handling request:%@", __PRETTY_FUNCTION__, [localException reason]);
|
||||
|
||||
if(aContext == nil)
|
||||
{
|
||||
aContext = [app createContextForRequest:aRequest];
|
||||
} else {
|
||||
[aContext _putAwakeComponentsToSleep];
|
||||
}
|
||||
|
||||
aSession = [aContext _session];
|
||||
aResponse = [app handleException:localException
|
||||
inContext:aContext];
|
||||
|
||||
if (aSession) {
|
||||
NS_DURING {
|
||||
[app saveSessionForContext:aContext];
|
||||
[app sleep];
|
||||
} NS_HANDLER {
|
||||
NSLog(@"WOApplication '%@': Another Exception occurred while trying to clean the application :%@", [app name], [localException reason]);
|
||||
} NS_ENDHANDLER;
|
||||
}
|
||||
|
||||
} NS_ENDHANDLER;
|
||||
|
||||
if ((aContext) && ([aContext _session]))
|
||||
{
|
||||
[app saveSessionForContext:aContext];
|
||||
}
|
||||
|
||||
if ((aResponse))
|
||||
{
|
||||
[aResponse _finalizeInContext:aContext];
|
||||
}
|
||||
|
||||
if ((aStatisticsStore))
|
||||
{
|
||||
GSWComponent * aPage = [aContext page];
|
||||
NSString * pageName = nil;
|
||||
|
||||
if ((aPage))
|
||||
{
|
||||
pageName = [aPage name];
|
||||
}
|
||||
[aStatisticsStore applicationDidHandleComponentActionRequestWithPageNamed:pageName];
|
||||
}
|
||||
return aResponse;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Handle request aRequest and return the response
|
||||
This lock application
|
||||
This may lock the application
|
||||
**/
|
||||
|
||||
-(GSWResponse*)handleRequest:(GSWRequest*)aRequest
|
||||
{
|
||||
//OK
|
||||
GSWResponse* response=nil;
|
||||
GSWApplication* application=[GSWApplication application];
|
||||
NSLock * lock;
|
||||
|
||||
[application lockRequestHandling];
|
||||
response=[self lockedHandleRequest:aRequest];
|
||||
if (!response)
|
||||
{
|
||||
response=[GSWResponse responseWithMessage:@"Component Handle request failed. No Response"
|
||||
inContext:nil
|
||||
forRequest:aRequest];
|
||||
[response _finalizeInContext:nil]; //DO Call _finalizeInContext: !
|
||||
};
|
||||
[application unlockRequestHandling];
|
||||
|
||||
return response;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
/** Handle request aRequest and return the response
|
||||
Application should be locked before this
|
||||
**/
|
||||
|
||||
-(GSWResponse*)lockedHandleRequest:(GSWRequest*)aRequest
|
||||
{
|
||||
//OK
|
||||
//GSWStatisticsStore* statisticsStore=nil;
|
||||
GSWApplication* application=[GSWApplication application];
|
||||
GSWContext* aContext=nil;
|
||||
GSWResponse* response=nil;
|
||||
NSDictionary* requestHandlerValues=nil;
|
||||
BOOL exceptionRaised=NO;
|
||||
|
||||
// NSLog(@"%s %@",__PRETTY_FUNCTION__, aRequest);
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
requestHandlerValues=[GSWComponentRequestHandler _requestHandlerValuesForRequest:aRequest];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
exceptionRaised=YES;
|
||||
LOGException(@"%@ (%@)",
|
||||
localException,
|
||||
[localException reason]);
|
||||
localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException,
|
||||
@"In -lockedHandleRequest:");
|
||||
LOGException(@"exception=%@",localException);
|
||||
[application awake];
|
||||
response=[application handleException:localException
|
||||
inContext:nil];
|
||||
[application sleep];
|
||||
[response _finalizeInContext:aContext];//DO Call _finalizeInContext: !
|
||||
NSAssert(!response || [response isFinalizeInContextHasBeenCalled],@"_finalizeInContext not called for GSWResponse");
|
||||
};
|
||||
NS_ENDHANDLER;
|
||||
if (!exceptionRaised)
|
||||
{
|
||||
NSString* senderID=nil;
|
||||
NSString* requestContextID=nil;
|
||||
|
||||
aContext=[[GSWApplication application]createContextForRequest:aRequest];
|
||||
|
||||
senderID=[requestHandlerValues objectForKey:GSWKey_ElementID[GSWebNamingConv]];
|
||||
[aContext _setSenderID:senderID];
|
||||
|
||||
requestContextID=[requestHandlerValues objectForKey:GSWKey_ContextID[GSWebNamingConv]];
|
||||
[aContext _setRequestContextID:requestContextID];
|
||||
|
||||
[application _setContext:aContext];
|
||||
//====>
|
||||
NS_DURING
|
||||
{
|
||||
[application awake];
|
||||
response=[self lockedDispatchWithPreparedApplication:application
|
||||
inContext:aContext
|
||||
elements:requestHandlerValues];
|
||||
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
exceptionRaised=YES;
|
||||
LOGException(@"%@ (%@)",
|
||||
localException,
|
||||
[localException reason]);
|
||||
localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException,
|
||||
@"In lockedDispatchWithPreparedApplication");
|
||||
LOGException(@"exception=%@",localException);
|
||||
response=[application handleException:localException
|
||||
inContext:aContext];
|
||||
[application sleep];
|
||||
[response _finalizeInContext:aContext]; //DO Call _finalizeInContext: !
|
||||
NSAssert(!response || [response isFinalizeInContextHasBeenCalled],
|
||||
@"_finalizeInContext not called for GSWResponse");
|
||||
};
|
||||
NS_ENDHANDLER;
|
||||
if (!exceptionRaised)
|
||||
{
|
||||
NS_DURING
|
||||
{
|
||||
[application sleep];
|
||||
[response _finalizeInContext:aContext];//LAST //CLEAN
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
LOGException(@"%@ (%@)",
|
||||
localException,
|
||||
[localException reason]);
|
||||
localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException,
|
||||
@"In [application sleep] or [response _finalizeInContext:aContext]");
|
||||
LOGException(@"exception=%@",localException);
|
||||
response=[application handleException:localException
|
||||
inContext:nil];
|
||||
[response _finalizeInContext:aContext]; //DO Call _finalizeInContext: !
|
||||
NSAssert(!response || [response isFinalizeInContextHasBeenCalled],
|
||||
@"_finalizeInContext not called for GSWResponse");
|
||||
};
|
||||
NS_ENDHANDLER;
|
||||
};
|
||||
//<===========
|
||||
};
|
||||
lock = [GSWApp requestHandlingLock];
|
||||
|
||||
if (lock) {
|
||||
SYNCHRONIZED(lock) {
|
||||
response = [self _handleRequest:aRequest];
|
||||
}
|
||||
END_SYNCHRONIZED;
|
||||
|
||||
} else {
|
||||
// no locking
|
||||
response = [self _handleRequest:aRequest];
|
||||
}
|
||||
|
||||
[application _setContext:nil];
|
||||
|
||||
return response;
|
||||
};
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
-(GSWResponse*)lockedDispatchWithPreparedApplication:(GSWApplication*)application
|
||||
inContext:(GSWContext*)aContext
|
||||
elements:(NSDictionary*)elements
|
||||
{
|
||||
//OK
|
||||
GSWResponse* response=nil;
|
||||
GSWResponse* errorResponse=nil;
|
||||
GSWSession* session=nil;
|
||||
NSString* sessionID=nil;
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
sessionID=[elements objectForKey:GSWKey_SessionID[GSWebNamingConv]];
|
||||
|
||||
if (sessionID)
|
||||
{
|
||||
session=[application restoreSessionWithID:sessionID
|
||||
inContext:aContext];
|
||||
if (!session)
|
||||
{
|
||||
// check for refuseNewSessions
|
||||
errorResponse=[application handleSessionRestorationErrorInContext:aContext];
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
// check for refuseNewSessions
|
||||
session=[application _initializeSessionInContext:aContext];
|
||||
}
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException,
|
||||
@"in session create/restore");
|
||||
LOGException(@"exception=%@",localException);
|
||||
errorResponse=[application handleException:localException
|
||||
inContext:aContext];
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
if (!response && !errorResponse)
|
||||
{
|
||||
if (session)
|
||||
{
|
||||
NS_DURING
|
||||
{
|
||||
response=[self lockedDispatchWithPreparedSession:session
|
||||
inContext:aContext
|
||||
elements:elements];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException,
|
||||
@"in lockedDispatchWithPreparedSession");
|
||||
LOGException(@"exception=%@",localException);
|
||||
errorResponse=[application handleException:localException
|
||||
inContext:aContext];
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
};
|
||||
};
|
||||
//======LAST //CLEAN
|
||||
if (response || errorResponse)
|
||||
{
|
||||
RETAIN(response);
|
||||
[aContext _putAwakeComponentsToSleep];
|
||||
[application saveSessionForContext:aContext];
|
||||
AUTORELEASE(response);
|
||||
};
|
||||
|
||||
return response ? response : errorResponse;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
-(GSWResponse*)lockedDispatchWithPreparedSession:(GSWSession*)aSession
|
||||
inContext:(GSWContext*)aContext
|
||||
elements:(NSDictionary*)elements
|
||||
{
|
||||
//OK
|
||||
GSWResponse* errorResponse=nil;
|
||||
GSWResponse* response=nil;
|
||||
GSWComponent* page=nil;
|
||||
BOOL storesIDsInCookies=NO;
|
||||
NSString* contextID=nil;
|
||||
|
||||
storesIDsInCookies=[aSession storesIDsInCookies]; //For What ?
|
||||
|
||||
contextID=[elements objectForKey:GSWKey_ContextID[GSWebNamingConv]];//use aContext requestContextID instead ?
|
||||
|
||||
if (contextID) // ??
|
||||
{
|
||||
NSAssert([contextID length]>0,@"contextID empty");
|
||||
page=[self lockedRestorePageForContextID:contextID
|
||||
inSession:aSession];
|
||||
if (!page)
|
||||
{
|
||||
GSWApplication* application=[aSession application];
|
||||
errorResponse=[application handlePageRestorationErrorInContext:aContext];
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString* pageName=[elements objectForKey:GSWKey_PageName[GSWebNamingConv]];
|
||||
NSException* exception=nil;
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
page=[[GSWApplication application] pageWithName:pageName
|
||||
inContext:aContext];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException,
|
||||
@"In pageWithName");
|
||||
LOGException(@"exception=%@",localException);
|
||||
ASSIGN(exception,localException);
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
if (!page)
|
||||
{
|
||||
errorResponse=[[GSWApplication application] handleException:exception
|
||||
inContext:aContext];
|
||||
};
|
||||
DESTROY(exception);
|
||||
};
|
||||
if (!response && !errorResponse && page)
|
||||
{
|
||||
[aContext _setPageElement:page];
|
||||
response=[self lockedDispatchWithPreparedPage:page
|
||||
inSession:aSession
|
||||
inContext:aContext
|
||||
elements:elements];
|
||||
};
|
||||
if (response)
|
||||
{
|
||||
BOOL isPageRefreshOnBacktrackEnabled=[[GSWApplication application] isPageRefreshOnBacktrackEnabled];
|
||||
if (isPageRefreshOnBacktrackEnabled)
|
||||
[response disableClientCaching];
|
||||
|
||||
[aSession _saveCurrentPage];
|
||||
#if 0
|
||||
if (!contextID) // ??
|
||||
{
|
||||
if (![aSession storesIDsInCookies])//??
|
||||
[aSession clearCookieFromResponse:response];
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
return response ? response : errorResponse;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
-(GSWResponse*)lockedDispatchWithPreparedPage:(GSWComponent*)aComponent
|
||||
inSession:(GSWSession*)aSession
|
||||
inContext:(GSWContext*)aContext
|
||||
elements:(NSDictionary*)elements
|
||||
{
|
||||
//OK
|
||||
GSWRequest* request=nil;
|
||||
GSWResponse* response=nil;
|
||||
GSWResponse* errorResponse=nil;
|
||||
NSString* senderID=nil;
|
||||
NSString* contextID=nil;
|
||||
NSString* httpVersion=nil;
|
||||
GSWComponent* page=nil;
|
||||
GSWComponent* responsePage=nil;
|
||||
BOOL isFromClientComponent=NO;
|
||||
BOOL hasFormValues=NO;
|
||||
GSWContext* responseContext=nil;
|
||||
GSWComponent* responsePageElement=nil;
|
||||
GSWRequest* responseRequest=nil;
|
||||
NSString* matchingContextID=nil;
|
||||
|
||||
request=[aContext request];
|
||||
contextID=[elements objectForKey:GSWKey_ContextID[GSWebNamingConv]];
|
||||
|
||||
response=[GSWApp createResponseInContext:aContext];
|
||||
|
||||
senderID=GSWContext_senderID(aContext);
|
||||
|
||||
matchingContextID=[aSession _contextIDMatchingIDsInContext:aContext];
|
||||
|
||||
httpVersion=[request httpVersion];
|
||||
[response setHTTPVersion:httpVersion];
|
||||
[response setAcceptedEncodings:[request browserAcceptedEncodings]];
|
||||
[response setHeader:@"text/html"
|
||||
forKey:@"content-type"];
|
||||
[aContext _setResponse:response];
|
||||
|
||||
if (matchingContextID)
|
||||
{
|
||||
page = [self lockedRestorePageForContextID:matchingContextID
|
||||
inSession:aSession];
|
||||
[aContext _setPageElement:page];
|
||||
[GSWApp appendToResponse:response
|
||||
inContext:aContext];
|
||||
}
|
||||
else
|
||||
{
|
||||
page=[aContext page];
|
||||
if (contextID)//??
|
||||
{
|
||||
hasFormValues=[request _hasFormValues];
|
||||
}
|
||||
else
|
||||
{
|
||||
[aContext _setPageChanged:NO];
|
||||
isFromClientComponent=[request isFromClientComponent];
|
||||
//??
|
||||
[aContext _setPageReplaced:NO];
|
||||
isFromClientComponent=[request isFromClientComponent];
|
||||
};
|
||||
if (hasFormValues)
|
||||
{
|
||||
NSAssert([GSWContext_elementID(aContext) length]==0,
|
||||
@"1 lockedDispatchWithPreparedPage elementID length>0");
|
||||
[GSWApp takeValuesFromRequest:request
|
||||
inContext:aContext];
|
||||
if (![GSWContext_elementID(aContext) length]==0)
|
||||
{
|
||||
LOGSeriousError0(@"2 lockedDispatchWithPreparedPage elementID length>0");
|
||||
GSWContext_deleteAllElementIDComponents(aContext);//NDFN
|
||||
};
|
||||
[aContext _setPageChanged:NO];//???
|
||||
isFromClientComponent=[request isFromClientComponent];
|
||||
[aContext _setPageReplaced:NO];
|
||||
};
|
||||
if (senderID) //??
|
||||
{
|
||||
BOOL pageChanged=NO;
|
||||
NSException* exception=nil;
|
||||
|
||||
NSAssert([GSWContext_elementID(aContext) length]==0,
|
||||
@"3 lockedDispatchWithPreparedPage elementID length>0");
|
||||
// Exception catching here ?
|
||||
NS_DURING
|
||||
{
|
||||
responsePage=(GSWComponent*)[GSWApp invokeActionForRequest:request
|
||||
inContext:aContext];
|
||||
|
||||
NSAssert([GSWContext_elementID(aContext) length]==0,@"4 lockedDispatchWithPreparedPage elementID length>0");
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
LOGException0(@"exception in invokeActionForRequest");
|
||||
LOGException(@"exception=%@",localException);
|
||||
localException=ExceptionByAddingUserInfoObjectFrameInfo(localException,
|
||||
@"In invokeActionForRequest component=%@ of Class %@",
|
||||
[aComponent name],
|
||||
[aComponent class]);
|
||||
LOGException(@"exception=%@",localException);
|
||||
ASSIGN(exception,localException);
|
||||
if (!responsePage)
|
||||
{
|
||||
errorResponse=[[GSWApplication application] handleException:exception
|
||||
inContext:aContext];
|
||||
};
|
||||
DESTROY(exception);
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
|
||||
if (errorResponse)
|
||||
{
|
||||
response=errorResponse;
|
||||
responseContext=aContext;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!responsePage)
|
||||
responsePage=page;
|
||||
|
||||
responseContext=[(GSWComponent*)responsePage context];//So what ?
|
||||
[responseContext _setPageReplaced:NO];
|
||||
responsePageElement=(GSWComponent*)[responseContext _pageElement];
|
||||
pageChanged=(responsePage!=responsePageElement);
|
||||
[responseContext _setPageChanged:pageChanged];//??
|
||||
if (pageChanged)
|
||||
{
|
||||
[responseContext _setPageElement:responsePage];
|
||||
};
|
||||
responseRequest=[responseContext request];//SoWhat ?
|
||||
[responseRequest isFromClientComponent];//SoWhat
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
responseContext=aContext;
|
||||
responsePageElement=page;
|
||||
responsePage=aComponent;
|
||||
responseRequest=request;
|
||||
};
|
||||
if (!errorResponse)
|
||||
{
|
||||
NS_DURING
|
||||
{
|
||||
NSAssert([GSWContext_elementID(aContext) length]==0,
|
||||
@"5 lockedDispatchWithPreparedPage elementID length>0");
|
||||
[GSWApp appendToResponse:response
|
||||
inContext:responseContext];
|
||||
NSAssert([GSWContext_elementID(aContext) length]==0,
|
||||
@"6 lockedDispatchWithPreparedPage elementID length>0");
|
||||
responseRequest=[responseContext request];//SoWhat ?
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
localException=ExceptionByAddingUserInfoObjectFrameInfo(localException,
|
||||
@"In appendToResponse page=%@ of Class %@",
|
||||
[page name],
|
||||
[page class]);
|
||||
LOGException(@"exception=%@",localException);
|
||||
errorResponse=[[GSWApplication application] handleException:localException
|
||||
inContext:aContext];
|
||||
}
|
||||
NS_ENDHANDLER;
|
||||
};
|
||||
};
|
||||
|
||||
return errorResponse ? errorResponse : response;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
-(GSWComponent*)lockedRestorePageForContextID:(NSString*)aContextID
|
||||
inSession:(GSWSession*)aSession
|
||||
{
|
||||
//OK
|
||||
GSWComponent* page=[aSession restorePageForContextID:aContextID];
|
||||
return page;
|
||||
};
|
||||
|
||||
@end
|
||||
|
||||
//====================================================================
|
||||
@implementation GSWComponentRequestHandler (GSWRequestHandlerClassA)
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// do we need this? -- dw
|
||||
+(id)handler
|
||||
{
|
||||
return [[GSWComponentRequestHandler new] autorelease];
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
+(NSDictionary*)_requestHandlerValuesForRequest:(GSWRequest*)aRequest
|
||||
{
|
||||
//OK
|
||||
NSDictionary* values=nil;
|
||||
|
||||
NS_DURING
|
||||
{
|
||||
values=[aRequest uriOrFormOrCookiesElements];
|
||||
}
|
||||
NS_HANDLER
|
||||
{
|
||||
localException=ExceptionByAddingUserInfoObjectFrameInfo0(localException,@"In +_requestHandlerValuesForRequest:");
|
||||
LOGException(@"exception=%@",localException);
|
||||
[localException raise];
|
||||
};
|
||||
NS_ENDHANDLER;
|
||||
|
||||
return values;
|
||||
};
|
||||
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -141,8 +141,8 @@ GSWEB_EXPORT NSString* GSWHTTPHeader_RecordingSessionID[2];
|
|||
GSWEB_EXPORT NSString* GSWHTTPHeader_RecordingIDsURL[2];
|
||||
GSWEB_EXPORT NSString* GSWHTTPHeader_RecordingIDsCookie[2];
|
||||
GSWEB_EXPORT NSString* GSWHTTPHeader_RecordingApplicationNumber[2];
|
||||
GSWEB_EXPORT NSString* GSWHTTPHeader_LoadAverage[2];
|
||||
GSWEB_EXPORT NSString* GSWHTTPHeader_RefuseSessions[2];
|
||||
GSWEB_EXPORT NSString* GSWHTTPHeader_LoadAverage;
|
||||
GSWEB_EXPORT NSString* GSWHTTPHeader_RefuseSessions;
|
||||
|
||||
// Header key to return statistics to Adaptor
|
||||
GSWEB_EXPORT NSString* GSWHTTPHeader_AdaptorStats[2];
|
||||
|
|
|
@ -140,8 +140,8 @@ NSString* GSWHTTPHeader_RecordingSessionID[2]={ @"x-gsweb-session-id", @"x-webob
|
|||
NSString* GSWHTTPHeader_RecordingIDsURL[2]={ @"x-gsweb-ids-url", @"x-webobjects-ids-url" };
|
||||
NSString* GSWHTTPHeader_RecordingIDsCookie[2]={ @"x-gsweb-ids-url", @"x-webobjects-ids-cookie" };
|
||||
NSString* GSWHTTPHeader_RecordingApplicationNumber[2]={ @"x-gsweb-application-number", @"x-webobjects-application-number" };
|
||||
NSString* GSWHTTPHeader_LoadAverage[2] = { @"x-gsweb-loadaverage", @"x-webobjects-loadaverage" };
|
||||
NSString* GSWHTTPHeader_RefuseSessions[2] = { @"x-gsweb-refusenewsessions", @"x-webobjects-refusenewsessions" };
|
||||
NSString* GSWHTTPHeader_LoadAverage = @"x-webobjects-loadaverage";
|
||||
NSString* GSWHTTPHeader_RefuseSessions = @"x-webobjects-refusenewsessions";
|
||||
NSString* GSWHTTPHeader_AdaptorStats[2] = { @"x-gsweb-adaptorstats", @"x-webobjects-adaptorstats" };
|
||||
|
||||
NSString* GSWHTTPHeader_MethodPost=@"POST";
|
||||
|
|
|
@ -77,5 +77,11 @@ static inline void GSWeb_appendStringWithImpPtr(NSMutableString* object,IMP* imp
|
|||
inContext:(GSWContext*)context;
|
||||
@end
|
||||
|
||||
@interface GSWResponse (PrivateDeclarations)
|
||||
|
||||
- (void) _redirectResponse:(NSString *) location contentString:(NSString *) content;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#endif // _GSWPrivate_h__
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#ifndef _GSWRequestHandler_h__
|
||||
#define _GSWRequestHandler_h__
|
||||
|
||||
#define DidHandleRequestNotification "WORequestHandlerDidHandleRequestNotification"
|
||||
#define DidHandleRequestNotification @"WORequestHandlerDidHandleRequestNotification"
|
||||
|
||||
|
||||
//====================================================================
|
||||
|
|
|
@ -34,6 +34,7 @@ RCS_ID("$Id$")
|
|||
|
||||
#include "GSWeb.h"
|
||||
#include "NSData+Compress.h"
|
||||
#include "GSWPrivate.h"
|
||||
|
||||
//====================================================================
|
||||
@implementation GSWResponse
|
||||
|
@ -228,7 +229,20 @@ void GSWResponse_appendTagAttributeValueEscapingHTMLAttributeValue(GSWResponse*
|
|||
(void*)_userInfo];
|
||||
LOGObjectFnStop();
|
||||
return description;
|
||||
};
|
||||
}
|
||||
|
||||
// it seems that in WO, this is a class method, which makes no sense
|
||||
- (void) _redirectResponse:(NSString *) location contentString:(NSString *) content
|
||||
{
|
||||
GSWResponse_appendContentString(self, content);
|
||||
[self setStatus:302];
|
||||
[self setHeader:location
|
||||
forKey:@"Location"];
|
||||
[self setHeader:@"YES"
|
||||
forKey:@"x-webobjects-refusing-redirection"];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
|
||||
//====================================================================
|
||||
|
@ -332,15 +346,15 @@ void GSWResponse_appendTagAttributeValueEscapingHTMLAttributeValue(GSWResponse*
|
|||
[self _finalizeCookiesInContext:aContext];
|
||||
|
||||
// Add load info to headers
|
||||
if (![self headersForKey:GSWHTTPHeader_LoadAverage[GSWebNamingConv]])
|
||||
if (![self headersForKey:GSWHTTPHeader_LoadAverage])
|
||||
[self setHeader:GSWIntToNSString([GSWApp activeSessionsCount])
|
||||
forKey:GSWHTTPHeader_LoadAverage[GSWebNamingConv]];
|
||||
forKey:GSWHTTPHeader_LoadAverage];
|
||||
|
||||
// Add refusing new sessions info to headers
|
||||
if ([GSWApp isRefusingNewSessions]
|
||||
&& ![self headersForKey:GSWHTTPHeader_RefuseSessions[GSWebNamingConv]])
|
||||
&& ![self headersForKey:GSWHTTPHeader_RefuseSessions])
|
||||
[self setHeader:GSWIntToNSString((int)[GSWApp _refuseNewSessionsTimeInterval])
|
||||
forKey:GSWHTTPHeader_RefuseSessions[GSWebNamingConv]];
|
||||
forKey:GSWHTTPHeader_RefuseSessions];
|
||||
|
||||
[self _finalizeContentEncodingInContext:aContext];
|
||||
|
||||
|
@ -673,7 +687,7 @@ escapingHTMLAttributeValue:(BOOL)escape
|
|||
forRequest:nil];
|
||||
LOGClassFnStop();
|
||||
return response;
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
|
Loading…
Reference in a new issue