[Cloud103]#2 curl初歩

# AGENDA

0.はじめに
1.TCP/IP通信の初歩
2.簡単ローカルWebサーバでやってみる
3.curlを使ってみる(Mac/Win)
4.curlを使ってみる(iPad)
5.curlでWep APIアクセス
6.ちゃんと勉強しよう

# 0.はじめに

[前回](http://qiita.com/nagahisa/items/307931622064a790622b)はPostmanでWebAPIアクセスやってみましたが、手順書などでWebAPIアクセス例を書く時はcurlを使うと便利です。前回のFace API仕様の最後にもcurl例が記載されています。

https://westus.dev.cognitive.microsoft.com/docs/services/563879b61984550e40cbbe8d/operations/563879b61984550f30395236
<img width="340" alt="1-01.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/2251d12d-6278-49f5-f417-a060b073e45f.png">



今回はcurlコマンドを使ったことが無い方を対象に、curlコマンドの初歩をやってみます。

**お詫び**
「管理者権限を持たないWindowsの人でも実行できるように」するつもりで準備していましたが、準備の途中で「Windows版nc.exeコマンドはバックドアに使われる恐れがある」とのネット情報があったため、該当部分は削除することにしました。
Windowsの人はハンズオンで実行できない部分が多いですがご容赦ください。


# 1.TCP/IP通信の初歩

「curlコマンドを使ったことが無い方」向けなので、超初歩的なことからボチボチやります :smile:

## (1)2つのプロセスのTCP/IP通信

Webサーバとブラウザなどのクライアントは「http(80),https(443)を使ったTCP/IP通信を行っている」なんて言いますよね。
でも、そもそもTCP/IP通信って一体なんなんでしょうね？
詳しい説明は書籍やネットワーク屋さんにおまかせして、何十年も昔にUN*X/Cのソフト屋さんだった僕の微かな記憶をたどると：

・ソケットってネットワーク用のファイルディスクリプタがある
・ソケット経由だとread/writeとか普通のファイル操作と同じ
・あるプロセスと別のプロセスは、IPアドレス：TCPポートの組み合わせ（＝TCP/IPソケット）でネットワーク経由で通信できる
・特定TCPポートでLISTENするTCP/IPソケット作ることができる

って、言葉だとよくわからないので Mac上の ncコマンドでやってみましょう。

## (2)nc = netcat = network + cat

　netcatコマンドの説明や使い方は以下のサイトがとても参考になります。

[ネットワーク診断の現場から（netcat編・その1）](http://www.intellilink.co.jp/article/column/security-net01.html)

一言でいうなら, networkで使えるcatコマンドなのかなぁ・・・
でも、LISTENモードがあるので、２つのプロセス間のTCP/IP通信をこんな感じで試すことができます。

サーバ側を-lオプションで起動（ポート:60000)

```
nc -l 60000
```

<img width="865" alt="1-01.JPG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/38026f0f-84f8-9902-e6f3-a8a361566012.jpeg">


クライアント側を起動（IP:localhost, ポート:60000)

```
nc localhost 60000
```
<img width="863" alt="1-02.JPG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/aacbb954-1636-22e9-8c43-a5b1a4bbefe7.jpeg">

チャット出来ます :smile:

<img width="862" alt="1-03.JPG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/42993929-d5fe-07b5-244c-3420506a26c2.jpeg">


Ctrl+D (EOF)を片方から送ると終了します。

では、ちょっとづつ netstatコマンドで見てみましょう。

・サーバ側を-lオプションで起動（ポート:60000)した時のnetstat

<img width="647" alt="1-04.JPG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/09c0e15f-4a6f-0197-d15b-9f00fedd26e5.jpeg">
60000でLISTENしていることがわかります。

・クライアント側を起動（IP:localhost, ポート:60000)した時のnetstat
<img width="653" alt="1-05.JPG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/f1cec53a-4f46-ded9-ea93-60d6c3955866.jpeg">

