fix to reture respnse for synchronous request.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@33949 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2011-10-07 09:17:14 +00:00
parent c71ffe21e9
commit 04c72fb364
4 changed files with 88 additions and 96 deletions

View file

@ -1,3 +1,10 @@
2011-10-07 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSURLProtocol.m:
* Source/NSURLConnection.m:
Ensure that a synchronous load returns the response.
* Tests/base/NSURLConnection/basic.m: add test for above change.
2011-10-04 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSURL.h: Document that methods creating file URLs

View file

@ -28,108 +28,69 @@
#import "Foundation/NSRunLoop.h"
#import "GSURLPrivate.h"
@interface _NSURLConnectionDataCollector : NSObject <NSURLProtocolClient>
@interface _NSURLConnectionDataCollector : NSObject
{
NSURLConnection *_connection; // Not retained
NSMutableData *_data;
NSError **_error;
NSURLResponse **_response;
NSError *_error;
NSURLResponse *_response;
BOOL _done;
}
- (id) initWithResponsePointer: (NSURLResponse **)response
andErrorPointer: (NSError **)error;
- (NSData*) _data;
- (BOOL) _done;
- (void) _setConnection: (NSURLConnection *)c;
- (NSData*) data;
- (BOOL) done;
- (NSError*) error;
- (NSURLResponse*) response;
- (void) setConnection: (NSURLConnection *)c;
@end
@implementation _NSURLConnectionDataCollector
- (id) initWithResponsePointer: (NSURLResponse **)response
andErrorPointer: (NSError **)error
{
if ((self = [super init]) != nil)
{
_response = response;
_error = error;
}
return self;
}
- (void) dealloc
{
RELEASE(_data);
[_data release];
[_error release];
[_response release];
[super dealloc];
}
- (BOOL) _done
- (BOOL) done
{
return _done;
}
- (NSData*) _data
- (NSData*) data
{
return _data;
}
- (void) _setConnection: (NSURLConnection*)c
- (NSError*) error
{
return _error;
}
- (NSURLResponse*) response
{
return _response;
}
- (void) setConnection: (NSURLConnection*)c
{
_connection = c;
}
// notification handler
- (void) URLProtocol: (NSURLProtocol*)proto
cachedResponseIsValid: (NSCachedURLResponse*)resp
{
return;
}
- (void) URLProtocol: (NSURLProtocol*)proto
didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge
{
return;
}
- (void) URLProtocol: (NSURLProtocol*)proto
didCancelAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge
{
return;
}
- (void) URLProtocol: (NSURLProtocol*)proto
wasRedirectedToRequest: (NSURLRequest*)request
redirectResponse: (NSURLResponse*)redirectResponse
{
return;
}
- (void) URLProtocol: (NSURLProtocol*)proto
didFailWithError: (NSError*)error
{
*_error = error;
_done = YES;
}
- (void) connection: (NSURLConnection *)connection
didFailWithError: (NSError *)error
{
*_error = error;
ASSIGN(_error, error);
_done = YES;
}
- (void) URLProtocol: (NSURLProtocol*)proto
didReceiveResponse: (NSURLResponse*)response
cacheStoragePolicy: (NSURLCacheStoragePolicy)policy
- (void) connection: (NSURLConnection *)connection
didReceiveResponse: (NSURLResponse*)response
{
*_response = response;
}
- (void) URLProtocolDidFinishLoading: (NSURLProtocol*)proto
{
_done = YES;
ASSIGN(_response, response);
}
- (void) connectionDidFinishLoading: (NSURLConnection *)connection
@ -138,23 +99,10 @@ redirectResponse: (NSURLResponse*)redirectResponse
}
- (void) URLProtocol: (NSURLProtocol*)proto
didLoadData: (NSData*)data
{
if (_data == nil)
{
_data = [data mutableCopy];
}
else
{
[_data appendData: data];
}
}
- (void) connection: (NSURLConnection *)connection
didReceiveData: (NSData *)data
{
if (_data == nil)
if (nil == _data)
{
_data = [data mutableCopy];
}
@ -320,20 +268,26 @@ typedef struct
{
NSData *data = nil;
if (0 != response)
{
*response = nil;
}
if (0 != error)
{
*error = nil;
}
if ([self canHandleRequest: request] == YES)
{
_NSURLConnectionDataCollector *collector;
NSURLConnection *conn;
NSRunLoop *loop;
collector = [_NSURLConnectionDataCollector alloc];
collector = [collector initWithResponsePointer: response
andErrorPointer: error];
collector = [_NSURLConnectionDataCollector new];
conn = [self alloc];
conn = [conn initWithRequest: request delegate: AUTORELEASE(collector)];
[collector _setConnection: conn];
conn = [conn initWithRequest: request delegate: [collector autorelease]];
[collector setConnection: conn];
loop = [NSRunLoop currentRunLoop];
while ([collector _done] == NO)
while ([collector done] == NO)
{
NSDate *limit;
@ -341,10 +295,18 @@ typedef struct
[loop runMode: NSDefaultRunLoopMode beforeDate: limit];
RELEASE(limit);
}
data = RETAIN([collector _data]);
data = [[[collector data] retain] autorelease];
if (0 != response)
{
*response = [[[collector response] retain] autorelease];
}
if (0 != error)
{
*error = [[[collector error] retain] autorelease];
}
[conn release];
}
return AUTORELEASE(data);
return data;
}
@end
@ -355,7 +317,7 @@ typedef struct
- (void) URLProtocol: (NSURLProtocol *)protocol
cachedResponseIsValid: (NSCachedURLResponse *)cachedResponse
{
return;
}
- (void) URLProtocol: (NSURLProtocol *)protocol
@ -374,7 +336,7 @@ typedef struct
didReceiveAuthenticationChallenge: (NSURLAuthenticationChallenge *)challenge
{
[this->_delegate connection: self
didReceiveAuthenticationChallenge: challenge];
didReceiveAuthenticationChallenge: challenge];
}
- (void) URLProtocol: (NSURLProtocol *)protocol

