У меня есть API на нашем веб-сервере, который предоставляет данные для наших приложений. Запросы POST и GET отлично работают с Postman или с использованием других тестов. Запросы GET, похоже, отлично работают в приложении, но запросы POST возвращаются с ошибкой (тестируется с помощью симулятора iPhone 6 с использованием iOS 10.2 на Xcode 8.2.1).Ошибка при попытке отправить запрос POST
Error Domain=NSURLErrorDomain Code=-1012 "(null)"
UserInfo={NSErrorFailingURLStringKey=https://api.mysite.com/api/Device/Login,
NSUnderlyingError=0x6000002487f0 {Error Domain=kCFErrorDomainCFNetwork Code=-1012 "(null)"
UserInfo={_kCFURLErrorAuthFailedResponseKey=<CFURLResponse 0x6000000fde00 [0x108d59df0]>
{url = https://api.mysite.com/api/Device/Login}}},
NSErrorFailingURLKey=https://api.mysite.com/api/Device/Login}
domain: @"NSURLErrorDomain" - code: 18446744073709550604
Вот основная часть функции, которая создает запрос POST:
-(NSString*)login:(NSString*)username password:(NSString*)password
{
NSString *deviceID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
NSString *deviceModel = [[UIDevice currentDevice] model];
NSString *deviceOS = [[UIDevice currentDevice] systemVersion];
NSString *deviceOSName = [[UIDevice currentDevice] systemName];
NSString *pushEnabled = @"False";
NSArray *userDictObjects = [NSArray arrayWithObjects:username, password, nil];
NSArray *userDictKeys = [NSArray arrayWithObjects:@"Username", @"Password", nil];
NSDictionary *userDict = [NSDictionary dictionaryWithObjects:userDictObjects forKeys:userDictKeys];
NSArray *deviceDictObjects = [NSArray arrayWithObjects:
deviceID,
deviceOSName,
deviceOS,
@"Apple",
deviceModel,
pushEnabled,
@"pushID", nil];
NSArray *deviceDictKeys = [NSArray arrayWithObjects:
@"DeviceID",
@"OS",
@"OSVersion",
@"Manufacturer",
@"Model",
@"PushEnabled",
@"PushID", nil];
NSDictionary *deviceDict = [NSDictionary dictionaryWithObjects:deviceDictObjects forKeys:deviceDictKeys];
NSArray *sectionsArrayObjects = [NSArray arrayWithObjects:userDict, deviceDict, nil];
NSArray *sectionsArrayKeys = [NSArray arrayWithObjects:@"User", @"Device", nil];
NSDictionary *sectionsDict = [NSDictionary dictionaryWithObjects:sectionsArrayObjects forKeys:sectionsArrayKeys];
NSLog(@"Json > %@", sectionsDict);
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:sectionsDict options:0 error:nil];
NSString *conURL = [NSString stringWithFormat:@"%@/api/Device/Login", apiURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:conURL]];
[request setHTTPMethod:@"POST"];
[request addValue:@"application/json" forHTTPHeaderField:(@"content-type")];
[request addValue:@"application/json" forHTTPHeaderField:(@"accept")];
[request setHTTPBody:jsonData]; // This jsonData is populated elsewhere from a dictionary with [NSJSONSerialization dataWithJSONObject:sectionsDict options:0 error:nil];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *authenticated = @"No";
if (error == nil) {
if (response) {
NSHTTPURLResponse *newResp = (NSHTTPURLResponse*)response;
NSLog(@"Authenticate - login - Response code - %li", (long)newResp.statusCode);
if (data.length > 0 && error == nil) {
NSLog(@"Authenticate - login - Data length - %li", (long)data.length);
authenticated = @"Yes";
} else {
NSLog(@"Authenticate - login - Data length - %li", (long)data.length);
NSLog(@"Authenticate - login - Error - %@", error);
}
} else {
NSLog(@"Authenticate - login - No response - %@", response);
}
} else {
NSLog(@"Authenticate - login - login error - %li", (long)error.code); // app currently gets here
if (error.code != -1012) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"There was a problem!"
message:@"The app is unable to login, the request timed out. Please make sure there is an Internet connection and try again."
delegate:self
cancelButtonTitle:@"Ok"
otherButtonTitles:nil];
[alert setTag:2];
[alert show];
} else {
NSLog(@"Authenticate - login - login error code - %li ", (long)error.code); // app currently gets here
}
}
Я попытался как HTTP и HTTPS, и это не имеет никакого значения. Что я делаю не так? Что я могу сделать, чтобы отправить успешный запрос POST, содержащий JSON в теле?
UPDATE
Я создал очень простой метод тестирования, который отправляет запрос POST, и это работает отлично. Я чувствую, что проблема связана с завершением JSON, который мне нужно отправить и как сервер получает его.
Дрессировка:
NSString *string= [NSString stringWithFormat:@"http://api.mysite.com/api/Test/LoginSimplePost?username=%@&password=%@&portalid=%i",username,password,portalid];
NSLog(@"%@",string);
NSURL *url = [NSURL URLWithString:string];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSLog(@"responseData: %@", responseData);
NSString *str = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(@"responseData: %@", str);
Вы не указали длину вашей 'jsonData' в' request'? Является ли ваш 'jsonData' действительным? Как вы его построили? Обратите внимание, что использование 'sendSynchronousRequest: returnResponse: error' устарело и блокирует текущий поток (и если он является основным, блокируйте интерфейс). Вы должны использовать NSURLSession. – Larme
@ Larme Я только что сделал редактирование, содержащее объяснение о jsonData. Поскольку этот метод называется, я устанавливаю небольшой графический счетчик и поле предупреждения и блокирую пользовательский интерфейс, в то время как приложение отправляет эту регистрационную информацию в API. Мне не нужно, чтобы этот вызов был асинхронным. – Ryan
Попробуйте добавить '[request setValue: [длина jsonData] дляHTTPHeaderField: @" Content-Length "];', а также есть круглые скобки вокруг '@ 'content-type" и '@" accept "(странно) , и разве у них обычно нет прописных букв? – Larme