接続(ESTABLISHED)しましたね、でもこの図の 49406ってポートは何なんでしょう？？
これはクライアント側が使ってるTCP PORTです。
クライアント側からみれば、DEST POR=60000, SRC PORT=49406ってことですね。

なお、クライアント側はnetcatでなくても、telnetコマンドでも同じです。
(終了するときはサーバ側で Ctrl+D )

```
telnet localhost 60000
```

<img width="863" alt="1-06.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/79389/06e4d1d2-3623-d657-314c-a8579ff27278.jpeg">

**宿題**
サーバ側ポートを1024未満（たとえば "nc -l 1023"）にするとどうなるでしょう？
なんでそうなるんでしょう？？

# 2.簡単ローカルWebサーバでやってみる

ローカル環境にWebサーバを用意して、netcat/telnetクライアントでアクセスしてみます。
（Windowsの方もWebサーバはインストールしてください。）

## (1)simple web server on Chrome

MacでもWindowsでも使える Chrome Appの "simple web server"を導入します。

[simple web server](https://chrome.google.com/webstore/detail/simple-web-server/gajihfoegjplbobbcnikileolkbgjaaf?hl=ja)

本当は、もう少し高機能なChrome App Webサーバもありますが、ちょっと事情があって :sweat:
高機能版は最後に紹介します。

・右上の"CHROMEに追加"ボタン押します。

<img width="349" alt="2-02.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/e65708ac-9737-2c84-3b7b-0d43f5f389fb.png">

・追加されました。
<img width="287" alt="2-03.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/28605760-5089-5aad-9b82-ae63cc4ea61e.png">

・起動するとこんな画面になり、Webコンテンツをここで書くようです（どこに保存されているか不明 :sweat_smile: )。
<img width="253" alt="2-04.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/1e79ec09-f576-6a13-6393-84a236e1d1ca.png">

・テキトーなhtmlを入力して"Save All"します。

```
<html>
<body>
<h1>Hello KENZO!</h1>
</body>
</html>
```
<img width="253" alt="2-05.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/508ab62d-d2b4-36ab-0696-c57b7f9860e9.png">

・ブラウザでWeb表示確認します。
<img width="225" alt="2-06.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/ea146c68-feff-f163-e128-b941bd9f9f1d.png">


## (2)ローカルWebサーバをnetcat/telnetでアクセス(Mac)

Macの方は、このローカルWebサーバに netcat/telnetでアクセスしてみましょう。

"simple web server"って言うだけあって、以下の１行だけでレスポンス返してくれます。

```
GET / HTTP/1.1
```

・netcatアクセス(Mac)
<img width="433" alt="2-10.JPG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/66e2052a-e0bc-3eeb-fed0-cdb625b7acb1.jpeg">


・telnetアクセス(Mac)
<img width="433" alt="2-11.JPG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/986596f6-c43d-a230-7e32-890f916244af.jpeg">

ちなみに、Windowsにもtelnetコマンドがあるのですが、僕の環境だと起動はできるけど
<img width="244" alt="2-07.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/76335b1e-94ba-de62-612d-f70d164dc8a2.png">
一文字入力すると変な終わり方してしまいます。
<img width="242" alt="2-08.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/79389/114feab7-7730-1410-ec97-8ab9fd2a9c2c.png">

どなたかWindowsに詳しい方、使い方教えてください！！

ともあれ、クライアントからWebサーバへ　"GET / HTTP/1.1"などの呪文を送って通信開始するってのが、HTTPプロトコルの仕様です。

そんな呪文をいちいち覚えていられない訳で、クライアントのブラウザは呪文を自動的に送信してくれています。

Chromeが送っている呪文や返ってきてる呪文は"デベロッパーツール"で確認できます。

・"デベロッパーツール"を起動
<img width="232" alt="2-10.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/cb4afe7c-9d95-e445-df4e-f856296916bb.png">

・"Network"タブに切り替えてリロードすると"Header"が確認できる
<img width="455" alt="2-11.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/40748a97-ba98-5696-18dc-a76d6baabf82.png">


# 3.curlを使ってみる(Mac/Win)

