ObjFW  Diff

Differences From Artifact [65175ae100]:

  • File src/OFHTTPClient.m — part of check-in [6ad892733b] at 2013-07-29 19:42:12 on branch trunk — OFHTTPClient: Fix -[close] behaviour.

    -[OFHTTPClient close] now closes the connection, no matter whether a
    reply still exists. -[OFHTTPRequestReply close] only disposes of the
    reference to the socket now, so that if the OFHTTPClient does not exist
    anymore the socket is closed, but not if the OFHTTPClient is still alive
    and in keep-alive mode. This is important so that closing a single reply
    does not close the client even though keep-alive was used. (user: js, size: 14602) [annotate] [blame] [check-ins using]

To Artifact [326cb8d0c5]:


19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
19
20
21
22
23
24
25

26
27
28
29
30
31
32
33







-
+







#include <string.h>
#include <ctype.h>

#include <errno.h>

#import "OFHTTPClient.h"
#import "OFHTTPRequest.h"
#import "OFHTTPRequestReply.h"
#import "OFHTTPResponse.h"
#import "OFString.h"
#import "OFURL.h"
#import "OFTCPSocket.h"
#import "OFDictionary.h"
#import "OFDataArray.h"

#import "OFHTTPRequestFailedException.h"
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80

81
82
83
84
85
86
87
62
63
64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
79

80
81
82
83
84
85
86
87







-
+










-
+







		*str = (firstLetter ? toupper(*str) : tolower(*str));

		firstLetter = false;
		str++;
	}
}

@interface OFHTTPClientReply: OFHTTPRequestReply
@interface OFHTTPClientResponse: OFHTTPResponse
{
	OFTCPSocket *_socket;
	bool _hasContentLength, _chunked, _keepAlive, _atEndOfStream;
	size_t _toRead;
}

- initWithSocket: (OFTCPSocket*)socket;
- (void)setKeepAlive: (bool)keepAlive;
@end

@implementation OFHTTPClientReply
@implementation OFHTTPClientResponse
- initWithSocket: (OFTCPSocket*)socket
{
	self = [super init];

	_socket = [socket retain];

	return self;
279
280
281
282
283
284
285
286

287
288
289
290
291
292
293
279
280
281
282
283
284
285

286
287
288
289
290
291
292
293







-
+







}

- (bool)insecureRedirectsAllowed
{
	return _insecureRedirectsAllowed;
}

- (OFHTTPRequestReply*)performRequest: (OFHTTPRequest*)request
- (OFHTTPResponse*)performRequest: (OFHTTPRequest*)request
{
	return [self performRequest: request
			  redirects: 10];
}

- (OFTCPSocket*)OF_createSocketForRequest: (OFHTTPRequest*)request
{
314
315
316
317
318
319
320
321
322


323
324
325
326
327
328
329
330
331
332

333
334
335
336
337
338
339
314
315
316
317
318
319
320


321
322
323
324
325
326
327
328
329
330
331

332
333
334
335
336
337
338
339







-
-
+
+









-
+








	[socket connectToHost: [URL host]
			 port: [URL port]];

	return socket;
}

- (OFHTTPRequestReply*)performRequest: (OFHTTPRequest*)request
			    redirects: (size_t)redirects
