AFNetworking 2.0 fügt der GET-Anforderung Header hinzu

78

Ich habe gerade angefangen, AFNetworking 2.0 zu verwenden, und ich habe mich gefragt, wie ich Header in eine HTTP-Get-Anfrage eingefügt habe. In der Dokumentation wird ein GET wie folgt eingerichtet:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = @{@"foo": @"bar"};
[manager POST:@"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];

Aber da wir nicht damit umgehen, NSURLRequestsbin ich mir nicht sicher, wie ich HTTP-Header setzen soll.

Jede Hilfe wäre dankbar.
Grüße,
Mike

Mackey18
quelle
3
@ RyanR kein Duplikat. Das ist von AFN 1.x nicht 2.0. Seitdem hat sich alles komplett verändert.
Mackey18
Laut dem Migrationsleitfaden existiert AFHttpClient weiterhin und ist weiterhin dafür verantwortlich,
HTTP-
2
Ein Open Source Projekt mit widersprüchlicher Dokumentation? NEVAR. AFHTTPClient -> AFHTTPSessionManager anscheinend. Du hast recht, mit setDefaultHeadersaugt. Eine 30-sekündige Suche in den Dokumenten und ich finde, dass AFHTTPRequestSerializer für HTTPHeaders pro Anfrage verantwortlich ist.
RyanR
2
@ RyanR D'oh hat das verpasst! Dank Ihrer Feststellung die richtige Methode gefunden:manager.requestSerializer setValue:<#(NSString *)#> forHTTPHeaderField:<#(NSString *)#>
Mackey18

Antworten:

84

Die fantastische Dokumentation für AFNetworking 2.0 macht es etwas schwierig, dies zu finden, aber es ist da. Auf dem AFHTTPRequestSerializerist -setValue:forHTTPHeaderField:.

Wenn Sie dem empfohlenen Ansatz zum Erstellen eines Sitzungsmanagers folgen, der von diesem abgeleitet AFHTTPSessionManagerist, kann diese Klasse alternativ eine Methode zum Ändern von Headern für jede Anforderung überschreiben -dataTaskWithRequest:completionHandler:. Ich verwende dies, um Anforderungen zu prüfen und Header von Fall zu Fall zu ändern, und ziehe es vor, den Serializer zu ändern, da er die Verantwortung für das in diesem Manager enthaltene Netzwerk behält (und das Durcheinander mit Singletons vermeidet).

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURLResponse *, id, NSError *))completionHandler
{
    static NSString *deviceId;
    if(!deviceId)
    {
        deviceId = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    }

    NSMutableURLRequest *req = (NSMutableURLRequest *)request;
    // Give each request a unique ID for tracing
    NSString *reqId = [NSString stringWithFormat:@"%@+%@", deviceId, [[NSUUID UUID] UUIDString] ];
    [req setValue:reqId forHTTPHeaderField:"x-myapp-requestId"];
    return [super dataTaskWithRequest:req completionHandler:completionHandler];
}
RyanR
quelle
4
Hast du etwas dagegen, einen Ausschnitt davon hinzuzufügen, wie dies verwendet werden würde? Ich bin ein Android-Typ, der versucht, iOS zu lernen, und ich bin mir nicht ganz sicher, wie ich diese Antwort verwenden soll.
ChuckKelly
1
aber warum sind die Header im Serialisierer gesetzt ??? Mir ist auch aufgefallen, dass sie auf diese Weise dauerhaft sind. Wenn Sie also ein Header-Feld festgelegt haben, bleibt es für immer dort! (Ich musste meine eigene Methode hinzufügen, um sie zu entfernen)
Peter Lapisu
4
@PeterLapisu, der diese Methode mit nilfor aufruft, valueentfernt sie. Sie sollten keine Header verwenden, um kurzlebige Werte vom Client an den Server zu übergeben - das ist Teil Ihrer Nutzlast. Header sind für Werte gedacht, die sich nicht häufig ändern, z. B. Authentifizierungsdaten, Cache-Steuerung usw. Einige Server bestimmen anhand der übereinstimmenden Header-Parameter sogar, ob zwischengespeicherte Daten zurückgegeben werden sollen, was Sie nicht versehentlich verhindern möchten. Wenn Sie Header nur für einzelne Anforderungen festlegen müssen, sind vermutlich Daten in der Nutzlast enthalten.
RyanR
2
@PeterLapisu Ich weiß nicht, was die AFN-Teams argumentiert haben, aber aus gestalterischer Sicht ist dies definitiv sinnvoll. Der Serializer ist das Ding, das weiß, wie man die Anfrage und Antwort für jedes Protokoll, das Sie verwenden, codiert / decodiert. Wenn es über FTP wäre, würden Sie diese Informationen anders serialisieren als über eine Nachrichtenwarteschlange. Auf diese Weise kennt nur die für diese Art von Transport verantwortliche Komponente die Details des Transports (dies ist Teil von [Kapselung] ( en.wikipedia.org/wiki/… )
RyanR
2
Ich glaube immer noch, dass es ein schlechtes Designproblem ist. github.com/AFNetworking/AFNetworking/issues/1793
Peter Lapisu
146

Hier ist ein Beispiel mit AFNetworking 2.0

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:@"calvinAndHobbesRock" forHTTPHeaderField:@"X-I do what I want"];

