Objective-C: objective-c response differs from curl response with similar http request - objective-c

Using below curl command I am able to get a valid response with required token.
curl -v -h "TOKEN:tokenValue" #“someurl.com”
However, When I try to create a NSMutableURLRequest as shown below, I get a different response.
NSURL* url = [NSURL URLWithString:kURL];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
[urlRequest addValue:tokenValueStr forHTTPHeaderField:#"TOKEN"];
[urlRequest setHTTPMethod:#"GET"];
[NSURLConnection sendAsynchronousRequest:urlRequest
queue:[NSOperationQueue mainQueue]
completionHandler:handler];
I have checked the [request allHTTPHeaderfields] and it shows dictionary with TOKEN key-value pair. and Token and url are valid URLs. Theoretically this request is what I am supposed to get the right response but it isnt and I did not find any useful reference online either. Any suggestions are appreciated.

When you pass a header into curl, you must give the name and value of the header like this:
HeaderName:HeaderValue
For the Objective-C parameter, you are passing in a value and a name. The value should just be "HeaderValue" and the name would be "HeaderName", which is "TOKEN" in this case.

Related

NSMutableURLRequest http status code 413

I have a web service. I use it to accept a base 64 string representation of a small (thumbnail size) image. This web service works awesome when using it with Fiddler and manually posting the request. When I run the same request with NSMutableURLRequest (or ASIHTTPRequest), it always returns a 413 status code (413 is Request Entity is Too Large).
Why would NSMutableURLRequest cause it to come up with a 413, whereas Fiddler returns 200 every time?
Here is my NSMutableURLRequest code. I could really use a push, if anybody has any ideas.
//the image request
NSMutableURLRequest *imageRequest=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:POST_IMAGE_API_URL]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:240.0];
//the post parameters
[imageRequest setHTTPMethod:#"POST"];
[imageRequest setHTTPBody:[imageMessage dataUsingEncoding:NSUTF8StringEncoding]];
[imageRequest setValue:#"text/xml" forHTTPHeaderField:#"Content-Type"];
//a few other things
NSURLResponse* imageresponse;
NSError *imageerror;
NSData* imageresult = [NSURLConnection sendSynchronousRequest:imageRequest returningResponse:&imageresponse error:&imageerror];
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)imageresponse;
NSLog(#"imageresponse: %d", httpResponse.statusCode);
When I see this bit of your code:
//the image request
NSMutableURLRequest *imageRequest =
[NSMutableURLRequest requestWithURL:[NSURL URLWithString:POST_IMAGE_API_URL]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:240.0];
I'm guessing you have some whacky characters in your "POST_IMAGE_API_URL" #define, most likely in the parameters that you're passing along.
You need to URL encode the URL string you pass to your URL request.
Try doing:
// assuming POST_IMAGE_API_URL starts with a "#" character
NSString * yourURLAsString = [NSString stringWithString: POST_IMAGE_API_URL];
NSURL * yourEncodedURL = [yourURL stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding];
and pass "yourEncodedURL" in as a parameter to the URLRequest.
I found a solution for this. The issue was not on the Apple end, but on the IIS end. There is an additional parameter for IIS hosted applications (one of which being my WCF service) beyond what is specified in the WCF's web.config file that specifies the "uploadReadAheadSize" for each service. I increased this and the 413 went away. Interestingly enough, I didn't get this error when sending the HTTP request from Fiddler on a desktop client on the same network as the server where the service resides. Basically, I had the solution to this guy's problem but not his context. My solution was his context.

AFNetworking Overload a Post Parameter

I am migrating from ASIHTTPRequest to AFNetworking and have run into an issue.
I am trying to hit an API with a request that overloads the post parameter. I was previously using ASIFormDataRequest for this and used this code to update 3 ids at the same time.
// ASIHTTPRequestCode
[request addPostValue:#"value1" forKey:#"id"];
[request addPostValue:#"value2" forKey:#"id"];
[request addPostValue:#"value3" forKey:#"id"];
Since AFNetworking uses an NSDictionary to store key value pairs, it doesn't seem straight forward how to do this. Any ideas?
I can't immediately see a direct way to do this with AFNetworking, but it is possible to do.
If you look at the code for AFHTTPClient requestWithMethod, you'll see this line, which is the one that sets up the request body to contain the parameters:
[request setHTTPBody:[AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding) dataUsingEncoding:self.stringEncoding]];
Basically you could pass an empty dictionary to requestWithMethod for the parameters, then it returns, call request setHTTPBody yourself, making up the query string yourself in a similar way to the way AFQueryStringFromParametersWithEncoding does it.
You can build the request this way:
NSURL *url = [NSURL URLWithString:#"http://www.mydomain.com/"];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:url];
NSDictionary *postValues = [NSDictionary dictionaryWithObject:[NSString stringWithFormat:#"%#,%#,%#",#"value1",#"value2",#"value3"] forKey:#"id"];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST" path:#"/path/to/your/page.php" postValues];
I was facing a similar issue but solved it by updating the url. I added the parameters i need to send with the url and set the "parameters to nil"
so the url became something like
server\url.htm?data=param1&data=param2&data=param3
and sent nil as paramDictionary
[request setHTTPBody:[AFQueryStringFromParametersWithEncoding(nil, self.stringEncoding) dataUsingEncoding:self.stringEncoding]];

How to use the token given from google reader api to view unread list in objective c

I am making a Google Reader App and so far I have been able to receive the sid, auth, and use those to get a token from http://www.google.com/reader/api/0/token?client=clientName.
My next step if I am correct is to send a GET request using this token to a url that will return me a list of unread messages.
Problem is I do not know what url to use or how to send this GET request using the ID's i have.
Can someone please show me some code that actually does this correctly in objective c.
Assuming you're using a NSURLRequest in Objective-C you can set a custom header like this:
NSMutableURLRequest* request = [[[NSMutableURLRequest alloc] initWithURL:url]
autorelease];
[request setValue:[NSString stringWithFormat:#"GoogleLogin auth=#%", token]
forHTTPHeaderField:#"Authorization"];
This is assuming you have two strings defined already, the URL and the token.
The URL you want is http://www.google.com/reader/atom/user/-/state/com.google/read
I've written a PHP library to interact with Google Reader's API feel free to dig around there. Specifically line 523 is relevent to this question. The library is up to date with their latest authorization changes.
NSMutableURLRequest* request = [[[NSMutableURLRequest alloc] initWithURL:url]autorelease];
[request setValue:[NSString stringWithFormat:#"GoogleLogin auth=#%", token]
forHTTPHeaderField:#"Authorization"];
[request setHTTPMethod:#"GET"];
responseStr = [[NSString alloc]initWithData:recieveData encoding:NSASCIIStringEncoding];
NSLog(#"message %#", responseStr);

Getting SHOUTcast metadata on the Mac

I'm creating an application in Objective-C and I need to get the metadata from a SHOUTcast stream. I tried this:
NSURL *URL = [NSURL URLWithString:#"http://202.4.100.2:8000/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
[request addValue:#"1" forHTTPHeaderField:#"icy-metadata"];
[request addValue:#"Winamp 5/3" forHTTPHeaderField:#"User-Agent"];
[request addValue:#"audio/mpeg" forHTTPHeaderField:#"Content-Type"];
[NSURLConnection connectionWithRequest:request delegate:self];
I would have to get the headers from this request in order to get the information, right? Unfortunately it keeps returning these headers:
Date = "17 Apr 2010 21:57:14 -0200";
"Max-Age" = 0;
What I'm doing wrong?
I found an answer to this question. Simply append a 7.html at the end of the URL and parse the file.
I.E.
http://38.96.148.138:7534/7.html
Fernando Valente's solution for this problem
http://www.fvalente.org/blog/2012/03/15/shoutcast-metadata-the-easy-way/
It seems that shoutcast does not follow HTTP exchange standards and its response headers and body are not separated by two newlines. NSURLConnection/NSURLResponse are unable to parse out the headers; however, connection:didReceiveResponse: is still fired, just with an empty NSURLResponse. This becomes clear if we take a look at data coming in connection:didReceiveData:. The first chunk received will contain metadata headers.

Partial Get request using NSURLMutableRequest

I am having trouble trying to do a partial get request using NSURLMutableRequest.
I set up the header values as follows:
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
NSString* range = [NSString stringWithFormat:#"bytes %d-%d/%d", receivedContentLength, expectedContentLength, expectedContentLength];
[request setHTTPMethod:#"GET"];
[request addValue:[fmt stringFromDate:[NSDate date]] forHTTPHeaderField:#"Date"];
[request addValue:#"application/octet-stream" forHTTPHeaderField:#"Content-Type"];
[request addValue:#"bytes" forHTTPHeaderField:#"Accept-Ranges"];
[request addValue:range forHTTPHeaderField:#"Content-Range"];
[request addValue:[NSString stringWithFormat:#"%d", (expectedContentLength - receivedContentLength)] forHTTPHeaderField:#"Content-Length"];
I have validated (using WGet) that the url that i am using supports partial get requests. The reason I cannot use the resume functionality of NSURLDownload is that it requires the eTag, something that the server doesn't currently support.
Am I missing something with the way I am setting up the header??
Thanks!
Ok figured out what it was. I was getting a temporarily moved redirect response to which I created a new response with the original range headers and the new redirect ones. I also changed "Content-Range" tag to "Range".
Yah - Now I can support wget style resumes! Suppose I should add an if-unmodified-since but not right now ;)