- (OFHTTPResponse*)performRequest: (OFHTTPRequest*)request
			redirects: (size_t)redirects
{
	void *pool = objc_autoreleasePoolPush();
	OFURL *URL = [request URL];
	OFString *scheme = [URL scheme];
	of_http_request_type_t requestType = [request requestType];
	OFMutableString *requestString;
	OFDictionary *headers = [request headers];
	OFDataArray *POSTData = [request POSTData];
	OFTCPSocket *socket;
	OFHTTPClientReply *reply;
	OFHTTPClientResponse *response;
	OFString *line, *path, *version, *redirect, *keepAlive;
	OFMutableDictionary *serverHeaders;
	OFEnumerator *keyEnumerator, *objectEnumerator;
	OFString *key, *object;
	int status;
	const char *type = NULL;

352
353
354
355
356
357
358
359

360
361
362
363


364
365
366
367


368
369
370
371
372
373
374
352
353
354
355
356
357
358

359
360
361


362
363
364
365


366
367
368
369
370
371
372
373
374







-
+


-
-
+
+


-
-
+
+







		socket = [_socket autorelease];
		_socket = nil;

		[_lastURL release];
		_lastURL = nil;

		/* Throw away content that has not been read yet */
		while (![_lastReply isAtEndOfStream]) {
		while (![_lastResponse isAtEndOfStream]) {
			char buffer[512];

			[_lastReply readIntoBuffer: buffer
					    length: 512];
			[_lastResponse readIntoBuffer: buffer
					       length: 512];
		}

		[_lastReply release];
		_lastReply = nil;
		[_lastResponse release];
		_lastResponse = nil;
	} else
		socket = [self OF_createSocketForRequest: request];

	if (requestType == OF_HTTP_REQUEST_TYPE_GET)
		type = "GET";
	if (requestType == OF_HTTP_REQUEST_TYPE_HEAD)
		type = "HEAD";
536
537
538
539
540
541
542
543

544
545
546
547



548
549
550
551
552

553
554
555
556

557
558
559
560
561
562
563
536
537
538
539
540
541
542

543
544



545
546
547
548
549
550
551

552
553
554
555

556
557
558
559
560
561
562
563







-
+

-
-
-
+
+
+




-
+



-
+







	if ([_delegate respondsToSelector:
	    @selector(client:didReceiveHeaders:statusCode:request:)])
		[_delegate     client: self
		    didReceiveHeaders: serverHeaders
			   statusCode: status
			      request: request];

	reply = [[[OFHTTPClientReply alloc] initWithSocket: socket]
	response = [[[OFHTTPClientResponse alloc] initWithSocket: socket]
	    autorelease];
	[reply setProtocolVersionFromString: version];
	[reply setStatusCode: status];
	[reply setHeaders: serverHeaders];
	[response setProtocolVersionFromString: version];
	[response setStatusCode: status];
	[response setHeaders: serverHeaders];

	keepAlive = [serverHeaders objectForKey: @"Connection"];
	if ([version isEqual: @"1.1"] ||
	    (keepAlive != nil && [keepAlive isEqual: @"keep-alive"])) {
		[reply setKeepAlive: true];
		[response setKeepAlive: true];

		_socket = [socket retain];
		_lastURL = [URL copy];
		_lastReply = [reply retain];
		_lastResponse = [response retain];
	}

	if (redirects > 0 && (status == 301 || status == 302 ||
	    status == 303 || status == 307) &&
	    (redirect = [serverHeaders objectForKey: @"Location"]) != nil &&
	    (_insecureRedirectsAllowed || [scheme isEqual: @"http"] ||
	    ![redirect hasPrefix: @"http://"])) {
594
595
596
597
598
599
600
601

602
603

604
605
606
607
608

609
610

611
612
613
614
615
616
617
618
619
620
621
622
623


624
625
594
595
596
597
598
599
600

601
602

603
604
605
606
607

608
609

610
611
612
613
614
615
616
617
618
619
620
621


622
623
624
625







-
+

-
+




-
+

-
+











-
-
+
+


			[newRequest autorelease];

			return [self performRequest: newRequest
					  redirects: redirects - 1];
		}
	}

	[reply retain];
	[response retain];
	objc_autoreleasePoolPop(pool);
	[reply autorelease];
	[response autorelease];

	if (status / 100 != 2)
		@throw [OFHTTPRequestFailedException
		    exceptionWithRequest: request
				   reply: reply];
				response: response];

	return reply;
	return response;
}

- (void)close
{
	[_socket close];
	[_socket release];
	_socket = nil;

	[_lastURL release];
	_lastURL = nil;

	[_lastReply release];
	_lastReply = nil;
	[_lastResponse release];
	_lastResponse = nil;
}
@end