コマンドラインツールでも、同様に呪文を処理してくれるものがあり、WGETやCURLが有名です。
今回は扱いませんが、WGETはURLに指定されたコンテンツをダウンロードするためのツールです。

curlの説明は以下を参考にしてください。

[curl日本語Wiki](https://ja.wikipedia.org/wiki/CURL)
[curlオフィシャルサイト](https://curl.haxx.se/)

<img width="319" alt="3-01.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/698fa527-80c7-233b-a64d-7c3837ed5e1d.png">

## (1)curlコマンドの準備(Mac)

Macの方はデフォルトでcurlが入っていると思いますので、念のため確認してください。

<img width="652" alt="3-01.JPG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/d170edbc-6b59-82e8-786a-d44468f51761.jpeg">

## (2)ローカルのWebサーバをcurlコマンドでアクセス(Mac)

```
curl -i http://localhost:3000
```

・curlアクセス(Mac)
<img width="499" alt="2-12.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/79389/59557f83-f0bd-2586-38ab-2fcbc61d4643.jpeg">


## (3)外部のWebサーバをcurlコマンドでアクセス(Mac)

外部サイトをcurlでアクセスするとこんな感じになります。

・curlアクセス(Mac)
<img width="667" alt="2-13.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/79389/39f23ae7-8de3-432c-0353-3806b5b94880.jpeg">


なお、Webブラウザやcurlコマンドは "GET / HTTP/1.1"だけでなく様々な呪文を唱えてくれていますので、nc/telnetでは外部アクセスは行わないでください。

もし間違ってやってしまうと。こんな感じのこわーいメッセージが返ってきてビビります。

・ncアクセス(Mac)
<img width="746" alt="2-14.JPG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/8b0c742c-20f8-af03-dca3-6c22ea9c6e30.jpeg">

## (4)curlコマンドの準備(Win)

https://curl.haxx.se/download.html
curl-7.54.1-win64-mingw.7z
展開してできたcurl-7.54.1-win64-mingwのbin配下をどこかにコピーします。
（例では Desktop¥1.Tools¥curl)

<img width="385" alt="2-23.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/99c8c35d-703f-1bf1-26d6-2a7bcb786651.png">


## (5)ローカルのWebサーバをcurlコマンドでアクセス(Win)

<img width="446" alt="2-22.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/8bb1d19b-96c3-b024-65eb-007ec7536180.png">

-vもちゃんと使えます(>で表示された部分が、サーバに送った呪文です）
<img width="355" alt="2-24.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/9a86bb52-61d3-63b0-bdaa-3d0188cef43a.png">


# 4.curlを使ってみる(iPad)

と、ここまで書いて来てなんですが、特にオフィス環境などでは Proxyなどの関係で、外部サイトへのcurlアクセスが難しいケースがあります。
でも大丈夫、このセクションでは「iPadでcurl」について説明します。

## (1)iCurlHTTPのインストール

iPadで以下のサイトにアクセスして、下の方にある　"Download on the AppSote"ボタンからインストールできます。（もちろん、AppStoreアプリからでも）

[icurlhttpサイト](http://www.jasonacox.com/icurlhttp/)

<img width="447" alt="4-01.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/d3c41f71-166f-5977-a73a-02465afe5b0b.png">

iPad画面

![4-02.PNG](http://qiita-image-store.s3.amazonaws.com/0/79389/e8f212b8-a696-19fe-8bd1-71920621dd0e.png)

## (2)iCurlHTTPを使ってみる

試しに、上の例でもやった https://www.google.com で試してみましょう。
302 Redirectが返ってくるはずです。

・上のURI欄に"https://www.google.com"入力して実行すると
![4-03.PNG](http://qiita-image-store.s3.amazonaws.com/0/79389/02dba397-951f-c242-09ac-f8db006cee91.png)

・なんとRedirectを判断して「移動先アクセスするか？」って聞いてきます。
折角なので、"Yes"でお願いしちゃいましょう。

![4-04.PNG](http://qiita-image-store.s3.amazonaws.com/0/79389/83c2e624-9f72-921f-d8d4-014805b883b5.png)

## (3)iCurlHTTPの"Verbose"を見てみる

iCurlHTTPの下の選択はUser-Agentのようですが、右上に "Basic|Verbose"の切替があるので試してみましょう。

なお表示を簡単にするために、先ほどの https://www.google.com ではなく、http://www.google.com で実行して、リダイレクト確認は"No"で終了させています。

・Basicだと、curl -i同様にレスポンスが確認できます。
![4-05.PNG](http://qiita-image-store.s3.amazonaws.com/0/79389/2d1a20a4-3232-b5a2-e41a-568f6e866239.png)

・Verboseだとcurl -v同様にリクエストも確認できます(>>で始まる部分）。
![4-06.PNG](http://qiita-image-store.s3.amazonaws.com/0/79389/7862d841-9c83-b73d-fc2c-cdd68bfcd0f3.png)

上のなんちゃってWebサーバ(simple web server)では"GET / HTTP/1.1"だけで行けちゃいましたが、普通は最低
GET / HTTP/1.1
Host: xxxx
User-Agent: xxxx
くらいは指定します。

この図では、User-AgentでちゃんとiPadが指定されていることが分かりますね。


# 5.curlで外部Web APIアクセス

PostmanでやったMS Face APIも curlで実行出来ますが、今回はcurl初歩として「簡単な」Web APIを扱ってみます。

「簡単な」の定義ですが、認証なし・GETだけでいい感じのデータが取れるWebサービスです :smile:


## (1)お天気情報

こんなサービスがあります。

[Weather Hacks](http://weather.livedoor.com/weather_hacks/webservice)

![4-01.JPG](http://qiita-image-store.s3.amazonaws.com/0/79389/6fe64f29-21e5-c3ab-ebf5-78e620fb4464.jpeg)

[ 全国の地点定義表（RSS）](http://weather.livedoor.com/forecast/rss/primary_area.xml)
をみると、東京のidは"130010"のようです。

ブラウザでアクセスしてみます。

```
http://weather.livedoor.com/forecast/webservice/json/v1?city=130010
```
[ここをクリック](http://weather.livedoor.com/forecast/webservice/json/v1?city=130010)

![4-03.JPG](http://qiita-image-store.s3.amazonaws.com/0/79389/d41d6de5-f4e9-b760-bc69-f6b627b7dc69.jpeg)

## (2)curlでアクセスしてみる (Mac)

ターミナルを開いて以下を実行すると：
```
curl -s http://weather.livedoor.com/forecast/webservice/json/v1?city=130010
```

<img width="648" alt="4-04.JPG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/9cfda477-ce05-853c-e505-4a57044c5c30.jpeg">

JSONが返って来ているので jqで整形してみやすくします。
もしjq入ってないなら、以下サイトから是非 jq 入れましょう！（スミマセン、僕はこのインストール方法は試してません:p)

[jqサイト](https://stedolan.github.io/jq/)
<img width="515" alt="5-01.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/ed2d77a3-2c84-3600-0323-ae75d8e86c3a.png">



```
curl -s http://weather.livedoor.com/forecast/webservice/json/v1?city=130010 | jq .
```
<img width="649" alt="4-05.JPG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/15ba902f-147c-a172-72a4-859a50eb6aee.jpeg">

最後の天気情報だけワンライナーで取れるようにしましょう。

```
curl -s http://weather.livedoor.com/forecast/webservice/json/v1?city=130010 | jq . | grep text
```

<img width="654" alt="4-06.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/79389/54829d32-88f7-0313-d50c-8c8c919fa33c.jpeg">


## (3)Windows版のjq.exeを用意する

以下からWindows版exeもダウンロード可能です。
https://stedolan.github.io/jq/

ダウンロードしたjq-win64.exeをどこかに（例では Desktop¥1.Tools)おきます。

<img width="437" alt="5-02.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/6ea10f73-e7af-b892-db8e-5a3fe9007fa7.png">


## (4)curlでアクセスしてみる (Win)

### curlだけ
```
curl\curl.exe -s http://weather.livedoor.com/forecast/webservice/json/v1?city=130010
```

<img width="486" alt="5-34.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/9a20a347-ed6e-3a48-6686-53fb5ec8b7c4.png">

### curlとjq組合せ
```
curl\curl.exe -s http://weather.livedoor.com/forecast/webservice/json/v1?city=130010 | jq-win64 .
```
<img width="487" alt="5-33.PNG" src="http://qiita-image-store.s3.amazonaws.com/0/79389/9c9e4d71-1dac-7f89-a5bd-104974deb02a.png">


## (5)curlでアクセスしてみる (iPad)

同じURLをiPadでもアクセスしてみましょう。
![5-30.PNG](http://qiita-image-store.s3.amazonaws.com/0/79389/9ab6a1e5-067e-f81c-205e-f8b307d46778.png)

日本語表示には対応してないようですが、文字化けではなく文字コードを表示してくれているのがありがたいですね。

残念ながらjqのようにJSON表示を見やすく表示する方法は見つけることが出来ませんでした。
どなたか良い方法を見つけたらぜひ教えてください。

なお、iCurlHTTPの環境設定（Method指定の左側の歯車アイコン）を見ると認証なども設定できるようです。

![5-31.PNG](http://qiita-image-store.s3.amazonaws.com/0/79389/e4baf22f-e165-1df7-4765-8eb8412ff97c.png)
![5-32.PNG](http://qiita-image-store.s3.amazonaws.com/0/79389/a20c5857-2708-ba7c-79f2-001b10b3f519.png)

Basic認証かかっているサイトはcurlコマンドでは"curl -u ID:PASS"のようなオプションで指定しますが、それも出来そうです（試してないけど:p）

## (6)独り言

Windows curl.exeの場合、cmd.exeの挙動がMac/LinuxのShellと違うので、特殊文字を含んだオプションを指定する場合などは注意が必要です。
手順書にのせるcurl送信例は、Mac/Linux curlで書いた方が楽かもしれません。
（もっと言うとcurl使うなら Mac/Linuxが良い・・・ってそれ言っちゃダメか :sweat_smile:  )


# 6.ちゃんと勉強しよう

今回はHTTPプロトコル上のリクエスト・レスポンスやヘッダを「呪文」の一言で片づけるなど、相変わらずいい加減な内容になっています。しかも、curl/jqの多彩なオプションもほとんど説明していません（今回の内容だけではMS Face APIアクセスは無理です。あれはPOSTなんで）。

curlはとても面白いコマンドですしWindows上でも簡単に試せますので、是非トライしてみてください。

## (1)個人的なお勧め本（ちょっと古いけど）

Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESS plus)
 単行本（ソフトカバー） 2010/4/8 山本 陽平  (著)
https://www.amazon.co.jp/dp/4774142042

## (2)実は去年も似たようなことをやってます。

[Cloud101]#2 HTTPとHTMLを感じる
http://qiita.com/nagahisa/items/b42a95945f13ad391955


## (3)ソケット通信～HTTP

まつもと直伝　プログラミングのオキテ 第16回　ネットワーク・プログラミング（ソケット編）
http://itpro.nikkeibp.co.jp/article/COLUMN/20071031/285990/

まつもと直伝　プログラミングのオキテ 第17回　ネットワーク・プログラミング（プロトコル編）
http://itpro.nikkeibp.co.jp/article/COLUMN/20080125/292023/
p3 に「Webに用いられるHTTP」

## (4)もう少し高機能なChrome Web Server

お手軽なWebサーバーの立て方
http://qiita.com/massie_g/items/2913066e596dae197539

https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=ja

・こちらは自分でWebコンテンツを自由に作成できます。
・ただしなぜかcurlアクセスでエラー18が発生し、コンテンツが転送されなかったので（ブラウザ表示はOK）、今回のcurlアクセスは対象外としました。

Enjoy! :tada: