- TOP>
- iOS Objective-C, Swift Tips>
- HTTP GETとPOST(Swift)
HTTP GETとPOST(Swift)アプリからサーバにHTTPでGET、あるいはPOSTリクエストすることは結構あると思う。しかし、それはiOSだとなかなか面倒だったりする。早速GETから。
HTTPリクエストに必要なものはURLRequestとURLSessionの2つである。まずはURLを指定してURLRequestを生成する。次に、URLSessionだが、Webページを取得する等の単純なGETならsharedメソッドから共有のセッションを取得すれば良いだろう。
そして、取得したセッションのdataTaskメソッドにURLRequestを渡して呼び出し、生成されたタスクのresumeメソッドを呼び出せばGETリクエストできる。
1 2 3 4 5 6 7 8 9 10 11 12 | let url = URL(string: "http://192.168.0.xx:8080/" )
let request = URLRequest(url: url!)
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if error == nil , let data = data, let response = response as ? HTTPURLResponse {
print( "Content-Type: \(response.allHeaderFields[" Content- Type "] ?? " ")" )
print( "statusCode: \(response.statusCode)" )
print(String(data: data, encoding: String.Encoding.utf8) ?? "" )
}
}.resume()
|
ただし、接続先がhttpsでなくhttpの場合は、セキュアでないアクセスとしてATSにブロックされてしまうので以下も必要となる。ここでは、すべてのhttpのアクセスを許可しているが、セキュリティ的に問題があるかも知れないので、実際には必要なドメインのみ許可しよう。ATSの詳細についてはこちらをご参照いただければと思う。
1 2 3 4 5 | < key >NSAppTransportSecurity</ key >
< dict >
< key >NSAllowsArbitraryLoads</ key >
< true >
</ true ></ dict >
|
dataTaskメソッドに渡すcompletionHandlerにはHTTPリクエスト完了時、Data、URLResponse、及びErrorの3つの引数が渡される。DataはHTTPリクエストが成功した場合にサーバから取得したデータ(Body)、URLResponseはHTTPヘッダやHTTPステータスコード、Errorはエラーがなければnilである。
completionHandler(クロージャ)の中ではHTTPレスポンスのうち、Body部分がData(バイト列)として渡される。このDataからHTMLを得るためには、エンコードを指定してStringに変換する必要がある。また、URLResponseはHTTPURLResponseにキャストすることによってstatusCodeを得ることができる。
GETだけでなく、もちろんPOSTも可能だ。GETとの違いはURLRequestのhttpMethodプロパティで"POST"を指定することと、httpBodyプロパティにPOSTするデータを設定することである。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | let url = URL(string: "http://192.168.0.xx:8080/" )
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.httpBody = "os=iOS&version=11&language=日本語" .data(using: .utf8)
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if error == nil , let data = data, let response = response as ? HTTPURLResponse {
print( "Content-Type: \(response.allHeaderFields[" Content- Type "] ?? " ")" )
print( "statusCode: \(response.statusCode)" )
print(String(data: data, encoding: .utf8) ?? "" )
}
}.resume()
|
このPOSTデータをSinatra(Ruby)で書いたサーバ側で受け取った結果は以下である。
os=iOS
version=11
language=日本語
192.168.0.27 - - [28/Jan/2018:09:14:22 +0900] "POST / HTTP/1.1" 200 19 0.0009
192.168.0.27 - - [28/Jan/2018:09:14:22 JST] "POST / HTTP/1.1" 200 19
- -> /
もちろん、サーバからテキストだけでなくJSONを受け取ることもできる。GETで受け取ったJSON形式のDataをJSONSerialization.jsonObjectメソッドに渡して呼びだ出せば、結果をDictionaryで得ることもできる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | let url = URL(string: "http://192.168.0.xx:8080/json" )
let request = URLRequest(url: url!)
let session = URLSession.shared
session.dataTask(with: request) { (data, response, error) in
if error == nil , let data = data, let response = response as ? HTTPURLResponse {
print( "Content-Type: \(response.allHeaderFields[" Content- Type "] ?? " ")" )
print( "statusCode: \(response.statusCode)" )
let dic = try ! JSONSerialization.jsonObject(with: data, options: .allowFragments) as ! [String: Any]
print( "name: \(dic[" name "] as! String)" )
print( "price: \(dic[" price "] as! Int)" )
}
}.resume()
|
Xcodeのコンソールに表示された結果は以下である。
Content-Type: application/json
statusCode: 200
name: ラーメン
price: 500
確認に使用したRubyのスクリプト(httpserver.rb)も載せておく。これをruby httpserver.rb -o 0.0.0.0 -p 8080で起動した。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | require 'sinatra'
get "/" do
"Hello, World!"
end
post "/" do
params. each do |key, value|
puts( "#{key}=#{value}" )
end
"Hello, World!(POST)"
end
get "/json" do
content_type :json
{ name: "ラーメン" , price: 500 }.to_json
end
|
(2018/01/28)
Copyright© 2004-2019 モバイル開発系(K) All rights reserved.
|