View file

@ -679,10 +679,15 @@ static NSURLProtocol *placeholder = nil;
wasRedirectedToRequest: request
redirectResponse: nil];
}
if (_isLoading == NO)
if (NO == _isLoading)
{
return;
return; // Loading cancelled
}
if (nil != this->input)
{
return; // Following redirection
}
// Fall through to continue original connect.
}
if (0 && this->cachedResponse)
@ -843,6 +848,8 @@ static NSURLProtocol *placeholder = nil;
GSMimeHeader *info;
NSString *enc;
int len = -1;
NSString *ct;
NSString *st;
NSString *s;
info = [document headerNamed: @"http"];
@ -878,11 +885,22 @@ static NSURLProtocol *placeholder = nil;
enc = [[document headerNamed: @"transfer-encoding"] value];
}
info = [document headerNamed: @"content-type"];
ct = [document contentType];
st = [document contentSubtype];
if (ct && st)
{
ct = [ct stringByAppendingFormat: @"/%@", st];
}
else
{
ct = nil;
}
_response = [[NSHTTPURLResponse alloc]
initWithURL: [this->request URL]
MIMEType: nil
MIMEType: ct
expectedContentLength: len
textEncodingName: nil];
textEncodingName: [info parameterForKey: @"charset"]];
[_response _setStatusCode: _statusCode text: s];
[document deleteHeaderNamed: @"http"];
[_response _setHeaders: [document allHeaders]];
@ -1237,7 +1255,8 @@ static NSURLProtocol *placeholder = nil;
IF_NO_GC([[self retain] autorelease];)
#if 0
NSLog(@"stream: %@ handleEvent: %x for: %@", stream, event, self);
NSLog(@"stream: %@ handleEvent: %x for: %@ (ip %p, op %p)",
stream, event, self, this->input, this->output);
#endif
if (stream == this->input)
@ -1479,6 +1498,7 @@ static NSURLProtocol *placeholder = nil;
}
if (_shouldClose == YES)
{
[this->output setDelegate: nil];
[this->output removeFromRunLoop:
[NSRunLoop currentRunLoop]
forMode: NSDefaultRunLoopMode];

View file

@ -30,11 +30,14 @@ int main()
PASS(connection != nil,
"NSURLConnection +connectionWithRequest: delegate: with nil as delegate returns a instance");
response = nil;
data = [NSURLConnection sendSynchronousRequest: mutable
returningResponse: &response
error: &error];
PASS(data != nil && [data length] > 0,
"NSURLConnection synchronously load data from an http URL");
PASS(response != nil && [response statusCode] > 0,
"NSURLConnection synchronous load returns a response");
path = [[NSFileManager defaultManager] currentDirectoryPath];
path = [path stringByAppendingPathComponent: @"basic.m"];