Добавить данные в запрос POST NSURLRequest


83

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


3
Опишите свой вопрос кодом.
Tirth

Ответы:


192

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

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];

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


2
Мне нужно добавить новый параметр в существующий NSURLRequest, а не создавать новый запрос. Я считаю, что сначала его нужно преобразовать в NSMutableURLRequest. Я не знаю, как получить существующие данные POST.
Тим

1
Другими словами, как получить postString существующего запроса?
Тим

1
Вы можете получить доступ к - (NSData *) HTTPBody, которое вы можете закодировать в NSString, пары ключ / значение
Саймон Ли

Существующие данные сообщения закодированы в UTF8, как в вашем примере. Как я могу изменить кодировку? Затем создать новую строку с новыми параметрами? затем закодируйте данные нового сообщения
Тим

1
Это должно сработать, но я не могу его сейчас протестировать .... NSMutableString * existingPost = [[NSMutableString alloc] initWithData: [req HTTPBody] кодировка: NSUTF8StringEncoding]; [existingPost appendFormat: @ "&% @ =% @", @ "name", @ "Locassa"];
Саймон Ли

16

Все изменения 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];

12

Предыдущие сообщения о формировании 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более прямолинейно / действенно.


Верно stringByAddingPercentEscapesUsingEncoding:, но stringByAddingPercentEncodingWithAllowedCharacters:отлично работает с любым персонажем. Пример: URLString = [URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
Алехандро Котилья

@AlejandroDavidCotillaRojas - вы можете использовать stringByAddingPercentEncodingWithAllowedCharacters, но вы не можете использовать URLQueryAllowedCharacterSet, поскольку это включает +и &(это разрешенный символ в рамках более широкого запроса, но если эти символы появляются в значении в запросе, они должны экранироваться, что этот набор символов не будет делать ). Таким образом, вы можете использовать либо URLQueryAllowedCharacterSetдля создания изменяемого набора символов и удаления нескольких символов, которые они туда включили, либо создать свой собственный набор символов с нуля. Или используйте CFURLCreateStringByAddingPercentEscapes.
Роб

Отличный ответ, действительно аргумент в пользу использования Alamofire, чтобы избежать всей этой глубины!
Дэн Розенстарк 03

Учитывая, что CFURLCreateStringByAddingPercentEscapesэто теперь не рекомендуется, вам действительно следует создать соответствующий набор символов самостоятельно. См. Stackoverflow.com/a/54742187/1271826 .
Роб

8
 NSURL *url= [NSURL URLWithString:@"https://www.paypal.com/cgi-bin/webscr"];
 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl
                                                        cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                    timeoutInterval:10.0];
[request setHTTPMethod:@"POST"];
 NSString *postString = @"userId=2323";
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];

8

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


1

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

let url = NSURL(string: "http://www.apple.com/")
let request = NSMutableURLRequest(URL: url!)
request.HTTPBody = "company=Locassa&quality=AWESOME!".dataUsingEncoding(NSUTF8StringEncoding)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.