Rubyのサーバー構築(WEBrickってなんぞ？)

## この記事について
この記事はRubyでWEBアプリ開発をするにあたり、Rails等のフルスタックフレームワークを使用しないでサーバーを立てることを目的としています。
自分自身、フレームワークを使用しないでサーバーを建てたことがない為、その学習の意味も込めて記事を作成しています。
間違いがありましたらご指摘いただけると幸いです。
## WEBrickとは？
汎用HTTPサーバーフレームワークです。HTTPサーバが簡単に作れます。

WEBrick はサーブレットによって機能します。サーブレットとはサーバの機能をオブジェクト化したものです。ファイルを読み込んで返す・forkしてスクリプトを実行する・テンプレートを適用するなど、「サーバが行なっている様々なこと」を抽象化しオブジェクトにしたものがサーブレットです。サーブレットは WEBrick::HTTPServlet::AbstractServlet のサブクラスのインスタンスとして実装されます。
[参照元　Rubyリファレンスマニュアル　library webrick](https://docs.ruby-lang.org/ja/latest/library/webrick.html)

**はてさて？何を言っているんだ？？**
## そもそもサーバって？
### サーバ??
- サービスや機能を提供する側、主に性能面で調整されたコンピュータのこと
### HTTPサーバ??
- コンピュータ（サーバ）の分類のひとつ
- Webサービスを使いたい人にWebサービスを提供してあげたりするお仕事をしているコンピュータのこと

**つまりWEBrickとは、RubyでHTTPサーバを建てるためのソフトウェアということらしい**

## WEBrickを使う前の予備知識

### テキストデータの形式
- JSON
「JavaScript Object Notation（JSON）」は、データのやり取りに使われる軽量なデータ形式のこと
    JSONはRubyで言うところのハッシュを同じような形を持ったデータ
    ``` sample.json
    {
  "user_info": {
    "user_id": "A1234567",
    "user_name": "Yamada Taro"
      }
    }
    ```
    このように`{}`と`:`で構成されるデータ
    Rubyではjsonライブラリを使ってJSONを扱うことができる。
    [詳しくはこちらを参照　とほほのWWW JSON入門](https://www.tohoho-web.com/ex/json.html)
　　
- XML
Extensible Markup Language（XML）もデータの表現に使われる形式の一つ
JSONと同様にデータの構造化に利用される。
最近では主流のデータ構造ではないので説明は省略します。

### ネットワーク
- **HTTPプロトコル**
「HTTP」は「HyperText Transfer Protocol」の略
サーバ同士が通信を行う上での決まりごと
クライアントから送られてきたものを「HTTPリクエスト」
バックエンドから送るものを「HTTPレスポンス」と言う。
[HTTPプロトコルとは](https://wa3.i-3-i.info/word110469.html)
　　
- **HTTPリクエストメソッドの種類**
クライアントからのリクエストには複数の種類があります。
これにはGET,POST,DELETEなど種類があり、内容によって処理を変えます。
以下のものが代表的なメソッドです。
    - GET
    用途: リソースの取得。クエリパラメータを使用してデータを送信できます。
    例: ウェブページの読み込み、画像の取得など。
    - POST
    用途: サーバーにデータを送信して新しいリソースを作成。
    例: フォームデータやJSONデータを送信して新しい記事を作成。
    - PUT
    用途: サーバー上の既存のリソースを完全に更新。
    例: データの完全な更新が必要な場合に使用。例えば、記事全体を新しい内容で置き換える。
    - DELETE
    用途: サーバー上のリソースを削除。
    例: 特定のリソースを削除する。例えば、記事の削除。
    - PATCH
    用途: サーバー上のリソースの一部分を更新。
    例: データの一部分だけを更新する。例えば、記事の一部分だけを修正。
  
    用途は以下のページを参照して下さい。
    [HTTP リクエストメソッドとは](https://developer.mozilla.org/ja/docs/Web/HTTP/Methods)
　　
- **ポート**
ネットワーク上で通信するために窓口のこと
例えば、標準的なHTTPのポートは80番、HTTPSのポートは443番が使用される。
例:[http://localhost:3000←この場合は3000番が使用されている]
[ポートとは](https://wa3.i-3-i.info/word1774.html)
　　
- **ルーティング&エンドポイント**
リクエストがどこに飛んできたらどういった処理をして返すかの「URL」を設定するところ
例:[http://localhost:3000/"ここから下の部分!!"]
ルーティングとは、クライアントからのリクエストがどのエンドポイント（URL）に飛んできたかを指定すること
エンドポイントとは、リクエストを処理するための具体的な場所や機能
　　
- **レスポンスステータス**
HTTPレスポンスコードは、サーバーがクライアント(フロント側)に対して返す状態を示す3桁の数字のこと。
使用されるコードと意味は以下の通り
    - 100番台「情報」
    - 200番台「成功」
    - 300番台「リダイレクト」
    - 400番台「クライアントエラー」
    - 500番台「サーバエラー」
[JavaScript MDN レスポンスステータス一覧](https://developer.mozilla.org/ja/docs/Web/HTTP/Status)
  
### サーブレット
リクエストに対する処理を担当するオブジェクトのこと

## 結局のところ、WEBrickでRubyサーバを立てて何をしてもらうの？
フロントエンド、ブラウザなど(以下**クライアント**と言う）からのリクエストを受け取り、適切に応答をしてもらうよ！

- **リクエストの受信:**
    クライアントから送信されるリクエストを待ち受ける。
    HTTPプロトコル（GET、POST、PUT、DELETEなど）　　
　　
- **リクエストに応じた処理:**
    クライアントからのリクエストに基づいて、サーバーは対応する処理を行う。
    例えばデータベースからデータを取得したり、計算を行ったり、他のサービスとの通信を行ったりする。
　　
- **データの送信:**
    処理が出来たデータをクライアントに送信する。
    ここで送信するデータとはJSONやHTML、画像などのこと。
　　
- **ルーティング:**
   クライアントからのリクエストに対して、適切なエンドポイントやルートにマッチするようにサーバーを設定する。
   特定のURLに対してどのRubyファイルや処理を呼び出すかを決める。

## WEBrickの使い方
###  WEBrickのインストール
- Rubyが使える環境にて`gen install webrick`を実行しインストールする。

### 書き方

```my_server.rb
require 'webrick' # インストールしたWEBrickを呼び出す

# サーバーの設定
server_config = {
  Port: 8000, # サーバーのポート番号
  DocumentRoot: File.expand_path('./public'), # ドキュメントのルートディレクトリ
}

# WEBrickのHTTPサーバーを作成
server = WEBrick::HTTPServer.new(server_config)

# Ctrl+Cでサーバーを停止するためのシグナルハンドラを設定
trap('INT') { server.shutdown }

# サーバーを起動
server.start
```
- WEBrickの呼び出し
```my_server.rb
require 'webrick'
```
    
- ポート番号の設定
```my_server.rb
server_config = {
  Port: 8000, # サーバーのポート番号
  DocumentRoot: File.expand_path('./public'), # ドキュメントのルートディレクトリ
}
```

- サーバー生成とシャットダウンの設定
```my_server.rb
# WEBrickのHTTPサーバーを作成
server = WEBrick::HTTPServer.new(server_config)

# Ctrl+Cでサーバーを停止するためのシグナルハンドラを設定　ここを忘れると停止できなくなる
trap('INT') { server.shutdown }

# サーバーを起動
server.start
```

### コンテンツタイプ設定
WEBrickでは送信するデータの形式を設定する必要がある
- 書き方
```contenttype.rb
response['Content-Type'] = 'application/json' # JSONデータを送信する場合
response['Content-Type'] = 'text/html' # HTMLデータを送信する場合
response['Content-Type'] = 'text/plain' # TEXTを送信する場合
```
クライアント側でどの形式か理解してもらうために、いずれかをサーブレット内に記述する必要がある。
また、RubyにはJSONモジュールが用意されているので、使用する場合は`require 'json'`を記述しRubyでJSONを使えるようにしておく。

### ルートの追加
アプリを作る場合、リクエストが複数あるのでそれに対応したエンドポイントを用意する必要がある。
```webrick.rb
class MyServlet < WEBrick::HTTPServlet::AbstractServlet
  def do_POST(request, response)
    response.status = 200
    response['Content-Type'] = 'application/json'

    post_data = JSON.parse(request.body)

    # ここで受け取ったデータを処理し、必要に応じてJSONデータを返す
    response.body = { result: 'success' }.to_json
  end
end

server.mount('/path/to/your/endpoint', MyServlet) # ルートの設定
```
こういった形のクラスを追加していき、エンドポイントを増やしていく。

最終的にはこう言った記述になる。

```webrick.rb
require 'webrick'
require 'json'

# サーバーの設定
server = WEBrick::HTTPServer.new(Port: 8000)

# サーブレットを作成
class MyServlet < WEBrick::HTTPServlet::AbstractServlet
  def do_POST(request, response)
    response.status = 200
    response['Content-Type'] = 'application/json'

    post_data = JSON.parse(request.body)

    # ここで受け取ったデータを処理する
    response.body = post_data.to_json
  end
end

# 新しいサーブレットを作成
class AnotherServlet < WEBrick::HTTPServlet::AbstractServlet
  def do_GET(request, response)
    response.status = 200
    response['Content-Type'] = 'text/plain'

    response.body = 'Hello from another endpoint!'
  end
end

# 既存のエンドポイントにサーブレットをマウント
server.mount('/path/to/your/endpoint', MyServlet)

# 新しいエンドポイントにサーブレットをマウント
server.mount('/another/endpoint', AnotherServlet)

# Ctrl+Cでサーバーを停止するためのシグナルハンドラを設定
trap('INT') { server.shutdown }

# サーバーを起動
server.start

```

### サーブレット内のメソッドについて
クラス内にdo_POSTやdo_GETと言ったメソッドを記述していますが、これはルーティングに対応したHTTPリクエストメソッドになります。
同じURLでもメソッドが違えば処理も違います。
## 所感
今回はWEBrickを中心に、簡易的なアプリを作成する際に必要なものをまとめてみました。
アプレンティスシップでチーム開発をするにあったって、ドキュメントにまとめるならと
記事にしてみましたが、かなり勉強になりました。
フレームワークでサーバを立ち上げていたので、曖昧な部分が多くあり、まだまだ勉強しなきゃですね。。。
正直、この内容だけだと不足分があると思うので、同様にフロント側からの視点でまた書いてみたいと思います。