mirror of
https://github.com/gnustep/libs-sqlclient.git
synced 2025-02-21 02:41:07 +00:00
Various minor improvements in handling incoming requests.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@20362 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
6c0902f3ae
commit
80a269bbde
4 changed files with 180 additions and 56 deletions
|
@ -1,3 +1,10 @@
|
|||
Fri Nov 19 14:40:00 2004 Richard Frith-Macdonald <rfm@gnu.org>
|
||||
|
||||
* WebServer.m: parse basic authentication infor and set it in extra
|
||||
headers in request.
|
||||
* WebServerBundles.m: support handling of paths longer than the
|
||||
ones set for each bundle.
|
||||
|
||||
Tue Nov 11 14:48:05 2004 Nicola Pero <n.pero@mi.flashnet.it>
|
||||
|
||||
* GNUmakefile (BUNDLE_INSTALL_DIR): install bundles in
|
||||
|
|
45
WebServer.h
45
WebServer.h
|
@ -91,6 +91,12 @@
|
|||
* <desc>The IP address of the host that the request came from.</desc>
|
||||
* <term>x-remote-port</term>
|
||||
* <desc>The port of the host that the request came from.</desc>
|
||||
* <term>x-http-username</term>
|
||||
* <desc>The username from the 'authorization' header if the request
|
||||
* supplied http basic authentication.</desc>
|
||||
* <term>x-http-password</term>
|
||||
* <desc>The password from the 'authorization' header if the request
|
||||
* supplied http basic authentication.</desc>
|
||||
* </deflist>
|
||||
* On completion, the method must modify response to contain the data
|
||||
* and headers to be sent out.<br />
|
||||
|
@ -387,7 +393,15 @@
|
|||
* supplied in the request. The WebServerBundles intance is responsible
|
||||
* for loading the bundles (based on information in the WebServerBundles
|
||||
* dictionary in the user defaults system) and for forwarding requests
|
||||
* to the appropriate bundles for processing.
|
||||
* to the appropriate bundles for processing.<br />
|
||||
* If a request comes in which is not an exact match for the path of any
|
||||
* handler, the request path is repeatedly shortened by chopping off the
|
||||
* last path component until a matching handler is found.<br />
|
||||
* The paths in the dictionary must <em>not</em> end with a slash...
|
||||
* an empty string will match all requests which do not match a handler
|
||||
* with a longer path.
|
||||
* <example>
|
||||
* </example>
|
||||
*/
|
||||
@interface WebServerBundles : NSObject <WebServerDelegate>
|
||||
{
|
||||
|
@ -408,12 +422,27 @@
|
|||
* HTTPS server rather than an HTTP server.
|
||||
* See [WebServer-setPort:secure:] for details.
|
||||
* </item>
|
||||
* <item>
|
||||
* WebServerBundles is a dictionary keyed on path strings, whose
|
||||
* values are dictionaries, each containing per-handler configuration
|
||||
* information and the name of the bundle containing the code to handle
|
||||
* requests sent to the path. NB. the bundle name listed should
|
||||
* omit the <code>.bundle</code> extension.
|
||||
* </item>
|
||||
* </list>
|
||||
* Returns YES on success, NO on failure (if the port of the WebServer
|
||||
* cannot be set).
|
||||
*/
|
||||
- (BOOL) defaultsUpdate: (NSNotification *)aNotification;
|
||||
|
||||
/**
|
||||
* Returns the handler to be used for the specified path, or nil if there
|
||||
* is no handler available.<br />
|
||||
* If the info argument is non-null, it is used to return additional
|
||||
* information, either the path actually matched, or an error string.
|
||||
*/
|
||||
- (id) handlerForPath: (NSString*)path info: (NSString**)info;
|
||||
|
||||
/**
|
||||
* Return dictionary of all handlers by name (path in request which maps
|
||||
* to that handler instance).
|
||||
|
@ -421,7 +450,7 @@
|
|||
- (NSMutableDictionary*) handlers;
|
||||
|
||||
/**
|
||||
* Return the WebServer instance that the receiver is actiang as a
|
||||
* Return the WebServer instance that the receiver is acting as a
|
||||
* delegate for.
|
||||
*/
|
||||
- (WebServer*) http;
|
||||
|
@ -442,12 +471,22 @@
|
|||
* information listing the bundle containing the handler to be used.<br />
|
||||
* The configuration information is a dictionary containing the name
|
||||
* of the bundle (keyed on 'Name'), and this is used to locate the
|
||||
* bundle in the applications resources.
|
||||
* bundle in the applications resources.<br />
|
||||
* Before a request is passed on to a handler, two extra headers are set
|
||||
* in it ... <code>x-http-path-base</code> and <code>x-http-path-info</code>
|
||||
* being the actual path matched for the handler, and the remainder of the
|
||||
* path after that base part.
|
||||
*/
|
||||
- (BOOL) processRequest: (GSMimeDocument*)request
|
||||
response: (GSMimeDocument*)response
|
||||
for: (WebServer*)http;
|
||||
|
||||
/**
|
||||
* Registers an object as the handler for a particular path.<br />
|
||||
* Registering a nil handler destroys any existing handler for the path.
|
||||
*/
|
||||
- (void) registerHandler: (id)handler forPath: (NSString*)path;
|
||||
|
||||
/**
|
||||
* Just write to stderr using NSLog.
|
||||
*/
|
||||
|
|
23
WebServer.m
23
WebServer.m
|
@ -1235,6 +1235,7 @@ unescapeData(const unsigned char* bytes, unsigned length, unsigned char *buf)
|
|||
GSMimeDocument *request;
|
||||
GSMimeDocument *response;
|
||||
BOOL responded = NO;
|
||||
NSString *str;
|
||||
NSString *con;
|
||||
NSMutableData *raw;
|
||||
NSMutableData *out;
|
||||
|
@ -1274,6 +1275,28 @@ unescapeData(const unsigned char* bytes, unsigned length, unsigned char *buf)
|
|||
value: [[session handle] socketService]
|
||||
parameters: nil];
|
||||
|
||||
str = [[request headerNamed: @"authorization"] value];
|
||||
if ([str length] > 6 && [[str substringToIndex: 6] caseInsensitiveCompare:
|
||||
@"Basic "] == NSOrderedSame)
|
||||
{
|
||||
str = [[str substringFromIndex: 6] stringByTrimmingSpaces];
|
||||
str = [GSMimeDocument decodeBase64String: str];
|
||||
if ([str length] > 0)
|
||||
{
|
||||
NSRange r = [str rangeOfString: @":"];
|
||||
|
||||
if (r.length > 0)
|
||||
{
|
||||
[request setHeader: @"x-http-username"
|
||||
value: [str substringToIndex: r.location]
|
||||
parameters: nil];
|
||||
[request setHeader: @"x-http-password"
|
||||
value: [str substringFromIndex: NSMaxRange(r)]
|
||||
parameters: nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response = AUTORELEASE([GSMimeDocument new]);
|
||||
[response setContent: [NSData data] type: @"text/plain" name: nil];
|
||||
|
||||
|
|
|
@ -48,6 +48,82 @@
|
|||
return [_http setPort: port secure: secure];
|
||||
}
|
||||
|
||||
- (id) handlerForPath: (NSString*)path info: (NSString**)info
|
||||
{
|
||||
NSString *error = nil;
|
||||
NSMutableDictionary *handlers;
|
||||
id handler;
|
||||
|
||||
if (info != 0)
|
||||
{
|
||||
*info = path;
|
||||
}
|
||||
handlers = [self handlers];
|
||||
handler = [handlers objectForKey: path];
|
||||
if (handler == nil)
|
||||
{
|
||||
NSUserDefaults *defs;
|
||||
NSDictionary *conf;
|
||||
NSDictionary *byPath;
|
||||
|
||||
defs = [NSUserDefaults standardUserDefaults];
|
||||
conf = [defs dictionaryForKey: @"WebServerBundles"];
|
||||
byPath = [conf objectForKey: path];
|
||||
if ([byPath isKindOfClass: [NSDictionary class]] == NO)
|
||||
{
|
||||
NSRange r;
|
||||
|
||||
r = [path rangeOfString: @"/" options: NSBackwardsSearch];
|
||||
if (r.length > 0)
|
||||
{
|
||||
path = [path substringToIndex: r.location];
|
||||
handler = [self handlerForPath: path info: info];
|
||||
}
|
||||
else
|
||||
{
|
||||
error = [NSString stringWithFormat:
|
||||
@"Unable to find handler in Bundles config for '%@'", path];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *name;
|
||||
|
||||
name = [byPath objectForKey: @"Name"];
|
||||
|
||||
if ([name length] == 0)
|
||||
{
|
||||
error = [NSString stringWithFormat:
|
||||
@"Unable to find Name in Bundles config for '%@'", path];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSBundle *mb = [NSBundle mainBundle];
|
||||
NSString *p = [mb pathForResource: name ofType: @"bundle"];
|
||||
NSBundle *b = [NSBundle bundleWithPath: p];
|
||||
Class c = [b principalClass];
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
error = [NSString stringWithFormat:
|
||||
@"Unable to find class in '%@' for '%@'", p, path];
|
||||
}
|
||||
else
|
||||
{
|
||||
handler = [c new];
|
||||
[self registerHandler: handler forPath: path];
|
||||
RELEASE(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (handler == nil && info != 0)
|
||||
{
|
||||
*info = error;
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
- (NSMutableDictionary*) handlers
|
||||
{
|
||||
if (_handlers == nil)
|
||||
|
@ -109,67 +185,21 @@
|
|||
response: (GSMimeDocument*)response
|
||||
for: (WebServer*)http
|
||||
{
|
||||
NSString *error;
|
||||
NSString *path;
|
||||
NSMutableDictionary *handlers;
|
||||
NSString *info;
|
||||
id handler;
|
||||
|
||||
path = [[request headerNamed: @"x-http-path"] value];
|
||||
handlers = [self handlers];
|
||||
handler = [handlers objectForKey: path];
|
||||
if (handler == nil)
|
||||
{
|
||||
NSUserDefaults *defs;
|
||||
NSDictionary *conf;
|
||||
NSDictionary *byPath;
|
||||
|
||||
defs = [NSUserDefaults standardUserDefaults];
|
||||
conf = [defs dictionaryForKey: @"WebServerBundles"];
|
||||
byPath = [conf objectForKey: path];
|
||||
if ([byPath isKindOfClass: [NSDictionary class]] == NO)
|
||||
{
|
||||
error = [NSString stringWithFormat:
|
||||
@"Unable to find Bundles config for '%@'", path];
|
||||
[self webAlert: error for: http];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *name;
|
||||
|
||||
name = [byPath objectForKey: @"Name"];
|
||||
|
||||
if ([name length] == 0)
|
||||
{
|
||||
error = [NSString stringWithFormat:
|
||||
@"Unable to find Name in Bundles config for '%@'", path];
|
||||
[self webAlert: error for: http];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSBundle *mb = [NSBundle mainBundle];
|
||||
NSString *p = [mb pathForResource: name ofType: @"bundle"];
|
||||
NSBundle *b = [NSBundle bundleWithPath: p];
|
||||
Class c = [b principalClass];
|
||||
|
||||
if (c == 0)
|
||||
{
|
||||
error = [NSString stringWithFormat:
|
||||
@"Unable to find class in '%@' for '%@'", p, path];
|
||||
[self webAlert: error for: http];
|
||||
}
|
||||
else
|
||||
{
|
||||
handler = [c new];
|
||||
[handlers setObject: handler forKey: path];
|
||||
RELEASE(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
handler = [self handlerForPath: path info: &info];
|
||||
if (handler == nil)
|
||||
{
|
||||
NSString *error = @"bad path";
|
||||
|
||||
/*
|
||||
* Log the error message.
|
||||
*/
|
||||
[self webAlert: info for: (WebServer*)http];
|
||||
|
||||
/*
|
||||
* Return status code 400 (Bad Request) with the informative error
|
||||
*/
|
||||
|
@ -179,12 +209,37 @@
|
|||
}
|
||||
else
|
||||
{
|
||||
NSString *extra = [path substringFromIndex: [info length]];
|
||||
|
||||
/*
|
||||
* Provide extra information about the exact path used to match
|
||||
* the handler, and any remaining path information beyond it.
|
||||
*/
|
||||
[request setHeader: @"x-http-path-base"
|
||||
value: info
|
||||
parameters: nil];
|
||||
[request setHeader: @"x-http-path-info"
|
||||
value: extra
|
||||
parameters: nil];
|
||||
|
||||
return [handler processRequest: request
|
||||
response: response
|
||||
for: http];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) registerHandler: (id)handler forPath: (NSString*)path
|
||||
{
|
||||
if (handler == nil)
|
||||
{
|
||||
[[self handlers] removeObjectForKey: path];
|
||||
}
|
||||
else
|
||||
{
|
||||
[[self handlers] setObject: handler forKey: path];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) webAlert: (NSString*)message for: (WebServer*)http
|
||||
{
|
||||
NSLog(@"%@", message);
|
||||
|
|
Loading…
Reference in a new issue