I am attempting to access the JIRA REST webservice using iOS. I have managed to get the requests to work, but the response is not JSON. I get a response with a session id and everything from the login request that comes before this one, and this request returns a similar response, but the data coming back that is suppose to be JSON but looks like : <61737369 616e2e6e 65742f73 65637572 652f7072 (continues for several lines)>. I have made the same requests with JMeter and it gets returned a JSON string, but this request in iOS does not.
NSURL *url = [NSURL URLWithString:#"https://company.atlassian.net/rest/
api/2/project"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url2];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type" ];
[request setHTTPMethod:#"GET"];
//Encoded authorization header
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
[NSURLConnection sendAsynchronousRequest:request queue:
[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse
*response, NSData *data, NSError *error){ }];
I have attempted to manipulate the Content-Type trying random different things, but none have worked. Any ideas on how to get it to return JSON?
You're setting the Content-Type header, but you don't appear to be sending any content. It seems more like you should be setting the Accept header.
You can't log an NSData instance and expect to see the contents, even if the content is a string. When you log, either try to convert the data into a string (alloc, initWithData:) or deserialize the JSON (JSONObjectWithData:options:error:).
Related
For send data from POST method using windows azure mobile service .
Getting response error response
message = "An error has occurred."
My post method is and
data dictionary is
NSDictionary *data = #{#"emailID": #"abc#gmail.comt",
#"userPhone": #"",
#"password": #"12345678",
#"id":#"",
#"signUpBy": [NSNumber numberWithInt:1]};
And API call function is is
-(void)signUpCallAPI:(NSDictionary *)parameter{
// URL that calls into the Azure Service
NSString *serviceUri = #"https://demo.azure-mobile.net/tables/SignUp";
// Convert to NSURL type
NSURL *myURL = [NSURL URLWithString:serviceUri];
// Create a request object
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
timeoutInterval:60];
NSError *error;
NSData *jsonData = nil;
if (parameter)
jsonData = [NSJSONSerialization dataWithJSONObject:parameter
options:NSJSONWritingPrettyPrinted
error:&error];
// Modify http headers for POST request
[request setHTTPMethod: #"POST"];
//Content type what we are sending
[request setValue:[NSString stringWithFormat:#"%lu",(unsigned long)jsonData.length ] forHTTPHeaderField:#"content-length"];
// Indicate JSON Data Format
[request setValue:#"application/json" forHTTPHeaderField:#"content-type"];
// Indicate JSON Data Format
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
// Indicate host property
[request setValue:#"demo.azure-mobile.net" forHTTPHeaderField:#"Host"];
// Indicate application key (you get this from the portal)
[request setValue:#"demoappkey" forHTTPHeaderField:#"X-ZUMO-APPLICATION"];
//add data to body
[request setHTTPBody:jsonData];
// Execute request
conn= [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn start];}
For Post data from signup api not working .
Anything need to do my side?
Any sample available for for post data using API.
Thanks in advance
Looks like you're trying to use Mobile Services without using the iOS SDK. Microsoft has created an SDK for various mobile platform that simplify sending and retrieving data from Mobile Services: https://github.com/Azure/azure-mobile-services
I'd suggest you first look at the ToDo sample iOS app: https://azure.microsoft.com/en-us/documentation/articles/mobile-services-ios-get-started/
Next, this article in the Microsoft documentation explains how to add Mobile Services to an existing app: https://azure.microsoft.com/en-us/documentation/articles/mobile-services-ios-get-started-data/
I have a bit of code for sending/receiving data from a webpage that works ~90% of the time. However the ~10% of the time it doesn't really bothers me, and I can't understand what's going on because the code isn't changing, and I have a similar android implementation that works flawlessly. Here's what I have.
- (NSString*) postData:(NSString*) url params:(NSString*) params
{
NSURL* urlRequest = [NSURL URLWithString:url];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[urlRequest standardizedURL] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10.0f];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/x-www-form-urlencoded;charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];
NSError* err = nil;
NSData* responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&err];
if (!err) {
return [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];;
}
return nil;
}
- (NSString*) getData:(NSString*) url
{
NSURL* urlRequest = [NSURL URLWithString:url];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[urlRequest standardizedURL] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:10];
NSError* err = nil;
NSData* responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&err];
if (!err) {
return [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];;
}
return nil;
}
I call getData to make the initial connection to the website. It has some information I parse out (two security tokens to send in when I send postData) and then send the data through the POST request. This first part always works everytime. However I then send another POST request to change pages again (after parsing out any new security tokens), and this is the part that fails ~10% of the time. By fail, I mean the website responds that my session has been compromised. I know this message happens if the security tokens are invalid, but I've checked those over and over and over and everytime they're fine. My theory is that I'm loosing cookie information, but from what I understand NSURLConnection should store the cookie information based on domain.
If I open a browser and go to the page, then delete the only cookie that is stored however, it takes me back to the login page (like expected) and doesn't give me the error message about my session being corrupted.
Any ideas would be greatly appreciated
I am trying to authenticate to a HTTP RESTful site using NSURLRequest from an iPhone app. I put the user/pass encoded in base64 and pass it in as the "Authorization" header in the NSURLRequest with the word "Basic " appended to it. However, I keep getting an auth error in the other end. Here is my code. If I do a manual CURL request, it works. I also checked to make sure the Base64 is properly encoded and user, pass, and url are correct.
NSMutableURLRequest *urlRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
NSString *basicAuthCredentials = [NSString stringWithFormat:#"%#:%#", user, pass];
NSString *authValue = [NSString stringWithFormat:#"Basic %#", AFBase64EncodedStringFromString(basicAuthCredentials)];
authValue = [authValue stringByReplacingOccurrencesOfString:#"\n" withString:#""];
[urlRequest setValue:authValue forHTTPHeaderField:#"Authorization"];
[urlRequest setHTTPMethod: #"GET"];
NSData *httpData = [self encodeDictionary:data];
[urlRequest setHTTPBody:httpData];
NSHTTPURLResponse *response;
NSError *error;
NSData* result = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
The auth code looks fine. Sure, the stringByReplacingOccurrencesOfString is unnecessary, but doesn't hurt. And I might use the native base64 methods (NSData methods base64EncodedDataWithOptions or base64EncodedStringWithOptions in iOS 7, base64Encoding in iOS versions prior to 7) rather than AFNetworking's, but I don't think this is the problem either.
Assuming your userid and password are correct and that your server really is using basic authentication (which I assume is correct if your cURL is succeeding), the only thing that is obviously incorrect here is the call to setHTTPBody for a GET request. NSURLConnection will not send the body for a GET request (nor should it, as the body is semantically meaningless in GET requests). If you want to send a request with a body, you should generally use POST. Or if you want to send parameters in a GET request, you can add them to the URL, but not to the body.
I'm writing an iPad app that needs to communicate with a backend server. The first order of business in using this backend is to login, and for this the server has a URL that we can POST to, which I do like this:
// Create the request.
NSString* loginURL = #"http://foo.local/signature/service/auth/rest/firewall/login";
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:loginURL]];
NSString* credentials = #"{\"userName\":\"foo2#foolinator.com\", \"password\":\"password\"}";
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:[credentials dataUsingEncoding:NSASCIIStringEncoding
allowLossyConversion:YES]];
// Logging in...
NSError* error = nil;
NSURLResponse* response;
NSData* result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*) response;
NSString* responseString = [NSHTTPURLResponse localizedStringForStatusCode:[httpResponse statusCode]];
NSLog(#"Response String is: %#\n", responseString);
NSLog(#"Header fields are: %#\n", [httpResponse allHeaderFields]);
What's odd is that the response I'm getting is Error 405: Method Not Allowed. I would've expected this if I was doing a GET, but I'm doing a POST.
I installed WireShark to examine the HTTP requests and it seems that there's actually two being made. The first one, is a POST call, and the server returns some cookie information as a response, and then a second GET call, which is what the code above gets back.
Why does this happen? Is it something to do with the response from the server the first time?
While you research your web service's login API, a couple of unrelated observations:
You should be sending this asynchronously if doing this from the main queue. Never issue synchronous network requests from the main queue. If you do this synchronously on the main queue (a) you risk having the iOS watch-dog process kill your app, which happens if the main queue becomes unresponsive while some synchronous network request is being processed; and (b) it's a bad UX to simply freeze an app during a network request ... if you need, disable the UI and show an indeterminate progress indicator (a UIActivityIndicatorView) while the network request is in progress.
You should probably be setting a value forHTTPHeaderField for Content-Length. It's probably not required, but it's good practice.
You probably should not be using a string with the JSON with the userid and password, but rather you should probably build this from a NSDictionary using something like NSJSONSerialization. As it is, if your password, for example, had any characters that needed to be escaped (e.g. a quotation mark), the existing code might not work. Using NSJSONSerialization is an easy way to ensure that your JSON is properly formatted.
You probably should not be sending a password in plaintext in your JSON request. At the very least, I hope your server employs HTTPS.
Anyway, with these observations, assuming your server really is expecting a JSON request, I might suggest something like:
// hopefully your production server is employing HTTPS
NSString *loginURL = #"https://foo.local/signature/service/auth/rest/firewall/login";
// use NSJSONSerialization to create JSON rather than building it in a NSString
NSDictionary *postDictionary = #{#"userName": userName, #"password": password}; // assuming you have NSString variables, `userName` and `password`
NSError *error = nil;
NSData *postData = [NSJSONSerialization dataWithJSONObject:postDictionary options:0 error:&error];
NSAssert(postData, #"dataWithJSONObject failed: %#", error);
// when creating request, also set Content-Length
NSURL *url = [NSURL URLWithString:loginURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:postData];
[request setValue:#"application/json; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
// issue request asynchronously
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError) {
NSLog(#"sendAsynchronousRequest error: %#", connectionError);
return;
}
// process the server response here
}];
You might still want to use a NSURLConnectionDataDelegate/NSURLConnectionDelegate based request (you can identify redirects, challenges, cancel it if you need, etc.), but the above might be a good start at an asynchronous JSON-based request.
So this is the use case.
Application Run, Authorization Header is set to nil. You get fresh data.
[_request setValue:nil forHTTPHeaderField:#"Authorization"];
User login, After that all the requests to server are send with Authorization Header like this.
[_request setValue:[NSString stringWithFormat:#"TRUEREST username=%#&session_token=%#&apikey=1234567890",#"username",#"session_token"]
forHTTPHeaderField:#"Authorization"];
Now I log out and now every request goes with Authorization Header nil value.
[_request setValue:nil forHTTPHeaderField:#"Authorization"];
But I am still getting response as if I am logged in user? Any idea what's the issue?
Request to the server is made using as follows
[NSURLConnection sendAsynchronousRequest:_request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {}];
I have tried to make NSMutableURLRequest in following 2 ways.
_request = [NSMutableURLRequest requestWithURL:url];
_request = [[NSMutableURLRequest alloc] initWithURL:url
cachePolicy:NSURLRequestReloadRevalidatingCacheData
timeoutInterval:60];
You might disable the use of cookies before you use the request:
[_request setHTTPShouldHandleCookies:NO];
Alternatively, delete any cookie - or the relevant cookie - form the NSHTTPCookieStorage singleton.
However, you could greatly improve your code using NSURLConnection implementing the delegate connection:willSendRequestForAuthenticationChallenge: where you are able to fully customize authentication handling.
Looks like a server problem. The server should send response header telling the URL loading system to not cache the response.