net/httpライブラリを使って、RubyでHTTP通信してみた

# RubyでHTTP通信する
RubyでHTTP通信を操作する方法はいろいろあるようだが、
今回は、net/httpのライブラリを使用。APIを叩いてみる。

## 目次
1. resposeを標準出力で見る
    1. ヘッダーの情報を取得する
    2. ボディの情報を取得する
2. requestを標準出力でみる
    1. ヘッダーの情報をgetで取得する
    2. ヘッダーの情報をpostで取得する
    3. ボディの情報をgetで取得する
    4. ボディの情報をpostで取得する
3. QiitaのAPIを叩く、自分の記事一覧を表示させる
4. まとめ
    1. クエリストリング（クエリ文字列）とは
    2. TCPとHTTPの違い

## 1. responseを標準出力で見る
### ヘッダーの情報を取得する

- net/httpというRubyの標準ライブラリを読み込む
    - クライアントとサーバー間で情報をやり取りするプロトコルであるHTTPを扱うライブラリ
- Net::HTTP クラスは、低レベルのHTTPクライアント
- http://www.example.com のドメインは、ドキュメントの実例で使用するためのもの。事前の調整や許可を求めることなく、このドメインを文献で使用することができる
- get_responseは、指定した対象にGETリクエストを送り、そのレスポンスをNet::HTTPResponse(HTTPレスポンスを表現するクラス)として返すメソッド
- parseは、一定の書式や文法に従って記述されたデータを解析し、プログラムで扱えるようなデータ構造の集合体に変換すること

