I'm doing an application that should work with the server.
Need to be authorized on the server through the program using the username and password.
I need to make a request to the server with the line:
{"login": "mad_fashist", "password": "eqeeuq313371", "method": "authentificator"}
The string must be in Json.
In response, I should get a line if authentication fails:
{"validated": "false", "kuid": "", "sid": "", "uid": ""}
And if authentication is passed:
{"validated":"true","kuid":"6","sid":"834fe9b4626502bf9ff23485a408ac40","uid":"69"}
The question is how to send and receive all of the above?
Use SBJson framework. and do smth like:
-(void)requestProjects
{
//I prepare the string
NSString *preparedString=[NSString stringWithFormat:#"%# %#", self.lastDate, self.currentCategory];
NSDictionary *jsonDict = [NSDictionary dictionaryWithObject:preparedString forKey:#"request"];
//Prepare convert to json string
NSString *jsonRequest = [jsonDict JSONRepresentation];
NSLog(#"jsonRequest is %#", jsonRequest);
//Set the URL YOU WILL PROVIDE
NSURL *url = [NSURL URLWithString:#"http:xxxxxxxxxxxxxxxxxxx"];
//PREPARE the request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
//Prepare data which will contain the json request string.
NSData *requestData = [NSData dataWithBytes:[jsonRequest UTF8String] length:[jsonRequest length]];
//Set the propreties of the request
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[request setValue:jsonRequest forHTTPHeaderField:#"Query-string"];
//set the data prepared
[request setHTTPBody: requestData];
//Initialize the connection with request
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
//Start the connection
[delegate showIndicator];
[connection start];
}
//delegate methods:
//METHODS TO HANßDLE RESPONSE
#pragma mark NSURLConnection delegate methods
//WHen receiving the response
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#" Did receive respone");
[responseData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
//While receiving the response data
[responseData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
//When failed just log
[delegate hideIndicator];
NSLog(#"Connection failed!");
NSLog(#"Error %#", error);
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
//When the response data is downloaded
// NSLog(#" Data obtained %#", responseData);
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
// NSLog(#" Response String %#", responseString);
//converted response json string to a simple NSdictionary
//If the response string is really JSONABLE I will have the data u sent me displayed succefully
NSMutableArray *results = [responseString JSONValue];
NSLog(#"Response: %#", results);
/// la la al alal alaa
}
It's your back end who should define how the response in Json will look like
Refer NSJsonSerialization class. Which is newly included in ios5.0. which is the most flexible one for your need. you can access it in apple developer site.
link to NSJSONSerialization
Related
I am trying to access protected resources on a Django site using NSURLConnection , OAuth2 Bearer token and HTTPS. I receive a token, which I then attach either to a GET parameter, POST parameter or header. I can access those URL:s which respond to GET parameter. But when I try to access urls using POST, the server returns me a 403 with a custom error message saying there is no header/post parameter containing the token. I have tried several solutions and HTTP libraries. This method uses AFNetworking, I tried it. We even changed the authorization to accept an alternative header due to warnings that apple does not like the modifying of "Authorization" header. My current code looks like this: (scheme == #"https")
-(void) logOut {
NSString *pget = #"/api/logout/";
NSString *path = [pget stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *absolutePath = [NSString stringWithFormat:#"%#://%#%#", scheme, host, path];
NSURL *url = [NSURL URLWithString:absolutePath];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:30.0];
NSString *authValue = [NSString stringWithFormat:#"Bearer %#", accessToken];
[urlRequest setValue:authValue forHTTPHeaderField:#"Authorization_Extra"];
[urlRequest setValue:#"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"content-type"];
[urlRequest setHTTPMethod: #"POST"];
/*
NSString *post = [NSString stringWithFormat:#"access_token_extra=%#", accessToken];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[postData length]];
[urlRequest setValue:postLength forHTTPHeaderField:#"Content-Length"];
[urlRequest setHTTPBody:postData];
*/
NSDictionary* headers = [urlRequest allHTTPHeaderFields];
NSLog(#"headers: %#",headers);
_originalRequest = urlRequest;
NSURLConnection* connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:NO];
[connection start];
}
#pragma mark NSURLConnection Delegate Methods
- (NSURLRequest *)connection: (NSURLConnection *)connection
willSendRequest: (NSURLRequest *)request
redirectResponse: (NSURLResponse *)redirectResponse;
{
if (redirectResponse) {
// we don't use the new request built for us, except for the URL
NSURL *newURL = [request URL];
NSMutableURLRequest *newRequest = [_originalRequest mutableCopy];
[newRequest setURL: newURL];
NSLog(#"New Request headers: %#", [newRequest allHTTPHeaderFields]);
return newRequest;
} else {
return request;
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response {
NSLog(#"Received response statuscode: %ld", (long)[response statusCode]);
responseData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[responseData appendData:data];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse*)cachedResponse {
return nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"connection finished:");
[_delegate handleData:responseData];
}
The _Delegate handleData parses the response, and the custom response is always that I am lacking either the header or post parameter needed for the Bearer token.
It seems that even though I am replacing the request with a mutable copy of the original on every redirect, the headers/parameters still get stripped by NSURLConnection. But why, and how, since I'm sending a copy of the original request every time and I verify by logging that they are there?
I want to send one data with POST method to one url and received answer from that url.
I write this code for send data ("a") to this url ("http://www.test.com/test/msht")
this is my code but not working please guide me how to send data and give answer from url.
-(IBAction)btn_post_clicked:(id)sender{
//if there is a connection going on just cancel it.
[self.connection cancel];
//initialize new mutable data
NSMutableData *data = [[NSMutableData alloc] init];
self.receivedData = data;
[data release];
//initialize url that is going to be fetched.
NSURL *url = [NSURL URLWithString:#"http://www.test.com/test/msht"];
//initialize a request from url
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[url standardizedURL]];
//set http method
[request setHTTPMethod:#"POST"];
//initialize a post data
NSString *postData = [[NSString alloc] initWithString:#"a"];
//set request content type we MUST set this value.
[request setValue:#"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
//set post data of request
[request setHTTPBody:[postData dataUsingEncoding:NSUTF8StringEncoding]];
//initialize a connection from request
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
self.connection = connection;
[connection release];
//start the connection
[connection start];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
[self.receivedData appendData:data];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
NSLog(#"%#" , error);
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
//initialize convert the received data to string with UTF8 encoding
NSString *htmlSTR = [[NSString alloc] initWithData:self.receivedData
encoding:NSUTF8StringEncoding];
NSLog(#"%#" , htmlSTR);
}
My friend your code is wrong!!! you should determine name of post value in post NSString....
you don't send a value only.
you should write this code if get post method name in server is user :
NSString *post = [NSString stringWithFormat:#"user=a"];
I am not getting the correct output from the server. The response I get back everytime is:
Gone
/prod/bwckgens.p_proc_term_datehas been permanently removed from this server.
This is usually recieved when you just direct the web browser to the page here instead of going through this page first. This makes me come to the conclusion that a cookie isn't being saved, but I read in the documentation that this is all handled by the NSURLConnection object. Is there something I am doing wrong here?
#import "PCFViewController.h"
#interface PCFViewController ()
#end
NSMutableData *mutData;
#implementation PCFViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)queryServer {
NSURL *url = [NSURL URLWithString:#"https://selfservice.mypurdue.purdue.edu/prod/bwckschd.p_disp_dyn_sched"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLCacheStorageAllowed timeoutInterval:3.0];
//the reason I perform a GET here is just to get a cookie and communicate like a normal web browser, since directly doing a POST to the proper address isn't working
[request setHTTPMethod:#"GET"];
[request setValue:#"text/html; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
if (connection) {
mutData = [NSMutableData data];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(#"Succeeded! Received %d bytes of data",[mutData length]);
NSString *str = [[NSString alloc] initWithData:mutData encoding:NSUTF8StringEncoding];
//just to see the contents(for debugging)
NSLog(#"%#", str);
[self handleConnection:connection];
}
-(void)handleConnection:(NSURLConnection *)connection
{
//this is the first step
if ([#"/prod/bwckschd.p_disp_dyn_sched" isEqualToString:[[[connection originalRequest] URL] path]]) {
//first request
//POST
NSURL *url = [NSURL URLWithString:#"https://selfservice.mypurdue.purdue.edu/prod/bwckgens.p_proc_term_date"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLCacheStorageAllowed timeoutInterval:3.0];
[request setHTTPMethod:#"POST"];
NSString *args = #"p_calling_proc=bwckschd.p_disp_dyn_sched&p_term=201320";
NSData *requestBody = [args dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:requestBody];
connection = [connection initWithRequest:request delegate:self];
[connection start];
if (connection) {
mutData = [NSMutableData data];
}
//second step. Here I send the list of classes(COMPUTER SCIENCE) I want to display as well as the term SPRING2013
}else if([#"/prod/bwckgens.p_proc_term_date" isEqualToString:[[[connection currentRequest] URL] path]]) {
NSURL *url = [NSURL URLWithString:#"https://selfservice.mypurdue.purdue.edu/prod/bwckschd.p_get_crse_unsec"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLCacheStorageAllowed
timeoutInterval:3.0];
[request setHTTPMethod:#"POST"];
NSString *args = #"term_in=201320&sel_subj=dummy&sel_day=dummy&sel_schd=dummy&sel_insm=dummy&sel_camp=dummy&sel_levl=dummy&sel_sess=dummy&sel_instr=dummy&sel_ptrm=dummy&sel_attr=dummy&sel_subj=CS&sel_crse=dummy&sel_title=dummy&sel_schd=%25&sel_from_cred=&sel_to_cred=&sel_camp=%25&sel_ptrm=%25&sel_instr=%25&sel_sess=%25&sel_attr=%25&begin_hh=0&begin_mi=0&begin_ap=a&end_hh=0&end_mi=0&end_ap=a";
NSData *requestBody = [args dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:requestBody];
connection = [connection initWithRequest:request delegate:self];
[connection start];
if (connection) {
mutData = [NSMutableData data];
}
//the courses should be shown now I have to parse the data
}else if([#"/prod/bwckschd.p_get_crse_unsec" isEqualToString:[[[connection currentRequest] URL] path]]) {
}
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(#"%#\n", error.description);
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[mutData setLength:0];
NSLog(#"%#\n", response.description);
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[mutData appendData:data];
}
#end
You cannot change the Request Object with the same URL Connection once it is started. Read the documentation of NSURLConnection. it says:
The URL request to load. The request object is deep-copied as part of
the initialization process. Changes made to request after this method
returns do not affect the request that is used for the loading
process.
So if you want to hit another URL, you have to create a new URLRequest and new URLConnection object. regarding your question about saving cookies. you can set the cache policy of the URLRequest using the following method
- (void)setCachePolicy:(NSURLRequestCachePolicy)policy
I'm working on a simple prototype and need to test sending push notifications from one device to another.
I've emailed Urban Airship to turn on the "Allow Push From Device" for my application - and they did turn it on.
I'm trying to use NSURLConnection to send the push notification from the device.
This is my code:
- (void) test {
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://go.urbanairship.com/api/push"]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
NSDictionary * push = #{#"device_tokens":#[#"<token>"], #"aps":#{#"alert":#"TEST", #"sound":#"default"}};
NSData * pushdata = [NSJSONSerialization dataWithJSONObject:push options:0 error:NULL];
[request setHTTPBody:pushdata];
[NSURLConnection connectionWithRequest:request delegate:self];
}
- (void) connection:(NSURLConnection *) connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *) challenge {
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodHTTPBasic]) {
NSURLCredential * credential = [[NSURLCredential alloc] initWithUser:#"<app key>" password:#"<app secret>" persistence:NSURLCredentialPersistenceForSession];
[[challenge sender] useCredential:credential forAuthenticationChallenge:challenge];
[credential release];
}
}
- (void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *) response {
NSHTTPURLResponse * res = (NSHTTPURLResponse *) response;
NSLog(#"response: %#",res);
NSLog(#"res %i\n",res.statusCode);
}
Anyone else done this successfully?
Taking a look at Urban Airship's guide to troubleshooting HTTP status codes, and the documentation for the push API, my guess would be that you need to add a trailing slash to the URL:
[NSURL URLWithString:#"https://go.urbanairship.com/api/push/"]
Example Using the V3 API...
-(void)richPushNotification{
NSDictionary *push = #{
#"audience" : #{
#"device_token" : deviceToken
},
#"device_types" : #[ #"ios" ],
#"notification" : #{
#"ios" : #{
#"alert":Message,
#"sound":#"default",
#"badge":#"auto",
}
},
#"message": #{
#"title": Message,
#"body": #"<html><body><h1>blah blah</h1> etc...</html>",
#"content_type": #"text/html",
#"extra": #{
#"offer_id" : #"608f1f6c-8860-c617-a803-b187b491568e"
}
}
};
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://go.urbanairship.com/api/push/"]];
[request setHTTPMethod:#"POST"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/vnd.urbanairship+json; version=3;" forHTTPHeaderField:#"Accept"];
NSString *authStr = [NSString stringWithFormat:#"%#:%#", appKey, appMasterSecret];
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding];
NSString *authValue = [NSString stringWithFormat:#"Basic %#", [authData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:push
options:0 // Pass 0 if you don't care about the readability of the generated string
error:NULL];
request.HTTPBody = jsonData;
[NSURLConnection connectionWithRequest:request delegate:self];
}
And The Response:
- (void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *) response {
NSHTTPURLResponse * res = (NSHTTPURLResponse *) response;
NSLog(#"response: %#",res);
NSLog(#"res %li\n",(long)res.statusCode);
if (res.statusCode == 202) {
//Show Alert Message Sent
}else{
//Handle Error
}
}
Currently I have:
NSArray* array = [NSArray arrayWithObjects:#"auth.login",#"username",#"password", nil];
NSData* packed_array = [array messagePack];
NSURL* url = [NSURL URLWithString:#"https://192.168.1.149:3790/api/1.0"];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
//Previously the below had changed by hostname.
//[request setValue:#"RPC Server" forHTTPHeaderField:#"Host"];
[request setValue:#"binary/message-pack" forHTTPHeaderField:#"Content-Type"];
[request setValue:[NSString stringWithFormat:#"%d",[packed_array length]] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:packed_array];
NSURLResponse *response;
NSError *error;
responseData = [NSMutableData dataWithData:[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]];
NSLog(#"response data: %#",[responseData messagePackParse]);
NSLog(#"error: %#",error);
- (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
NSLog(#"called canAuthenticateAgainstProtectionSpace");
return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
}
- (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSLog(#"called didReceiveAuthenticationChallenge");
[challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
}
Which returns "Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid"…"
How should I be implementing the answer from this question and getting data back?
I figured out the problem(s). First I fixed the way I was using the delegate and secondly I changed the host. I edited the code to remove the changing of the host and commented it. I still don't think my question was a duplicate…
If your application flow needs the syncronous request, i answer something similar here Objective-C SSL Synchronous Connection