I am attempting to use AFNetworking with an XML-RPC based API while using GDataXML as my XML parsing and creation class.
I have successfully written some methods that output a proper XML request according to the spec of the API, I have also tested this XML request using apigee console and verified I get a correct response back every time with the apigee console and the API.
Now comes AFNetworking, I have the following code written which sometimes, but rarely works.
NSMutableURLRequest *request = [[FZAPIClient sharedClient] requestForDataServiceQueryOnTable:@"Contact" usingQueryData:@{ @"LastName" : @"Wagner" } forFields:@[ @"FirstName", @"LastName" ] withLimit:1000 forPage:0];
AFHTTPRequestOperation *operation = [[FZAPIClient sharedClient] HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSError *error = nil;
GDataXMLDocument *opdoc = [[GDataXMLDocument alloc] initWithData:[[operation request] HTTPBody] options:0 error:&error];
if (error) {
NSLog(@"Error creating XML: %@", error);
}
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:responseObject options:0 error:nil];
GDataXMLElement *element = [doc rootElement];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[FZAPIErrorHandler handleError:error];
}];
[operation start];
Implementation for - (NSMutableURLRequest *)requestForDataServiceQueryOnTable:(NSString *)table usingQueryData:(NSDictionary *)queryData forFields:(NSArray *)fields withLimit:(NSInteger)limit forPage:(NSInteger)page;
- (NSMutableURLRequest *)requestForDataServiceQueryOnTable:(NSString *)table
usingQueryData:(NSDictionary *)queryData
forFields:(NSArray *)fields
withLimit:(NSInteger)limit
forPage:(NSInteger)page {
GDataXMLDocument *xmlDocument = [FZXMLGenerator requestForDataServiceQueryOnTable:table
usingQueryData:queryData
forFields:fields
withLimit:limit
forPage:page];
NSMutableURLRequest *request = [self requestWithMethod:@"POST" path:@"" parameters:nil];
[request setHTTPBody:[xmlDocument XMLData]];
[request setHTTPMethod:@"POST"];
return request;
}
When the request works, I get an excepted response.
When the request doesn't work (which is 99% of the time) I get the following response.
<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value>
<i4>0</i4>
</value>
</member>
<member>
<name>faultString</name>
<value>Failed to parse XML-RPC request: Premature end of file.</value>
</member>
</struct>
</value>
</fault>
</methodResponse>
This makes me suspect something is happening to the HTTPBody property, I have added logging just about everywhere I can think and see that the XML is indeed attached to the request when it is fired. It is also still accessible via the operation in the completion block.
Any ideas?
It looks like it was as simple as setting the content type on the request.
Updating the method to
- (NSMutableURLRequest *)requestForDataServiceQueryOnTable:(NSString *)table
usingQueryData:(NSDictionary *)queryData
forFields:(NSArray *)fields
withLimit:(NSInteger)limit
forPage:(NSInteger)page {
GDataXMLDocument *xmlDocument = [FZXMLGenerator requestForDataServiceQueryOnTable:table
usingQueryData:queryData
forFields:fields
withLimit:limit
forPage:page];
NSMutableURLRequest *request = [self requestWithMethod:@"POST" path:@"" parameters:nil];
[request setHTTPBody:[xmlDocument XMLData]];
[request setValue:@"application/xml" forHTTPHeaderField:@"Content-Type"];
return request;
}
Solved the problem, notice the line
[request setValue:@"application/xml" forHTTPHeaderField:@"Content-Type"];
To make this global on all requests I added the line, [self setDefaultHeader:@"Content-Type" value:@"application/xml"];
to my - (id)initWithBaseURL:(NSURL *)url;
implementation.