Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 3 years have passed since last update.

curl, Postman, ブラウザを使ってHTTPを理解する

Last updated at Posted at 2020-09-19

この記事で理解してもらいたいこと

Web(ブラウザ)は単なるインタフェースに過ぎないよという話。
WebはHTTPリクエストに簡単に送るためのツール、HTTPレスポンスをわかりやすく表示するためのツールといっても過言ではありません。

以下3つを使って説明していきます。

  1. curl
  2. Postman
  3. ブラウザ

事前準備

Railsのアプリを作っておく。scaffoldでOK。

$ rails new curl_example
$ rails g scaffold article title:string content:text
$ rails db:migrate
$ rails s
=> Booting Puma
=> Rails 6.0.3.3 application starting in development 
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.6 (ruby 2.6.6-p146), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop

application_controller
class ApplicationController < ActionController::Base
  # 今回の検証をしやすくするためこの一行追加
  # 実務では安易に追加してはいけない。詳細はCSRFでググってください。
  protect_from_forgery with: :null_session
end

curl

GET(記事一覧取得)

$ curl http://localhost:3000/articles
<!DOCTYPE html>
<html>
  <head>
    <title>CurlExample</title>
    <meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="QM6SZATnSEC1vD1WJJZM1mzLLWkSZLKsGqj60vWLMxYWomphdmHIEj+Bc5LDUiHzMGRj/AKqGN9rDqgJQ5aPjA==" />
    

    <link rel="stylesheet" media="all" href="/assets/application.debug-4024757a3d614102a20eedb0b76535ad941829836b18b0e2347eeede95da3921.css" data-turbolinks-track="reload" />
    <script src="/packs/js/application-9afcbb5693aa87623e69.js" data-turbolinks-track="reload"></script>
  </head>

  <body>
    <p id="notice"></p>

<h1>Articles</h1>

<table>
  <thead>
    <tr>
      <th>Title</th>
      <th>Content</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
  </tbody>
</table>

<br>

<a href="/articles/new">New Article</a>

  </body>
</html>

→ 〜〜〜って見覚えないですか?HTMLですよね。よく見ると一覧画面のHTMLのテキストですね。

POST(記事新規作成)

$ curl -X POST -F 'article[title]=hoge' -F 'article[content]=fuga' http://localhost:3000/articles

<html><body>You are being <a href="http://localhost:3000/articles/1">redirected</a>.</body></html>

→ このレスポンスは気にしなくてOKです。リダイレクトなので。

Image from Gyazo

→ 新規作成できてる。入力フォームとかないのに新規作成できてる。よくわからないコマンド打っただけでなんか新規作成できてる。→ これがHTTPリクエストです。

余談ですがこれでも新規作成できる

$ curl -X POST -d 'article[title]=hoge&article[content]=fuga' http://localhost:3000/articles

Postman

GET(記事一覧取得)

Image from Gyazo

POST(記事新規作成)

Image from Gyazo

ブラウザ

GET(記事一覧取得)

http://localhost:3000/articles にアクセス

Image from Gyazo

→ 当然こんな画面が表示される。
開発者ツールのnetworkタブの該当のリクエストの中身を見るとRequest URLにhttp://localhost:3000/articlesが設定されてる

Image from Gyazo

→ responseタブを見ると一覧画面のHTMLのテキストがずらーっと見える。curlでもpostmanでも見えてたやつ。ブラウザは一見わかりづらいこのテキストをユーザーにとってみやすく画面を構築してくれる便利ツール。

POST(記事新規作成)

Image from Gyazo

Image from Gyazo

