2017-01-17 8 views
0

У меня есть 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); 
+0

Вы не указали длину вашей 'jsonData' в' request'? Является ли ваш 'jsonData' действительным? Как вы его построили? Обратите внимание, что использование 'sendSynchronousRequest: returnResponse: error' устарело и блокирует текущий поток (и если он является основным, блокируйте интерфейс). Вы должны использовать NSURLSession. – Larme

+0

@ Larme Я только что сделал редактирование, содержащее объяснение о jsonData. Поскольку этот метод называется, я устанавливаю небольшой графический счетчик и поле предупреждения и блокирую пользовательский интерфейс, в то время как приложение отправляет эту регистрационную информацию в API. Мне не нужно, чтобы этот вызов был асинхронным. – Ryan

+0

Попробуйте добавить '[request setValue: [длина jsonData] дляHTTPHeaderField: @" Content-Length "];', а также есть круглые скобки вокруг '@ 'content-type" и '@" accept "(странно) , и разве у них обычно нет прописных букв? – Larme

ответ

0

Ниже работает для меня, может быть, что поможет вам.

- (void)UpdateUser:(NSDictionary *)userdetails { 
     NSURL *url = [NSURL URLWithString:@"SOME URL"]; 
     NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url]; 
     request.HTTPMethod = @"POST"; 
     [request addValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; 
     [request addValue:@"application/json" forHTTPHeaderField:@"Accept"]; 
     NSData *jsonData = [NSJSONSerialization dataWithJSONObject:userdetails options:NSJSONWritingPrettyPrinted error:nil]; //don't set error to nil, handle the error 
     [request setHTTPBody:jsonData]; 
     NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self]; 
     [connection start]; 
    } 

ИЛИ другой случай

Это kCFURLErrorUserCancelledAuthentication ошибка, -10xx ошибки из перечисления CFNetworkErrors. Название этой константы довольно самоочевидно. Сервер по какой-то причине отказался от аутентификации

+0

Я вроде как нескромный, эти ошибки фактически API не нравится то, что отправляется, но моя ошибка в этом случае не является kCFURLErrorUserCancelledAuthentication, а вместо kCFErrorDomainCFNetwork. Заголовки и тело, которые я отправляю с помощью приложения, могут быть отправлены через Почтальон без проблем. Я думаю, что проблема в том, что приложение сначала делает что-то с данными. Возможно, неправильно кодирует JSON? UTF8 против ASCII и т. Д.? – Ryan

Смежные вопросы