```ruby
require 'net/http'    # net/httpライブラリを読み込む

uri = "http://www.example.com/index.html"
response = Net::HTTP.get_response(URI.parse(uri))
p response.header
```
[class Net::HTTPResponse](https://docs.ruby-lang.org/ja/latest/class/Net=3a=3aHTTPResponse.html#I_HEADER)

- ターミナルで上記のファイルを実行

```console
$ ruby <ファイル名>
```
- ステータスコードとその説明が帰ってくる

```console
#<Net::HTTPOK 200 OK readbody=true>
```


### ボディの情報を取得する

- get.print は、HTTPでボディを取得し、出力するメソッド
   - 引数には uri と paramsを指定
   - uri（Uniform Resource Identifier）は、インターネット上のデータやサービス、機器などの所在情報を識別する書き方のルールの総称で、URLは、URIで定められたルールに従って書かれたり使われたりする
   - paramsは、ソフトウェアやシステムの挙動に影響を与える、外部から投入されるデータのこと

```ruby
require 'net/http'    # net/httpライブラリを読み込む
Net::HTTP.get_print 'www.example.com', '/index.html'
```

- ターミナルで上記のファイルを実行

```console
$ ruby <ファイル名>
```
- HTTPのボディの情報が平文で返ってくる

```html

<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>
</head>

<body>
    <div>
        <h1>Example Domain</h1>
        <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
        <p><a href="https://www.iana.org/domains/example">More information...</a></p>
    </div>
</body>
</html>
```

## 2. requestを標準出力で見る
### ヘッダーの情報をgetで取得する
- Net::HTTP::Getは、HTTPのGETリクエストを表すクラス

```ruby
require 'net/http'    # net/httpライブラリを読み込む
http = Net::HTTP.new('www.example.com', 80)
req = Net::HTTP::Get.new('/somefile')
res = http.request(req)
print res.header
```
- Rubyの実行結果

```console
#<Net::HTTPNotFound:0x00007fe6a3095740>
```

### ヘッダーの情報をpostで取得する
- Net::HTTP::Postは、HTTPのPOSTリクエストを表すクラス

```ruby
require 'net/http'
http = Net::HTTP.new('www.example.com', 80)
req = Net::HTTP::Post.new('/somefile')
res = http.request(req)
print res.header
```

- Rubyの実行結果

```console
#<Net::HTTPNotFound:0x00007f8063871e10>
```

### ボディの情報をgetで取得する
```ruby
require 'net/http'    # net/httpライブラリを読み込む
http = Net::HTTP.new('www.example.com', 80)
req = Net::HTTP::Get.new('/somefile')
res = http.request(req)
print res.body
```
参照 [class Net::HTTPRequest](https://docs.ruby-lang.org/ja/latest/class/Net=3a=3aHTTPRequest.html)

- Rubyの実行結果

```console
<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
```
### ボディの情報をpostで取得する

```ruby

require 'net/http'
http = Net::HTTP.new('www.example.com', 80)
req = Net::HTTP::Post.new('/somefile')
res = http.request(req)
print res.body
```

- Rubyの実行結果

```console
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
	<head>
		<title>404 - Not Found</title>
	</head>
	<body>
		<h1>404 - Not Found</h1>
		<script type="text/javascript" src="//wpc.75674.betacdn.net/0075674/www/ec_tpm_bcon.js"></script>
	</body>
</html>
```

# 3. RubyでHTTPS通信もしてみる
- Qiitaの記事一覧のAPIを叩く

a. uri変数の値に何が入っているかみてみる

```ruby
require 'net/https'
require 'uri'

path = 'https://qiita.com/api/v2/items'
uri = URI.parse(path)

p uri
```
- Rubyの実行結果

```console
#<URI::HTTPS https://qiita.com/api/v2/items>    #QiitaのURI
```
b. http変数の値に何が入っているかみてみる

```ruby
require 'net/https'
require 'uri'

path = 'https://qiita.com/api/v2/items'
uri = URI.parse(path)
http = Net::HTTP.new(uri.host, uri.port)

p http
```
- Rubyの実行結果

```console
#<Net::HTTP qiita.com:443 open=false>    #443はポート番号
```
c. req変数の値に何が入っているかみてみる

```ruby
require 'net/https'
require 'uri'

path = 'https://qiita.com/api/v2/items'
uri = URI.parse(path)
http = Net::HTTP.new(uri.host, uri.port)

http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

req = Net::HTTP::Get.new(uri.request_uri)

p req
```
- Rubyの実行結果

```console
#<Net::HTTP::Get GET>    # ヘッダーデータとボディデータを取得して表示するだけなのでGET
```
d. res変数の値に何が入っているかみてみる

```ruby
require 'net/https'
require 'uri'

path = 'https://qiita.com/api/v2/items'

uri = URI.parse(path)
http = Net::HTTP.new(uri.host, uri.port)

http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

req = Net::HTTP::Get.new(uri.request_uri)

res = http.request(req)
puts res.code, res.msg
puts res.body

p res
```
- Rubyの実行結果

```console
#<Net::HTTPOK 200 OK readbody=true>    #レスポンスが成功  HTTPボディの内容が正しい
```

## まとめ
### GETリクエストとPOSTリクエストの違い
- GET
    - サーバから情報を取得する時に用いる
    - データの送信方法
        - リクエスト時にサーバへ送信するデータはURLの後に付け加えられる
        - 付け加えられるデータはクエリストリングで表される
        - クエリストリング（クエリ文字列）とは
Webページ間で手軽に値を受渡しできる方法で、サーバーに情報を送るためにURLの末尾につけ足す「?」以下の文字列のこと。URLパラメーター（値）。
            - 基本的なURL : https://xxx.jp/
            - 基本のURL + クエリストリング : https://xxx.jp/?●=▲×■&○=△×□
- POST
    - サーバへ情報を登録する時に用いる
    - データの送信方法
        - リクエストボディにデータが記述される

### TCPとHTTPの違い
TCPとは、 Transmission Control Protocolの略で、インターネットなどのネットワークで、IPの一段階上位層のプロトコルとして標準的に使われるものの一つである。
TCPもHTTPも同じプロトコルであるが、レイヤー（ネットワーク通信を行う際に必要な役割を分類したネットワーク通信の型のようなもの）が違う。TCPとIPは別のレイヤーだが、TCPを使うときにIPを使うので、TCP/IPという表現でよく使われる。

- HTTP → セッション層～アプリケーション層
- TCP → トランスポート層
- IP → ネットワーク層

| レイヤー                  | 役割                                          |
|:-----------------------:|:--------------------------------------------:|
| アプリケーション層           | システムやサービスに必要な機能を実装するための層        |
| プレゼンテーション層         | アプリケーション層から受け取ったデータを適切な形式のデータに変換し、セッション層へ渡す |
| セッション層               | 通信の中断や再開、通信の流れを管理する               |
| トランスポート層            | データの送信元と送信先の間での制御や通知、交渉などを担う |
| ネットワーク層              | データのやり取りをする機器同士が通信を行う             |

## 参照
- [Ruby 2.6.0 リファレンスマニュアル](https://docs.ruby-lang.org/ja/latest/class/Net=3a=3aHTTP.html)
- [Qiita API で公開情報の記事一覧を取得する、アクセストークンなどの認証必要なしのスクリプト例](https://qiita.com/YumaInaura/items/8004559925f40059abce)
- [HTTPとPOSTとGET](https://qiita.com/Sekky0905/items/dff3d0da059d6f5bfabf)