Index: src/OFHTTPClient.m ================================================================== --- src/OFHTTPClient.m +++ src/OFHTTPClient.m @@ -326,11 +326,11 @@ OFURL *URL = [request URL]; OFString *scheme = [URL scheme]; of_http_request_method_t method = [request method]; OFMutableString *requestString; OFDictionary *headers = [request headers]; - OFDataArray *POSTData = [request POSTData]; + OFDataArray *entity = [request entity]; OFTCPSocket *socket; OFHTTPClientResponse *response; OFString *line, *path, *version, *redirect, *keepAlive; OFMutableDictionary *serverHeaders; OFEnumerator *keyEnumerator, *objectEnumerator; @@ -338,16 +338,10 @@ int status; if (![scheme isEqual: @"http"] && ![scheme isEqual: @"https"]) @throw [OFUnsupportedProtocolException exceptionWithURL: URL]; - if (method != OF_HTTP_REQUEST_METHOD_GET && - method != OF_HTTP_REQUEST_METHOD_HEAD && - method != OF_HTTP_REQUEST_METHOD_POST) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; - /* Can we reuse the socket? */ if (_socket != nil && [[_lastURL scheme] isEqual: [URL scheme]] && [[_lastURL host] isEqual: [URL host]] && [_lastURL port] == [URL port]) { /* @@ -409,23 +403,10 @@ while ((key = [keyEnumerator nextObject]) != nil && (object = [objectEnumerator nextObject]) != nil) [requestString appendFormat: @"%@: %@\r\n", key, object]; - if (method == OF_HTTP_REQUEST_METHOD_POST) { - OFString *contentType = [request MIMEType]; - - if (contentType == nil) - contentType = @"application/x-www-form-urlencoded; " - @"charset=UTF-8"; - - [requestString appendFormat: - @"Content-Type: %@\r\n" - @"Content-Length: %zu\r\n", - contentType, [POSTData count] * [POSTData itemSize]]; - } - if ([request protocolVersion].major == 1 && [request protocolVersion].minor == 0) [requestString appendString: @"Connection: keep-alive\r\n"]; [requestString appendString: @"\r\n"]; @@ -439,13 +420,13 @@ /* Reconnect in case a keep-alive connection timed out */ socket = [self OF_createSocketForRequest: request]; [socket writeString: requestString]; } - if (method == OF_HTTP_REQUEST_METHOD_POST) - [socket writeBuffer: [POSTData items] - length: [POSTData count] * [POSTData itemSize]]; + if (entity != nil) + [socket writeBuffer: [entity items] + length: [entity count] * [entity itemSize]]; @try { line = [socket readLine]; } @catch (OFInvalidEncodingException *e) { @throw [OFInvalidServerReplyException exception]; @@ -458,14 +439,14 @@ */ if (line == nil) { socket = [self OF_createSocketForRequest: request]; [socket writeString: requestString]; - if (method == OF_HTTP_REQUEST_METHOD_POST) - [socket writeBuffer: [POSTData items] - length: [POSTData count] * - [POSTData itemSize]]; + if (entity != nil) + [socket writeBuffer: [entity items] + length: [entity count] * + [entity itemSize]]; @try { line = [socket readLine]; } @catch (OFInvalidEncodingException *e) { @throw [OFInvalidServerReplyException exception]; @@ -578,18 +559,32 @@ OFHTTPRequest *newRequest; newRequest = [OFHTTPRequest requestWithURL: newURL]; [newRequest setMethod: method]; [newRequest setHeaders: headers]; - [newRequest setPOSTData: POSTData]; - [newRequest setMIMEType: [request MIMEType]]; + [newRequest setEntity: entity]; if (status == 303) { + OFMutableDictionary *newHeaders; + OFEnumerator *keyEnumerator, *objectEnumerator; + id key, object; + + newHeaders = [OFMutableDictionary dictionary]; + keyEnumerator = [headers keyEnumerator]; + objectEnumerator = [headers objectEnumerator]; + while ((key = [keyEnumerator nextObject]) != + nil && + (object = [objectEnumerator nextObject]) != + nil) + if (![key hasPrefix: @"Content-"]) + [newHeaders setObject: object + forKey: key]; + [newRequest setMethod: OF_HTTP_REQUEST_METHOD_GET]; - [newRequest setPOSTData: nil]; - [newRequest setMIMEType: nil]; + [newRequest setHeaders: newHeaders]; + [newRequest setEntity: nil]; } [newRequest retain]; objc_autoreleasePoolPop(pool); [newRequest autorelease]; Index: src/OFHTTPRequest.h ================================================================== --- src/OFHTTPRequest.h +++ src/OFHTTPRequest.h @@ -66,22 +66,20 @@ { OFURL *_URL; of_http_request_method_t _method; of_http_request_protocol_version_t _protocolVersion; OFDictionary *_headers; - OFDataArray *_POSTData; - OFString *_MIMEType; + OFDataArray *_entity; OFString *_remoteAddress; } #ifdef OF_HAVE_PROPERTIES @property (copy) OFURL *URL; @property of_http_request_method_t method; @property of_http_request_protocol_version_t protocolVersion; @property (copy) OFDictionary *headers; -@property (retain) OFDataArray *POSTData; -@property (copy) OFString *MIMEType; +@property (retain) OFDataArray *entity; @property (copy) OFString *remoteAddress; #endif /*! * @brief Creates a new OFHTTPRequest. @@ -176,36 +174,22 @@ * @return A dictionary with headers for the HTTP request. */ - (OFDictionary*)headers; /*! - * @brief Sets the POST data of the HTTP request. - * - * @param POSTData The POST data of the HTTP request - */ -- (void)setPOSTData: (OFDataArray*)POSTData; - -/*! - * @brief Returns the POST data of the HTTP request. - * - * @return The POST data of the HTTP request - */ -- (OFDataArray*)POSTData; - -/*! - * @brief Sets the MIME type for the POST data. - * - * @param MIMEType The MIME type for the POST data - */ -- (void)setMIMEType: (OFString*)MIMEType; - -/*! - * @brief Returns the MIME type for the POST data. - * - * @return The MIME type for the POST data - */ -- (OFString*)MIMEType; + * @brief Sets the entity body of the HTTP request. + * + * @param entity The entity body of the HTTP request + */ +- (void)setEntity: (OFDataArray*)entity; + +/*! + * @brief Returns the entity body of the HTTP request. + * + * @return The entity body of the HTTP request + */ +- (OFDataArray*)entity; /*! * @brief Sets the remote address from which the request originates. * * @param remoteAddress The remote address from which the request originates Index: src/OFHTTPRequest.m ================================================================== --- src/OFHTTPRequest.m +++ src/OFHTTPRequest.m @@ -118,12 +118,11 @@ - (void)dealloc { [_URL release]; [_headers release]; - [_POSTData release]; - [_MIMEType release]; + [_entity release]; [_remoteAddress release]; [super dealloc]; } @@ -134,12 +133,11 @@ @try { copy->_method = _method; copy->_protocolVersion = _protocolVersion; [copy setURL: _URL]; [copy setHeaders: _headers]; - [copy setPOSTData: _POSTData]; - [copy setMIMEType: _MIMEType]; + [copy setEntity: _entity]; [copy setRemoteAddress: _remoteAddress]; } @catch (id e) { [copy release]; @throw e; } @@ -159,12 +157,11 @@ if (request->_method != _method || request->_protocolVersion.major != _protocolVersion.major || request->_protocolVersion.minor != _protocolVersion.minor || ![request->_URL isEqual: _URL] || ![request->_headers isEqual: _headers] || - ![request->_POSTData isEqual: _POSTData] || - ![request->_MIMEType isEqual: _MIMEType] || + ![request->_entity isEqual: _entity] || ![request->_remoteAddress isEqual: _remoteAddress]) return false; return true; } @@ -178,12 +175,11 @@ OF_HASH_ADD(hash, _method); OF_HASH_ADD(hash, _protocolVersion.major); OF_HASH_ADD(hash, _protocolVersion.minor); OF_HASH_ADD_HASH(hash, [_URL hash]); OF_HASH_ADD_HASH(hash, [_headers hash]); - OF_HASH_ADD_HASH(hash, [_POSTData hash]); - OF_HASH_ADD_HASH(hash, [_MIMEType hash]); + OF_HASH_ADD_HASH(hash, [_entity hash]); OF_HASH_ADD_HASH(hash, [_remoteAddress hash]); OF_HASH_FINALIZE(hash); return hash; @@ -263,28 +259,18 @@ - (OFDictionary*)headers { OF_GETTER(_headers, true) } -- (void)setPOSTData: (OFDataArray*)POSTData -{ - OF_SETTER(_POSTData, POSTData, true, 0) -} - -- (OFDataArray*)POSTData -{ - OF_GETTER(_POSTData, true) -} - -- (void)setMIMEType: (OFString*)MIMEType -{ - OF_SETTER(_MIMEType, MIMEType, true, 1) -} - -- (OFString*)MIMEType -{ - OF_GETTER(_MIMEType, true) +- (void)setEntity: (OFDataArray*)entity +{ + OF_SETTER(_entity, entity, true, 0) +} + +- (OFDataArray*)entity +{ + OF_GETTER(_entity, true) } - (void)setRemoteAddress: (OFString*)remoteAddress { OF_SETTER(_remoteAddress, remoteAddress, true, 1) @@ -297,30 +283,29 @@ - (OFString*)description { void *pool = objc_autoreleasePoolPush(); const char *method = of_http_request_method_to_string(_method); - OFString *indentedHeaders, *indentedPOSTData, *ret; + OFString *indentedHeaders, *indentedEntity, *ret; indentedHeaders = [[_headers description] stringByReplacingOccurrencesOfString: @"\n" withString: @"\n\t"]; - indentedPOSTData = [[_POSTData description] + indentedEntity = [[_entity description] stringByReplacingOccurrencesOfString: @"\n" withString: @"\n\t"]; ret = [[OFString alloc] initWithFormat: @"<%@:\n\tURL = %@\n" @"\tMethod = %s\n" @"\tHeaders = %@\n" - @"\tPOST data = %@\n" - @"\tPOST data MIME type = %@\n" + @"\tEntity = %@\n" @"\tRemote address = %@\n" @">", - [self class], _URL, method, indentedHeaders, indentedPOSTData, - _MIMEType, _remoteAddress]; + [self class], _URL, method, indentedHeaders, indentedEntity, + _remoteAddress]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } @end Index: src/OFHTTPServer.m ================================================================== --- src/OFHTTPServer.m +++ src/OFHTTPServer.m @@ -294,11 +294,11 @@ of_http_request_method_t _method; OFString *_host, *_path; uint16_t _port; OFMutableDictionary *_headers; size_t _contentLength; - OFDataArray *_POSTData; + OFDataArray *_entity; } - initWithSocket: (OFTCPSocket*)socket server: (OFHTTPServer*)server; - (bool)socket: (OFTCPSocket*)socket @@ -347,11 +347,11 @@ [_timer release]; [_host release]; [_path release]; [_headers release]; - [_POSTData release]; + [_entity release]; [super dealloc]; } - (bool)socket: (OFTCPSocket*)socket @@ -416,14 +416,10 @@ _method = of_http_request_method_from_string( [method UTF8String]); } @catch (OFInvalidFormatException *e) { return [self sendErrorAndClose: 405]; } - if (_method != OF_HTTP_REQUEST_METHOD_GET && - _method != OF_HTTP_REQUEST_METHOD_HEAD && - _method != OF_HTTP_REQUEST_METHOD_POST) - return [self sendErrorAndClose: 405]; @try { _path = [line substringWithRange: of_range(pos + 1, [line length] - pos - 10)]; } @catch (OFOutOfRangeException *e) { @@ -444,27 +440,24 @@ { OFString *key, *value; size_t pos; if ([line length] == 0) { - switch (_method) { - case OF_HTTP_REQUEST_METHOD_POST:; - OFString *tmp; - char *buffer; - - tmp = [_headers objectForKey: @"Content-Length"]; - if (tmp == nil) - return [self sendErrorAndClose: 411]; - - @try { - _contentLength = (size_t)[tmp decimalValue]; - } @catch (OFInvalidFormatException *e) { - return [self sendErrorAndClose: 400]; - } + size_t contentLength; + + @try { + contentLength = [[_headers + objectForKey: @"Content-Length"] decimalValue]; + } @catch (OFInvalidFormatException *e) { + return [self sendErrorAndClose: 400]; + } + + if (contentLength > 0) { + char *buffer; buffer = [self allocMemoryWithSize: BUFFER_SIZE]; - _POSTData = [[OFDataArray alloc] init]; + _entity = [[OFDataArray alloc] init]; [_socket asyncReadIntoBuffer: buffer length: BUFFER_SIZE target: self selector: @selector(socket: @@ -472,15 +465,13 @@ length:exception:)]; [_timer setFireDate: [OFDate dateWithTimeIntervalSinceNow: 5]]; return false; - default: - _state = SEND_RESPONSE; - break; } + _state = SEND_RESPONSE; return true; } pos = [line rangeOfString: @":"].location; if (pos == OF_NOT_FOUND) @@ -535,14 +526,14 @@ exception: (OFException*)exception { if ([socket isAtEndOfStream] || exception != nil) return false; - [_POSTData addItems: buffer - count: length]; + [_entity addItems: buffer + count: length]; - if ([_POSTData count] >= _contentLength) { + if ([_entity count] >= _contentLength) { @try { [self createResponse]; } @catch (OFWriteFailedException *e) { return false; } @@ -613,11 +604,11 @@ request = [OFHTTPRequest requestWithURL: URL]; [request setMethod: _method]; [request setProtocolVersion: (of_http_request_protocol_version_t){ 1, _HTTPMinorVersion }]; [request setHeaders: _headers]; - [request setPOSTData: _POSTData]; + [request setEntity: _entity]; [request setRemoteAddress: [_socket remoteAddress]]; response = [[[OFHTTPServerResponse alloc] initWithSocket: _socket server: _server] autorelease];