→ Request URLとFormDataのところがミソ。
Request URLには http://localhost:3000/articles が設定されている
FormDataには
article[title]という名前にi am formという値が紐づけられている
article[content]という名前に`hello formという値が紐づけられている

curlやPostmanでも同じことをしましたね。

余談

Request URLってどこでどう設定されるのか?
article[title]とかarticle[content]ってどこでどう設定されるのか?

Image from Gyazo

→ RequestURLはformのaction属性に指定したものです。FormDataの名前はinput要素やtextareaのname属性に指定したものです。form_withを使うとその辺をいい感じに設定した状態でHTMLを吐いてくれます。

まとめ

世の中のシステムはだいたい

  • どこに(エンドポイント e.g. http://localhost:3000/articles)
  • どんなデータを(e.g. article[title]=hoge)
  • どんな方法で(HTTPメソッド e.g. POST)

で成り立っている。

curlだろうがPostmanだろうがHTTPリクエストを送れればツールはなんだって良い。
ただ、一般ユーザーにとってcurlやPostmanを使ってもらうわけにはいかない。なのでブラウザという誰にとってもわかりやすいインタフェースを作ってあげる必要がある。Railsはそれがめちゃめちゃ作りやすいフレームワーク。

余談

HTTPレスポンスは大きく「ステータスライン」「レスポンスヘッダ」「レスポンスボディ」に分かれる。

Image from Gyazo

引用 HTTPレスポンスヘッダとは|「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典

curlに-iオプションをつけるとステータスラインとレスポンスヘッダ部分も確認できる。

$ curl -i http://localhost:3000/articles
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Content-Type: text/html; charset=utf-8
ETag: W/"c97efccfebc4d13dfc90d25f7e67ab78"
Cache-Control: max-age=0, private, must-revalidate
Set-Cookie: _curl_example_session=PhunKXciBkyLwuk9msnHqbk%2BwC9GGQKu96vEabdvZlemacHf%2FwboM746FBuA%2FtJMoQ068BqdenbMCXjS1K5mEMW0bphL7uYoqbLvbH43wed2c1vyG33SVrZDAhNKFy4aR8YTAoI9E%2F0FucI8SKhSujxNveG3Pvo2Lwuqm0rWqk1F8qXUkOYzufZmvIdKOC900sUjGSrTr402znqehJ00yluz0bYepyTi7RVblaDU54bt5I8WX4zg49PhwfiO4EptCgiHv2OlL9xnuhBmbqo2Qj4IfMi%2FRSgvVTJ7lPU%3D--KaQXqkIv8lYW4G54--Yq0oVArpQfhCMjX1eQx2uA%3D%3D; path=/; HttpOnly
X-Request-Id: 69a9c964-08fd-4b85-a557-6a5e9be5fed9
X-Runtime: 0.008425
Transfer-Encoding: chunked

<!DOCTYPE html>
<html>
  <head>
    <title>CurlExample</title>
    <meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="RJuaT2poSWU4BD4DDbW1Cak4zVdJN3dPqu6OQJh8Due7aVwSCPx8s+aP5jVAlaFMSrBhLKN8KuflSA2HbCujKg==" />
    

    <link rel="stylesheet" media="all" href="/assets/application.debug-4024757a3d614102a20eedb0b76535ad941829836b18b0e2347eeede95da3921.css" data-turbolinks-track="reload" />
    <script src="/packs/js/application-9afcbb5693aa87623e69.js" data-turbolinks-track="reload"></script>
  </head>

  <body>
    <p id="notice"></p>

<h1>Articles</h1>

<table>
  <thead>
    <tr>
      <th>Title</th>
      <th>Content</th>
      <th colspan="3"></th>
    </tr>
  </thead>

  <tbody>
      <tr>
        <td>hello</td>
        <td>world</td>
        <td><a href="/articles/8">Show</a></td>
        <td><a href="/articles/8/edit">Edit</a></td>
        <td><a data-confirm="Are you sure?" rel="nofollow" data-method="delete" href="/articles/8">Destroy</a></td>
      </tr>
  </tbody>
</table>

<br>

<a href="/articles/new">New Article</a>

  </body>
</html>

本質的にユーザーが求めているものは<html>~~~</html>の部分であり、それは「レスポンスボディ」に設定されて返ってくることがわかる。

次に試しにrender json: @articlesを追記してみる。

articles_controller.rb
class ArticlesController < ApplicationController
  def index
    @articles = Article.all
    render json: @articles # 追加
  end
end
$ curl -i http://localhost:3000/articles
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Permitted-Cross-Domain-Policies: none
Referrer-Policy: strict-origin-when-cross-origin
Content-Type: application/json; charset=utf-8
ETag: W/"c330b5c01cb4a59b3579b5d672195fc2"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: 2eee0398-5764-42ff-9d40-5df6988abd43
X-Runtime: 0.060005
Transfer-Encoding: chunked

[{"id":8,"title":"hello","content":"world","created_at":"2020-10-09T13:15:08.437Z","updated_at":"2020-10-10T00:31:59.271Z"}]

レスポンスボディにはJSON形式のものが設定されていることがわかる。

Railsなどのサーバの役割は究極的には何らかのレスポンスを返すにすぎない。
そのレスポンスはクライアントに応じて適切な形式で返す必要がある。従来のWebアプリであれは同期的にページを遷移していくのでまるっとHTMLの形式で返す必要があるだろうし、一方でSPAであれば非同期的に都度必要な情報を取得する形になるのでJSON形式で返す必要がある。

演習

  • curlコマンドで特定の記事を更新してください
  • curlコマンドで特定の記事を削除してください
  • postmanで特定の記事を更新してください
  • postmanで特定の記事を削除してください
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?