My app is pulling down a JSON file from my server (GoDaddy) and parsing it into an array. The user is then able to add a new record to the existing JSON. I'm running into issues when I try to post all of the data back to server.
To be clear, I'm trying to overwrite the existing file that's on the server with the new data. I know FTP isn't the direction I need to be going, but I'm not using a database of any kind. Just files on the server.
I've made sure the JSON is valid and I've called GoDaddy to make sure I don't need to change any permissions. I've used this directory for FTP before.
Could it be that my REMOTE_PATH_TO_ROOT_APP_FOLDER uses FTP credentials? If so, what URL do I need to use?
- (void)postExamplesDictionaryToServer:(nonnull NSString *)dName
:(nonnull NSString *)rName
:(nonnull NSData *)jsonData
{
NSString *userFileURLString = [NSString stringWithFormat:#"%#/%#/%#TESTER.json", REMOTE_PATH_TO_ROOT_APP_FOLDER, dName, rName];
NSURL *userFileURL = [NSURL URLWithString:userFileURLString];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[jsonData length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:userFileURL];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json; charset=UTF-8" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:jsonData];
[[self.session uploadTaskWithRequest:request fromData:jsonData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
{
NSString *requestReply = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(#"Error: %#", error);
}] resume];
}
EDIT: I logged the NSERROR passed to the completion handler and got this:
Error: (null)
BUT...If I change the URL to a file that doesn't already exist on the server, I get this:
Error: Error Domain=NSURLErrorDomain Code=-1008 "resource unavailable"
UserInfo={NSUnderlyingError=0x7fca8ad44280 {Error Domain=kCFErrorDomainCFNetwork Code=-1008 "(null)"},
NSErrorFailingURLStringKey=ftp://*****:*****#ftp.*****.com/public_html/app/******/File.json,
NSErrorFailingURLStringKey=ftp://*****:*****#ftp.*****.com/public_html/app/******/File.json, NSLocalizedDescription=resource unavailable}
Does this mean it's not attempting to do an upload task, only a request somehow?
Related
I have to pass Authorization token in NSMutableURLRequest , My query is Whenever I have to pass Correct token than I am getting good response with https Status (200.. etc). but whenever I have to pass wrong Authorization token Than I am getting following response insted of http status code 401
* with wrong token response * (I had hide my query htpp:....)
Error Domain=NSURLErrorDomain Code=-1012 "(null)" UserInfo={NSErrorFailingURLStringKey=http......, NSUnderlyingError=0x60800024c420 {Error Domain=kCFErrorDomainCFNetwork Code=-1012 "(null)" UserInfo={_kCFURLErrorAuthFailedResponseKey={url = http.....}}}, NSErrorFailingURLKey=http....}
** here is my code **
// parameter in dictionary
NSDictionary *parameters = #{ #"user_id": [NSNumber numberWithInt:1]};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:parameters
options:NSJSONWritingPrettyPrinted
error:&error];
// Convert dictionary to Json String
if (! jsonData) {
NSLog(#"Got an error: %#", error);
} else {
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
jsonparameter = jsonString;
}
NSData *postData = [jsonparameter dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [NSMutableURLRequest
requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:SiteAPIURL,wsname]]];
NSString *Accesstoken = [NSString stringWithFormat:#"Bearer %#",tokenInfo.access_token];
// Set Access token
[request setValue:Accesstoken forHTTPHeaderField:#"Authorization"];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
NSHTTPURLResponse __autoreleasing *response;
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"%#",error.localizedDescription);
NSLog(#"Status code =%ld",(long)response.statusCode);
401 is server generated error. -1012 is system generated error. This sometimes may be because of app is keeping cached certificates and certificate on the server has been changed so they don't match. Clearing Caches and Preferences folders from app's home directory will delete the old certificate data and app will have to download the new one from the server and you problem will be solved.
I'm trying to access the following URL:
http://appointmentreminder4.azurewebsites.net/Profile
This URL uses a "Get" method, and is supposed to provide JSON results. Before accessing the URL, you need to login using your Email Address and Password. After logging in successfully, the Web API issues a token. This token is used in ALL communications going forward.
I am currently unable to retrieve the token in Objective-C. I have attempted to google this problem, but I cannot figure out:
1) How to get the token
2) How to get the JSON output from the URL.
Here is the code I have written so far that returns neither the JSON, nor the token:
NSDictionary *postDict = [[NSDictionary alloc] initWithObjectsAndKeys:
#"Email Adress", #"MyEmailAddress",
#"Password", #"MyPassword",
nil];
NSError *error = nil;
NSData* jsonData = [NSJSONSerialization dataWithJSONObject:postDict options:kNilOptions error:&error];
NSURLResponse *response;
NSData *localData = nil;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"http://appointmentreminder4.azurewebsites.net/home"]];
[request setHTTPMethod:#"POST"];
if (error == nil)
{
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[request setHTTPBody:jsonData];
// Send the request and get the response
localData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *result = [[NSString alloc] initWithData:localData encoding:NSASCIIStringEncoding];
NSLog(#"Post result : %#", result);
}
If the above link fails, use this link to navigate to the specific page:
http://appointmentreminder4.azurewebsites.net/home
I have a web service that allows me to update records on in our database.
The columns in the table are as follows:
allowsActions
assetID
inventoryObjectID
objectDescription
quantity
retired
serialNumber
action
I'm using the following to GET data from the webservice.
NSString *urlString = [NSString stringWithFormat:#"%#", inventoryAndActionsWebservice];
NSURL *url = [NSURL URLWithString:urlString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"GET"];
Then shoving into a dictionary like so:
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
{
if (data.length > 0 && connectionError == nil)
{
NSLog(#"WE HAS THE DATAS");
NSDictionary *inventory = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
// Then storing the values in CoreData here
}
}
What would be the syntax for updating the webservice? It expects an object in the body of the service call (POST).
NSMutableURLRequest let's you setHTTPBody: and setHTTPMethod:.#"POST"is the way to do a post. Most services need to know the body length and encoding set in headers. (seeaddValue:forHTTPHeaderField:`) for that.
The only reason this topic is tricky is because the developer is forced to grapple with two problems at once: what constitutes a valid request for my server, and (2) how do I form that request with iOS? Part (2) is actually pretty easy once you get a valid request.
The best way to proceed is to get an example working using curl (or something equivalent). Then move on to producing that request in iOS. If you have trouble, ask a question here of the form: "I know my server needs X, here's my code to produce X, but I'm getting this error Y".
So the syntax that I was looking for was ultimately this:
NSString *jSONString = [NSString stringWithFormat:#"{\"MediaInventoryObjectsId\":%d,\"AssetId\":%d,\"Quantity\":%d,\"SerialNumber\":\"%#\",\"Description\":\"%#\",\"AllowActions\":%d,\"Retired\":%d}",inventoryObjectId, assetID, quantity, serialNumber, description, allowActions, retired];
// Convert jSON string to data
NSData *putData = [jSONString dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
// Instantiate a url request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
// Set the request url format
[request setURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#/%d", inventoryAndActionsWebservice, inventoryObjectId]]];
[request setHTTPMethod:#"PUT"];
[request setHTTPBody:putData];
[request setValue:#"application/json" forHTTPHeaderField:#"content-type"];
// Send data to the webservice
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
I'm working on a method to centralize my URL connections for sending and receiving JSON data from a server. It works with POST, but not GET. I'm using a Google App Engine server and on my computer it'll handle the POST requests and return proper results (and log appropriately), but I get the following error when I try the request with a GET method:
Error Domain=kCFErrorDomainCFNetwork Code=303 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error 303.)" UserInfo=0xd57e400 {NSErrorFailingURLKey=http://localhost:8080/api/login, NSErrorFailingURLStringKey=http://localhost:8080/api/login}
In addition, the GAE dev server shows a "broken pipe" error, indicating that the client closed the connection before the server was finished sending all data.
Here's the method:
/* Connects to a given URL and sends JSON data via HTTP request and returns the result of the request as a dict */
- (id) sendRequestToModule:(NSString*) module ofType:(NSString*) type function:(NSString*) func params:(NSDictionary*) params {
NSString *str_params = [NSDictionary dictionaryWithObjectsAndKeys:func, #"function", params, #"params", nil];
NSString *str_url = [NSString stringWithFormat:#"%#%#", lds_url, module];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:str_url]];
NSData *data = [[NSString stringWithFormat:#"action=%#", [str_params JSONString]] dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:type];
[request setHTTPBody:data];
[request setValue:[NSString stringWithFormat:#"%d", [data length]] forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
NSError *error = nil;
NSURLResponse *response = nil;
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSLog(#"Error: %#", error);
NSLog(#"Result: %#", [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding]);
return [result objectFromJSONData];
}
A sample call would be:
NSDictionary *response = [fetcher sendRequestToModule:#"login" ofType:#"GET" function:#"validate_email" params:dict];
Again, this works with a POST but not a GET. How can I fix this?
In my case i was not calling [request setHTTPMethod: #"POST" ]
I think the root cause is you have an invalid URL.
JSON encoding will include things like '{', '}', '[' and ']'. All of these need to be URL encoded before being added to a URL.
NSString *query = [NSString stringWithFormat:#"?action=%#", [str_params JSONString]];
query = [query stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#", str_url, query]];
To directly answer your question:
According to CFNetwork Error Codes Reference the error is kCFErrorHTTPParseFailure. This means the client failed to correctly parse the HTTP response.
The reason why is that a GET doesn't include a body. Why would you want to submit JSON in a GET anyways?
If the target api returns data only you pass it in the url params.
If you want to send data and "get" a response use a post and examine the body on return.
Sample Post:
NSError *error;
NSString *urlString = [[NSString alloc] initWithFormat:#"http://%#:%#/XXXX/MVC Controller Method/%#",self.ServerName, self.Port, sessionId ];
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding ]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
// hydrate the remote object
NSString *returnString = [rdc JSONRepresentation];
NSData *s10 = [returnString dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPBody:s10];
NSURLResponse *theResponse = [[NSURLResponse alloc] init];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&theResponse error:&error];
NSString *message = [[NSString alloc] initWithFormat: #"nothing"];
if (error) {
message = [[NSString alloc] initWithFormat:#"Error: %#", error];
} else {
message = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}
NSLog(#"%#", message);
return message;
i am trying to load the data from an online link that works with php. The link returns an xml.
That xml i want to save in the Documents Directory from the iPad.
I am trying this:
NSString *post = #"";
NSData *postData = [post dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:NO];
NSMutableURLRequest *urlRequest = [[[NSMutableURLRequest alloc] init] autorelease];
[urlRequest setURL:[NSURL URLWithString:#"http://www.test.be/tools/xml_nieuwsbrief.php"]];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:postData];
NSData *urlData;
NSURLResponse *response;
NSError *error;
urlData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
if(!urlData) {
NSLog(#"No connection!");
}
NSLog(#"Receive:%d bytes",[urlData length]);
NSString *aStr = [[[NSString alloc] initWithData:urlData encoding:NSUTF8StringEncoding]autorelease];
NSLog(#"________%#", aStr);
the string does return - null -, i a have been searching the internet, but does not find anything that can lead me to my problem.
Can someone help me for letting me see what i am doing wrong?
Thanks in advance,
Snowy
I'd check the status code of the response object (change the NSURLResponse object into an NSHTTPURLResponse and you'll have a statusCode property available).
If you are actually getting - null - out of the NSData-response you should probably be looking at the server-side script. Perhaps it is not expecting an empty POST-request?