対象: HTTP GETとPOST(Swift)アプリからサーバにHTTPでGET、あるいはPOSTリクエストすることは結構あると思う。しかし、それはiOSだとなかなか面倒だったりする。早速GETから。 HTTPリクエストに必要なものはURLRequestとURLSessionの2つである。まずはURLを指定してURLRequestを生成する。次に、URLSessionだが、Webページを取得する等の単純なGETならsharedメソッドから共有のセッションを取得すれば良いだろう。 そして、取得したセッションのdataTaskメソッドにURLRequestを渡して呼び出し、生成されたタスクのresumeメソッドを呼び出せばGETリクエストできる。 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 { // HTTPヘッダの取得 print("Content-Type: \(response.allHeaderFields["Content-Type"] ?? "")") // HTTPステータスコード print("statusCode: \(response.statusCode)") print(String(data: data, encoding: String.Encoding.utf8) ?? "") } }.resume() ただし、接続先がhttpsでなくhttpの場合は、セキュアでないアクセスとしてATSにブロックされてしまうので以下も必要となる。ここでは、すべてのhttpのアクセスを許可しているが、セキュリティ的に問題があるかも知れないので、実際には必要なドメインのみ許可しよう。ATSの詳細についてはこちらをご参照いただければと思う。
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するデータを設定することである。 let url = URL(string: "http://192.168.0.xx:8080/") var request = URLRequest(url: url!) // POSTを指定 request.httpMethod = "POST" // POSTするデータをBodyとして設定 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 { // HTTPヘッダの取得 print("Content-Type: \(response.allHeaderFields["Content-Type"] ?? "")") // HTTPステータスコード 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で得ることもできる。 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 { // HTTPヘッダの取得 print("Content-Type: \(response.allHeaderFields["Content-Type"] ?? "")") // HTTPステータスコード print("statusCode: \(response.statusCode)") // JSONからDictionaryへ変換 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で起動した。 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.
[Home]
|