Dołącz dane do żądania POST NSURLRequest

83

Jak dołączyć dane do istniejącego POST NSURLRequest? Muszę dodać nowy parametr userId=2323.

Tim
źródło
3
Opisz swoje pytanie jakimś kodem.
Tirth

Odpowiedzi:

192

Jeśli nie chcesz korzystać z klas innych firm, możesz ustawić treść posta w następujący sposób ...

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

Po prostu dołącz swoją parę klucz / wartość do ciągu postu

Simon Lee
źródło
2
Muszę dodać nowy parametr do istniejącego NSURLRequest, a nie tworzyć nowe żądanie. Uważam, że najpierw należy go przekonwertować na NSMutableURLRequest. Nie wiem, jak uzyskać istniejące dane POST.
Tim
1
Czy innymi słowy, w jaki sposób otrzymujesz postString istniejącego żądania?
Tim
1
Możesz uzyskać dostęp do - (NSData *) HTTPBody, które możesz zakodować w NSString, pary klucz / wartość
Simon Lee
Istniejące dane postu są kodowane w UTF8, jak w przykładzie. Jak mogę odwrócić kodowanie? Następnie utworzysz nowy ciąg z nowymi parametrami? następnie zakoduj nowe dane postu
Tim
1
To powinno działać, ale nie mogę tego teraz przetestować .... NSMutableString * existingPost = [[NSMutableString assign] initWithData: [req HTTPBody] encoding: NSUTF8StringEncoding]; [existingPost appendFormat: @ "&% @ =% @", @ "name", @ "Locassa"];
Simon Lee,
16

Wszystkie zmiany w NSMutableURLRequestdomenie należy wprowadzić przed wywołaniemNSURLConnection .

Widzę ten problem, gdy kopiuję i wklejam powyższy kod, uruchamiam TCPMoni widzę, że żądanie jest GETzamiast oczekiwanego 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];
Kevin
źródło
12

Poprzednie posty dotyczące POSTżądań formowania są w dużej mierze poprawne (dodaj parametry do treści, a nie do adresu URL). Ale jeśli jest jakaś szansa, że ​​dane wejściowe zawierają jakiekolwiek zastrzeżone znaki (np. Spacje, ampersand, znak plus), wtedy będziesz chciał obsłużyć te zastrzeżone znaki. Mianowicie, powinieneś procentowo zmienić dane wejściowe.

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

Gdzie precentEscapeStringmetoda jest zdefiniowana w następujący sposób:

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

Zauważ, że była obiecująca NSStringmetoda stringByAddingPercentEscapesUsingEncoding(obecnie przestarzała), która robi coś bardzo podobnego, ale opiera się pokusie jej użycia. Obsługuje niektóre znaki (np. Znak spacji), ale nie niektóre inne (np. Znaki +lub &).

Współczesny odpowiednik jest stringByAddingPercentEncodingWithAllowedCharacters, ale znowu nie być skłonny do użytku URLQueryAllowedCharacterSet, jak również pozwala +i &przekazać Niecytowany. Te dwa znaki są dozwolone w ramach szerszego „zapytania”, ale jeśli te znaki pojawiają się w wartości w zapytaniu, muszą zostać zmienione. Technicznie możesz użyćURLQueryAllowedCharacterSet do zbudowania zmiennego zestawu znaków i usunąć kilka postaci, które tam umieścili, lub zbudować własny zestaw znaków od podstaw.

Na przykład, jeśli spojrzeć na Alamofire za kodowanie parametrów , biorą URLQueryAllowedCharacterSet, a następnie usunąć generalDelimitersToEncode(który zawiera znaki #, [, ], i @, ale z powodu historycznego błędu w niektórych starych serwerów WWW, ani ?też nie /) i subDelimitersToEncode(czyli !, $, &, ', (, ), *, +, ,, ;, i =). Jest to poprawna implementacja (choć można debatować nad usunięciem ?i /), chociaż dość zawiła. Być może CFURLCreateStringByAddingPercentEscapesjest bardziej bezpośredni / skuteczny.

Obrabować
źródło
Prawda stringByAddingPercentEscapesUsingEncoding:, ale stringByAddingPercentEncodingWithAllowedCharacters:działa dobrze z każdą postacią. Przykład: URLString = [URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
Alejandro Cotilla
@AlejandroDavidCotillaRojas - Możesz używać stringByAddingPercentEncodingWithAllowedCharacters, ale nie możesz używać URLQueryAllowedCharacterSet, ponieważ obejmuje to +i &(są to dozwolone znaki w ramach szerszego zapytania, ale jeśli te znaki pojawiają się w wartości w zapytaniu, muszą być chronione przed ucieczką, czego ten zestaw znaków nie zrobi ). Możesz więc użyć URLQueryAllowedCharacterSetdo zbudowania zmiennego zestawu znaków i usunąć kilka znaków, które tam umieścili, lub zbudować własny zestaw znaków od podstaw. Lub użyj CFURLCreateStringByAddingPercentEscapes.
Rob
Świetna odpowiedź, naprawdę uzasadnia użycie Alamofire, aby uniknąć całej tej głębi!
Dan Rosenstark
Biorąc pod uwagę, że CFURLCreateStringByAddingPercentEscapesjest to przestarzałe, naprawdę powinieneś sam zbudować odpowiedni zestaw znaków. Zobacz stackoverflow.com/a/54742187/1271826 .
Rob
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]];
Alex Terente
źródło
8

Powyższy przykładowy kod był dla mnie bardzo pomocny, jednak (jak wskazano powyżej), myślę, że powinieneś NSMutableURLRequestraczej użyć niż NSURLRequest. W obecnej formie nie mogłem go zmusić do odpowiedzi na setHTTPMethodwezwanie. Zmiana typu naprawiła rzeczy.

David Fulton
źródło
1

Każdy, kto szuka szybkiego rozwiązania

let url = NSURL(string: "http://www.apple.com/")
let request = NSMutableURLRequest(URL: url!)
request.HTTPBody = "company=Locassa&quality=AWESOME!".dataUsingEncoding(NSUTF8StringEncoding)
spaceMonkey
źródło