[manager GET:@"http://localhost:3000" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];

Der Schlüssel sind die folgenden 2 Zeilen:

manager.requestSerializer = [AFJSONRequestSerializer serializer];
[manager.requestSerializer setValue:@"calvinAndHobbessRock" forHTTPHeaderField:@"X-I-do-what-I-want"];
Shaheen Ghiassy
quelle
1
Danke für das Beispiel !!
Diegomen
17

Das Hinzufügen eines Antwort- und Anforderungsserialisierers löste mein Problem.

manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.requestSerializer = [AFJSONRequestSerializer serializer];

[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
user2073541
quelle
7

Ich habe dieses Formular verwendet, um einen Termin mit einem bestimmten Header zu vereinbaren.

AFHTTPRequestOperationManager *operationManager = [AFHTTPRequestOperationManager manager];
[operationManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[operationManager.requestSerializer setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

[operationManager POST:url
            parameters:params
               success:^(AFHTTPRequestOperation *operation, id responseObject) {

                   if (success) {
                       success(responseObject);
                   }

               }
               failure:^(AFHTTPRequestOperation *operation, NSError *error) {

                   NSLog(@"Error: %@", [error description]);

               }
 ];
Carlos Avalos
quelle
Denken Sie nicht, dass diese Header ab dem Zeitpunkt, an dem Sie sie festgelegt haben, mit einer beliebigen Anfrage gesendet werden?
Vahotm
6

Hier ist, was ich für die beste Option halte. Konfigurieren Sie in einem Singleton irgendwo ein AFHTTPSessionManagerusing a NSURLSessionConfigurationund verwenden Sie dieses dann AFHTTPSessionManagerjedes Mal , wenn Sie eine Anfrage stellen möchten.

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.HTTPAdditionalHeaders = @{@"Accepts": @"application/json"};

mySingletonSessionManager = [[AFHTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:kMyBaseUrl] sessionConfiguration:config];
Chris
quelle
3

Ich habe das getan ... für diejenigen, die Token weitergeben

[manager.requestSerializer setValue:[NSString stringWithFormat:@"Token token=\"%@\"", _userObj.oAuth] forHTTPHeaderField:@"Authorization"];
Serge Pedroza
quelle
-3

Verwenden Sie den folgenden Code, um einen beliebigen Headerwert einzugeben:

[[FRHTTPReqManager sharedManager].requestSerializer setValue:value forHTTPHeaderField:key];
Evana
quelle