AFNetworkingのAFHTTPSessionManagerを使っていてBodyに素のXMLを入れてPOSTしたかったのだが、そのやり方がなかなか見当たらずソースコードを読んで解決したのでメモしておく。
ざっくり言うとAFHTTPSessionManagerでのPOSTはこんな感じに行う。
let manager = AFHTTPSessionManager()
manager.POST(url, parameters: params, success: { (task, response) -> Void in
// success
}) { (task, error) -> Void in
// failure
}
POSTするパラメータがあれば、上のメソッドのparameters
のところにdictionaryとかで渡せばいいはずだが(確か)、今回やりたいのはBodyにXMLのテキストを入れるということだった。
まず気軽にparametersにXML文字列を直接渡してみようなどとやってみたら失敗した。
let manager = AFHTTPSessionManager()
let xmlstr = "<?xml ..."
manager.POST(url, parameters: xmlstr, success: { (task, response) -> Void in
// success
}) { (task, error) -> Void in
// failure
}
これでできたリクエストを見てみるとBodyにはこんなのが入っていた。
(null)=%3C%3Fxml%20...
どうやら名前が空で値がURLエンコード済文字列のパラメータをBodyとして設定してしまっているらしい。
ソースコードを読むとそれがデフォルトの動作だということがわかった。
// AFURLRequestSerialization.m
switch (self.queryStringSerializationStyle) {
case AFHTTPRequestQueryStringDefaultStyle:
query = AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding);
break;
}
じゃあデフォルトじゃない動作は、というと上のコードの近くにあった。
// AFURLRequestSerialization.m
if (self.queryStringSerialization) {
NSError *serializationError;
query = self.queryStringSerialization(request, parameters, &serializationError);
if (serializationError) {
if (error) {
*error = serializationError;
}
return nil;
}
}
self.queryStringSerialization
はBlockで、このブロックを設定してparameterのシリアライズをカスタマイズできるよ、ということのようだった。
つまり文字列をそのままBodyに入れたい場合は、
let manager = AFHTTPSessionManager()
let xmlstr = "<?xml ..."
manager.requestSerializer.setQueryStringSerializationWithBlock { (request, params, error) -> String! in
return params as! String
}
manager.POST(url, parameters: xmlstr, success: { (task, response) -> Void in
// success
}) { (task, error) -> Void in
// failure
}
manager.requestSerializer.setQueryStringSerializationWithBlock
でparameterをそのまま文字列と返してあげればよかった。
これで解決できた。良かった。