Добавить данные в POST NSURLRequest

Как вы добавляете данные к существующему POST NSURLRequest? Мне нужно добавить новый параметр userId=2323.


person Tim    schedule 27.05.2011    source источник
comment
Пожалуйста, опишите свой вопрос с некоторым кодом.   -  person Tirth    schedule 27.05.2011


Ответы (5)


Если вы не хотите использовать сторонние классы, то вот как вы устанавливаете тело сообщения...

NSURL *aUrl = [NSURL URLWithString:@"http://www.apple.com/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl
                                         cachePolicy:NSURLRequestUseProtocolCachePolicy
                                     timeoutInterval:60.0];

[request setHTTPMethod:@"POST"];
NSString *postString = @"company=Locassa&quality=AWESOME!";
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];

NSURLConnection *connection= [[NSURLConnection alloc] initWithRequest:request 
                                                             delegate:self];

Просто добавьте пару ключ/значение в строку сообщения.

person Simon Lee    schedule 27.05.2011
comment
Мне нужно добавить новый параметр в существующий NSURLRequest, а не создавать новый запрос. Я считаю, что сначала его нужно преобразовать в NSMutableURLRequest. Чего я не знаю, так это как получить существующие данные POST. - person Tim; 27.05.2011
comment
Другими словами, как вы получаете postString существующего запроса? - person Tim; 27.05.2011
comment
Вы можете получить доступ к - (NSData *)HTTPBody, который вы можете закодировать в NSString, пары ключ/значение - person Simon Lee; 27.05.2011
comment
Существующие почтовые данные закодированы в UTF8, как в вашем примере. Как я могу изменить кодировку? Затем создать новую строку с новыми параметрами? затем закодируйте новые данные сообщения - person Tim; 27.05.2011
comment
Это должно работать, но я не могу проверить это в данный момент.... NSMutableString *existingPost = [[NSMutableString alloc] initWithData:[req HTTPBody] encoding:NSUTF8StringEncoding]; [existingPost appendFormat:@&%@=%@, @name, @Locassa]; - person Simon Lee; 27.05.2011
comment
Кажется, у меня есть строка подключения NSURLConnection * ниже [request setHTTPBody]. Я просто взламывал и пытался понять, что может быть не так. - person okysabeni; 19.05.2014
comment
Где используется «соединение»? - person Arbitur; 19.11.2014
comment
@Arbitur В данном случае не используется. Вы можете сохранить его для дальнейшего использования на случай, если вам понадобится отменить запрос (например, если пользователь отклоняет просмотр, но запрос не выполнен). Но initWithRequest запускает запрос и возвращает ссылку NSURLConnection, если она вам нужна (и вы можете проверить, что это не nil, чтобы убедиться, что запрос запущен нормально). - person Rob; 07.01.2015
comment
Однако этот ответ неверен. Вы не должны запускать соединение, а затем продолжать изменять запрос. (См. ответ Кевина ниже.) Сначала нужно закончить настройку запроса, и только потом запускать соединение. И, очевидно, предполагается, что вы реализовали методы NSURLConnectionDataDelegate. И, конечно же, вы должны в процентах экранировать значения, которые вы вставляете в свой HTTPBody. - person Rob; 07.01.2015

Все изменения в NSMutableURLRequest должны быть сделаны до вызова NSURLConnection.

Я вижу эту проблему, когда копирую и вставляю приведенный выше код, запускаю TCPMon и вижу, что запрос GET вместо ожидаемого POST.

NSURL *aUrl = [NSURL URLWithString:@"http://www.apple.com/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl
                                     cachePolicy:NSURLRequestUseProtocolCachePolicy
                                 timeoutInterval:60.0];


[request setHTTPMethod:@"POST"];
NSString *postString = @"company=Locassa&quality=AWESOME!";
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];

NSURLConnection *connection= [[NSURLConnection alloc] initWithRequest:request 
                                                         delegate:self];
person Kevin    schedule 31.12.2012

Предыдущие посты о формировании POST запросов во многом правильны (добавляйте параметры в тело, а не URL). Но если есть вероятность того, что входные данные содержат какие-либо зарезервированные символы (например, пробелы, амперсанд, знак плюса), вам нужно будет обработать эти зарезервированные символы. А именно, вы должны процент экранировать ввод.

