Empty body in POST in ASIHTTPRequest - iphone

Basically, I am sending a POST request with an empty data body:
ASIHTTPRequest *request [ASIHTTPRequest alloc] init];
[request setURL:[NSURL URLWithString:escapedUrlString]];
[request setRequestMethod:#"POST"];
[request addRequestHeader:#"Content-Type" value:#"application/xml"];
[request startSynchronous];
But i am getting this response each time:
Incorrect NSStringEncoding value 0x0000 detected. Assuming NSStringEncodingASCII. Will stop this compatiblity mapping behavior in the near future.
I am wondering if it's mandatory to set post values.

I don't have much experience with the ASIHTTPRequest wrapper but I can see you are initialising it with alloc:init whilst most examples I've seen have a convenience initialiser requestWithURL:(NSURL*)url i.e.
ASIHTTPRequest *request = [AIHTTPRequest requestWithURL:escapedUrlString];
At a guess I'd say this convenience initaliser will also set some of the required variables for your post request to work, including NSStringEnconding.
From the ASIHTTPRequest documentation at http://allseeing-i.com/ASIHTTPRequest/How-to-use#handling_text_encodings
Handling text encodings
ASIHTTPRequest will attempt to read
the text encoding of the received data
from the Content-Type header. If it
finds a text encoding, it will set
responseEncoding to the appropriate
NSStringEncoding. If it does not find
a text encoding in the header, it will
use the value of
defaultResponseEncoding (this defaults
to NSISOLatin1StringEncoding).
When you call [request
responseString], ASIHTTPRequest will
attempt to create a string from the
data it received, using
responseEncoding as the source
encoding.

As Rog says, use initWithURL or requestWithURL. Anyway, in my case the problem was that I was connecting to a slow server and the request timed out giving the "Incorrect NSStringEncoding value 0x0000 detected" error.
I solved it with:
request.timeOutSeconds = 50;
You can try with more than 50 second if your server is even slower.

Related

How to submit a very-very long String to server via POST and get jSON response

I wish to send a very very long string(length of string is more than 10000) to the server and in return get the jSON response from the string.What is the best approach for the task. I am sending various parameters along with this very very long string.
Split down your long string to parts which can be send over one request. Create a json like this
{
"index":"0",
"length":"LENGTH_OF_STRING",
"string":"xsfsffwff.......",
//other json parameters
}
then you can send your string
The problem is that you're trying to put this all into a query parameter. Most servers have built-in limits for URLs, and for good reason.
There's nothing special about the body of an HTTP POST, so just send that up like you would anything else. Just make sure that you set the Content-Length header (since you know that; it might be covered by the HTTP library) and then just stream your data up. No need for any encoding or query params.
I don't know much about objective-c, but I'm sure there's a way to send data like this in an HTTP POST very simply. I've done this with Go and node.js, and both have simple ways of sending arbitrary data in a POST request body.
If you are using the ASI-Http classes , then you can send request like this
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:[WebService getAddPhoto]]];
[request addPostValue:[[imgArray objectAtIndex:i] valueForKey:#"vComments"] forKey:#"comment"];
NSData *imageData = UIImagePNGRepresentation([UIImage imageWithContentsOfFile:[[imgArray objectAtIndex:i] valueForKey:#"vPhoto"]]);
NSString *encodedString = [imageData base64EncodingWithLineLength:[imageData length]];
[request addPostValue:encodedString forKey:#"Photo"];
[request setDelegate:self];
[request startAsynchronous]

Long data is not posting using ASIFormDataRequest

I am using ASIFormDataRequest to send data to server. I am posting a string to server. This string contains encoded image in base64 format. When string length is approx 70,000 character or 70 kb approx, request works fine but when length goes to 130,000 characters or approx. 125 kb, string is not posted to server.
Initially, I supposed this is an server issue so I increased the length in config file too high. But I designed an aspx page where I put a textfield and submit button. I entered same string (approx. 130,000 characters) and submit it and it saved in database successfully. Which suggests that there is no issue on server side and problem occurs in mobile end.
I am not able to find any solution. Please help me to out of this problem. I am also posting the source code:
NSString *string = #"fdfd..."; // very long string. Approx. 130,000 characters long
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:string forKey:#"encryptedJson"];
[request setDelegate:self];
[request setDidFinishSelector:#selector(sendFormRequestDone:)];
[request setDidFailSelector:#selector(sendFormRequestWentWrong:)];
[request startSynchronous];
Please do this
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request retain];

Network error when sending a file through http post with NSMutableURLRequest

I have a problem using setHTTPBodyStream instead of setHTTPBody with a NSMutableURLRequest.
I'm working on code to send large file to a server through http post. With the following portion code, everything works perfectly :
NSData * mydata = [NSData dataWithContentsOfFile:self.tmpFileLocationToUpload];
[request setHTTPBody:mydata];
If I change it to :
NSData * mydata = [NSData dataWithContentsOfFile:self.tmpFileLocationToUpload];
self.tmpInputStream = [NSInputStream inputStreamWithData:mydata];
[request setHTTPBodyStream: self.tmpInputStream];
Then I always end with a network error : Error - The operation couldn’t be completed. (kCFErrorDomainCFNetwork error 303.)
The goal is at the end to create inputStrem directly from the file to be able to send large file without to load them in memory.
Did I miss something with setHTTPBodyStream use ?
Thanks for your help.
Regards.
SĂ©bastien.
Try setting the HTTP method (if you're not already). I was able to fix a "kCFErrorDomainCFNetwork error 303" error by adding:
[request setHTTPMethod:#"POST"];
When you use setHTTPBody, it automatically sets the Content-length header of the request, but when you use setHTTPBodyStream, it doesn't, but rather sets Transfer-encoding of chunked. A chunked transfer encoding is used when the length of the stream cannot be determined in advance. (See Chunked transfer encoding.)
When using NSURLConnection in conjunction with setHTTPBodyStream, you can manually set Content-length and it will prevent the Transfer-encoding of chunked (assuming you know the length in advance):
NSString *contentLength = [NSString stringWithFormat:#"%d", [mydata length]];
[request setValue:contentLength forHTTPHeaderField:#"Content-length"];
When using NSURLSession, attempts to manually set Content-length in conjunction with a chunked request may not prevent it from being a chunked request.

Post Data format is diffrent then what I needed

I am having a simple problem while making a request to server for updating a name field. I need to post some data in this format:-
{"api_token"=>"api", "device_token"=>"device", "user"=>{"name"=>"mohit"}, "id"=>"4"}
But when i am trying to post something its posting in this format:-
{"user"=>"(\n {\n name = ChangeName;\n }\n)", "api_token"=>"api", "device_token"=>"device", "id"=>"4"}
I am not able to figure out how to change my code to generate proper request. Here is the code that I am using.
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:#"http://localhost:3000/users/4?api_token=api&device_token=device"]];
NSMutableDictionary *dict= [NSMutableDictionary dictionaryWithObjectsAndKeys: #"Mike",#"name", nil];
NSArray *array=[[NSArray alloc]initWithObjects:dict, nil];
[request setPostValue:array forKey:#"user"];
[request setRequestMethod:#"PUT"];
[request setDelegate:self];
[request setDidFinishSelector:#selector(requestFinished:)];
[request startAsynchronous];
Please let me know if i need to post some more code fragments.
ASIFormDatRequest setPostValue:forKey: wants strings, not structures. It ends up calling description to convert them to strings and you're getting the printable description of an array with a dictionary in it.
Rails uses a naming scheme that allows you to simulate a hierarchy in a flat space using a field naming convention detailed at http://guides.rubyonrails.org/form_helpers.html. You should read that and understand the html produced by the form helpers.
Try:
[request setPostValue:#"mohit" forKey:#"user[name]"];
and rails will unpack it into the proper kind of collection on the server.

I need the correct syntax for the setValue:forHTTPHeaderField: method on NSMutableURLRequest

I am pulling my hair out trying to conjure up the correct syntax to set the HTTP header information do a byte-range load from an HTTP server.
This is the offending method on NSMutableURLRequest
- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field
This is how I am using this method to load the first 512 byte of a URL request.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
[request setValue:#"0-512\r\n" forHTTPHeaderField:#"Range"];
So far it is ignored and I always receive the entire data payload. I just want the range of bytes specified (0 - 512). Can someone please relieve my headache?
Update:
I have used curl to confirm that my web server supports byte ranges thusly:
curl --range 0-2047 http://www.somewhere.com/humungodata.dat -o "foobar"
The file size of foobar is 2048
Cheers,
Doug
Problem solved.
By adding additional header fields the code immediately worked correctly. Why? Dunno. But it works:
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
[request setValue:#"keep-live" forHTTPHeaderField:#"Connection"];
[request setValue:#"300" forHTTPHeaderField:#"Keep-Alive"];
[request setValue:#"bytes=0-2047" forHTTPHeaderField:#"Range"];
Your original code was wrong in the setValue line, it should be #"bytes=0-512". In your followup, you used the correct string, so the other headers should not be needed.
What you have there should be the correct way to add a header value to a URL request, however i thought only posts got header values, maybe im wrong, have you tried doing this on other enviroments and gotten it to work? Maybe take out the \r\n?