//create body of the request

NSString *userid = ...
NSString *encodedUserid = [self percentEscapeString:userid];
NSString *postString    = [NSString stringWithFormat:@"userid=%@", encodedUserid];
NSData   *postBody      = [postString dataUsingEncoding:NSUTF8StringEncoding];

//initialize a request from url

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPBody:postBody];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

//initialize a connection from request, any way you want to, e.g.

NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

Где метод precentEscapeString определяется следующим образом:

- (NSString *)percentEscapeString:(NSString *)string
{
    NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                 (CFStringRef)string,
                                                                                 (CFStringRef)@" ",
                                                                                 (CFStringRef)@":/?@!$&'()*+,;=",
                                                                                 kCFStringEncodingUTF8));
    return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
}

Обратите внимание, что был многообещающий метод NSString, stringByAddingPercentEscapesUsingEncoding (теперь устаревший), который делает что-то очень похожее, но не поддавайтесь искушению использовать его. Он обрабатывает некоторые символы (например, пробел), но не некоторые другие (например, символы + или &).

Современный эквивалент — stringByAddingPercentEncodingWithAllowedCharacters, но опять же, не поддавайтесь искушению использовать URLQueryAllowedCharacterSet, так как это также позволяет + и & проходить без экранирования. Эти два символа разрешены в более широком «запросе», но если эти символы появляются в значении внутри запроса, они должны экранироваться. Технически вы можете либо использовать URLQueryAllowedCharacterSet для создания изменяемого набора символов и удалить несколько символов, которые они туда включили, либо создать свой собственный набор символов с нуля.

Например, если вы посмотрите на кодирование параметров Alamofire, они берут URLQueryAllowedCharacterSet, а затем удалите generalDelimitersToEncode (который включает символы #, [, ] и @, но из-за исторической ошибки на некоторых старых веб-серверах нет ни ?, ни /) и subDelimitersToEncode (т.е. !, $, &, ', (, ), *, +, ,, ; и =). Это правильная реализация (хотя вы могли бы обсудить удаление ? и /), хотя и довольно запутанная. Возможно, CFURLCreateStringByAddingPercentEscapes более прямой/эффективный.

person Rob    schedule 29.03.2014
comment
Верно насчет stringByAddingPercentEscapesUsingEncoding:, но stringByAddingPercentEncodingWithAllowedCharacters: отлично работает с любым символом. Пример: URLString = [URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; - person Alejandro Cotilla; 06.02.2016
comment
@AlejandroDavidCotillaRojas — вы можете использовать stringByAddingPercentEncodingWithAllowedCharacters, но вы не можете использовать URLQueryAllowedCharacterSet, так как это включает + и & (это разрешенные символы в более широком запросе, но если эти символы появляются внутри значения в запросе, они должны экранироваться, что и этот набор символов не пойдет). Таким образом, вы можете либо использовать URLQueryAllowedCharacterSet для создания изменяемого набора символов и удалить несколько символов, которые они туда включили, либо создать свой собственный набор символов с нуля. Или используйте CFURLCreateStringByAddingPercentEscapes. - person Rob; 06.02.2016
comment
Отличный ответ, действительно обосновывает использование Alamofire, чтобы избежать всей этой глубины! - person Dan Rosenstark; 03.03.2016
comment
Учитывая, что CFURLCreateStringByAddingPercentEscapes теперь устарел, вам действительно следует создать соответствующий набор символов самостоятельно. См. stackoverflow.com/a/54742187/1271826. - person Rob; 18.02.2019

Приведенный выше пример кода был действительно полезен для меня, однако (как было указано выше), я думаю, вам нужно использовать NSMutableURLRequest, а не NSURLRequest. В его нынешнем виде я не мог заставить его ответить на вызов setHTTPMethod. Изменение типа исправило ситуацию.

person David Fulton    schedule 04.07.2012

Любой, кто ищет быстрое решение

let url = NSURL(string: "http://www.apple.com/")
let request = NSMutableURLRequest(URL: url!)
request.HTTPBody = "company=Locassa&quality=AWESOME!".dataUsingEncoding(NSUTF8StringEncoding)
person spaceMonkey    schedule 15.09.2016