Skip to content

Latest commit

 

History

History
671 lines (481 loc) · 18.7 KB

File metadata and controls

671 lines (481 loc) · 18.7 KB
marp true
paginate true
size 58140
<style> /* 3色は「クライアント・サーバー・データ」専用。場所を囲む枠は黒 */ :root { --ink: #1c2126; --sub: #5c6570; --line: #cdcac1; --paper: #ffffff; --view: #17558f; --logic: #b8501e; --store: #2c6b4f; } section { color-scheme: light; font-family: "Hiragino Kaku Gothic ProN", "Noto Sans JP", "Yu Gothic UI", "Meiryo", sans-serif; background: var(--paper); color: var(--ink); padding: 40px 56px; /* 40px は本文の下限。守れないなら文字数を削る */ font-size: 40px; line-height: 1.5; display: flex; flex-direction: column; justify-content: center; } section > * { flex-shrink: 0; } section h1 { font-size: 60px; font-weight: 700; margin: 0 0 26px; letter-spacing: -.01em; color: var(--ink); } section h2 { font-size: 50px; font-weight: 700; margin: 0 0 24px; color: var(--ink); padding-bottom: 14px; border-bottom: 2px solid var(--line); } section h3 { font-size: 40px; font-weight: 700; margin: 0 0 12px; color: var(--sub); } section a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; } section ul, section ol { margin: 0; } section > p { margin: 0; } section li { margin-bottom: 16px; } section li::marker { color: var(--sub); } strong { font-weight: 700; } .view { color: var(--view); } .logic { color: var(--logic); } .store { color: var(--store); } .big { font-size: 62px; font-weight: 700; line-height: 1.45; text-align: center; } .sub { color: var(--sub); font-size: 40px; } .note { border-top: 2px solid var(--ink); margin-top: 24px; padding-top: 14px; font-size: 40px; line-height: 1.5; color: #414851; } .lead { font-size: 54px; font-weight: 700; line-height: 1.45; } .point { border: 3px solid var(--ink); padding: 30px 32px; font-size: 54px; font-weight: 700; line-height: 1.45; } .cols { display: flex; gap: 22px; align-items: stretch; margin: 6px 0; } .col { flex: 1; min-width: 0; } .box { border: 2px solid var(--line); padding: 24px 22px; font-size: 40px; line-height: 1.5; } .box .label { font-size: 44px; font-weight: 700; display: block; margin-bottom: 10px; } .box.b-view { border-color: var(--view); } .box.b-view .label { color: var(--view); } .box.b-logic { border-color: var(--logic); } .box.b-logic .label { color: var(--logic); } .box.b-store { border-color: var(--store); } .box.b-store .label { color: var(--store); } .box.mute { border-color: var(--line); background: #f2f1ed; } .box.mute .label { color: var(--sub); } /* 項目が長い箱を詰めて表示する(40px を守れないときだけ) */ .box.tight { font-size: 30px; line-height: 1.4; padding: 18px 18px; } .box.tight .label { font-size: 34px; margin-bottom: 8px; } /* 手順など項目が多いスライド用。40px を守れないときだけ使う */ .small { font-size: 32px; line-height: 1.45; } .small li { margin-bottom: 10px; } .small .note { font-size: 32px; } .small table { font-size: 32px; } .small th, .small td { padding: .28em .5em; } .recap4 { display: flex; gap: 18px; margin-top: 44px; } .recap4 .item { flex: 1; min-width: 0; } .recap4 img { display: block; width: 100%; height: auto; margin: 0; border: 1px solid var(--line); background: #ffffff; } .recap4 .cap { font-size: 34px; text-align: center; color: var(--sub); margin-top: 10px; } /* default テーマの table 指定(display:block / max-content / 縞模様)を打ち消す */ .tablewrap { width: 100%; } section table { display: table; font-size: 40px; border-collapse: collapse; width: 100%; table-layout: fixed; margin: 0; } section table tr, section table tr:nth-child(2n) { background-color: transparent; border-top: none; } section th, section td { border: 1px solid var(--line); padding: .35em .5em; text-align: left; overflow-wrap: break-word; } section th { background: #f2f1ed; font-weight: 700; } section tbody th { background: #f7f6f3; font-weight: 400; } .c-view { color: var(--view); font-weight: 700; } .c-logic { color: var(--logic); font-weight: 700; } .c-store { color: var(--store); font-weight: 700; } section.title { border-top: 10px solid var(--ink); justify-content: center; } section.title h1 { font-size: 60px; margin-bottom: 0; } section.title h1 + p { margin-top: 20px; } section.chapter { justify-content: center; } section.chapter h1 { font-size: 54px; margin: 0; } section.chapter .sub { margin-top: 22px; } section.chapter .num { color: var(--sub); font-size: 28px; font-weight: 700; letter-spacing: .24em; margin-bottom: 16px; font-family: ui-monospace, "SF Mono", monospace; } section.pic { padding: 36px; justify-content: center; align-items: center; } section.pic h3 { color: var(--ink); font-size: 40px; margin: 0 0 20px; text-align: center; } img { background: #ffffff; display: block; margin: 0 auto; max-width: 100%; } /* Marp は本文の絵文字を

に置き換える。上の img 指定で block になるのを戻す */ img.emoji { display: inline; margin: 0; background: none; height: 1em; width: auto; vertical-align: -0.15em; } section.pic img { max-height: 470px; border: 1px solid var(--line); } section.title footer, section.chapter footer { display: none; } section::after { color: var(--sub); font-size: 16px; } </style>

サーバとの通信

ウェブ実装で必要になる通信の知識


この資料の目標

Webアプリを支えるサーバとの通信の
しくみを、ざっくりつかむ!

この資料で扱うこと

  1. HTTP とは
  2. URL の構成
  3. HTTPメソッド(GET / POST)
  4. HTTP の中身(ヘッダ)
  5. CORS とは

CHAPTER 1

HTTPとは


HTTP は、Webでよく使われる
通信のルール(プロトコル)
HTTP = Hypertext Transfer Protocol

HTTPとは

もとはブラウザ⇄サーバ間の通信用。WebAPIの呼び出しなどにも使われる。

いまの主流は HTTPS

HTTPS は、HTTPの通信を暗号化したもの。盗み見や改ざんを防ぐ。

SSL と TLS

  • SSL:古い暗号化の規格(いまは使われない)
  • TLS:SSL の後継。実際に使われているのはこちら
  • 慣習で、TLS のことを「SSL」と呼ぶことも多い
つまり HTTPS = HTTP を TLS で暗号化したもの。
この資料は HTTP を前提に解説。詳しくは HTTPS / SSL / TLS で調べてみよう。

HTTPは「ステートレス」

通信は1回ごとに独立していて、
前回の続きとしては扱われない
ステート(状態)+ レス(ない)。
サーバーは前の通信を覚えていない。たとえば「ログイン成功」も保持しない。

でも「セッションレス」ではない

通信にセッション情報を乗せるので、
ログイン状態は保てる
だから HTTP は ステートレスだが、セッションレスではない。

CHAPTER 2

URLの構成


URL は、インターネット上の
リソースへのあて先
URL = Uniform Resource Locator

URL と URI

URI はリソースを識別する仕組みの総称。URL はその一種で、実務ではほぼ URL を使う。

URLの構成


オリジン

スキーム・ドメイン・ポートの3つをまとめて オリジン と呼ぶ。

オーソリティ

// の後ろ、パスの前までの部分。ホストの前に認証用のユーザー情報を含めることもある。
オリジンとは違い、スキームを含まず・ユーザー情報を含む。

CHAPTER 3

HTTPメソッド


メソッド = 通信のアクション

仕様上のメソッド GET / POST / PUT / DELETE など
今回は、よく使う GET と POST の2つを見る。

GET と POST


GET とは

  • サーバからデータを取得する
  • クエリパラメータを URL に含められる
  • URLは人の目に触れやすい → 個人情報は送らない
HTTPメソッドとしてべき等・安全。
ここでの「安全」は、サーバ側へ更新を要求しないという意味。

POST とは

  • サーバのデータを更新する
  • データは body に含めて送る(=ペイロード)
  • URLには出ないが、暗号化はしない
HTTPメソッドとしてべき等でなく・安全でない。
個人情報を扱うなら HTTPS で通信ごと暗号化する。

TIPS:べき等とは

同じリクエストを何回処理しても、
サーバのデータが同じ状態になること
ここまではメソッドの定義の話。
GET/POSTを使ったAPIのべき等性・安全性は、サーバ/クライアントの実装しだい。

実際にやってみる(GET)

  1. 新しいタブで開発者ツールを開く(githubログイン中ならシークレットウィンドウ)
  2. Network タブを開いて github.com にアクセス
  3. 一覧の github.com の行がメソッド GET になっているか確認
  4. リロードやロゴのクリックで内容が変わらないことを確認(べき等)
  5. 検索窓に jigintern など入れて検索
  6. search を探し、GET で呼ばれ、Request URL に入力文字列が含まれることを確認
  7. 同じ文字列なら何度でも同じ結果になることを確認

Network タブで確認する

height:470


実際にやってみる(POST)

  1. github にログインする
  2. 一覧から session を探し、POST で呼ばれていることを確認
  3. URLにはパスワードが入っていないのに、Payload タブを開くとパスワードが入っていることを確認

まとめ(HTTPメソッド)

  • GET:クエリで送る/人に見える情報だけ/べき等な処理に
  • POST:body で送る/秘密の情報に/更新する処理に(暗号化はしない)
メソッドは動作や性質が定義されているだけ。
定義どおりに動くよう、サーバ側が実装する必要がある。

CHAPTER 4

HTTPの中身


リクエストとレスポンスの構成


主なリクエストヘッダ

ヘッダ 役割
user-agent ブラウザ・OS の種類
cookie サーバから預かった情報(セッションなど)
host 接続先のホスト名
accept 受け取れるデータ形式
accept-language 受け取れる言語
accept-encoding 受け取れる圧縮形式

主なレスポンスヘッダ

ヘッダ 役割
content-type 本文のデータ形式
Content-Encoding 本文の圧縮形式
set-cookie ブラウザに保存させる情報
connection 接続の扱い方
server サーバのソフトウェア名
ヘッダは基本 ブラウザが自動で付与。慣れるまで自作・付与はしなくてよい。

実際に見てみる

GETの中身

  • ログイン済みの github.com を開く(リロード)
  • Nameが github.com の行をクリック
  • リクエスト/レスポンスヘッダ、レスポンスボディを確認

POSTの中身

  • github にログイン(済みなら一度サインアウト → 再ログイン)
  • Nameが session の行をクリック
  • ヘッダやペイロードを確認

まとめ(HTTPの中身)

  • リクエストもレスポンスも、本体以外の情報をたくさん持つ
  • ヘッダから通信の情報を得られる
  • ヘッダは任意に足せるが、基本はやらなくてよい

CHAPTER 5

CORSとは


CORS は、オリジンをまたいで
データをやり取りするしくみ
CORS = Cross-Origin Resource Sharing

同一オリジンポリシー

CSRF や XSS といった攻撃を防ぐため、異なるオリジン間の送受信は標準でブロックされる。

なぜ CORS が必要?

HTML/JS を取ってくるオリジンと、
叩くAPIのオリジンが違うことがある
そこで、安全と認められたオリジン間だけ、またいで通信できるようにしたのが CORS。

この教材でのしくみ

8000 のページから、その JS が 3000 の API を呼ぶ。ポートが違う=別オリジンなので CORS が必要。

CORSリクエスト

リクエストに origin、レスポンスに Access-Control-Allow-Origin を付け、両者が一致すれば受け取れる。

プリフライトを起こさない条件(単純リクエスト)

メソッド GET / HEAD / POST
ヘッダ Accept / Accept-Language / Content-Language / Content-Type / Range
Content-Type x-www-form-urlencoded / multipart/form-data / text/plain
加えて、アップロード監視のイベントリスナーや ReadableStream を使っていないこと。

実際に見てみる(単純リクエスト)

  1. /transfer-protocol に移動
  2. deno run server.js を実行(サーバは 3000番)
  3. 別ターミナルで deno run client.js を実行(クライアントは 8000番)
  4. http://localhost:8000 を開き、開発者ツールを開く
  5. try cors ボタン → Network / Console を確認(エラー)
  6. try cors (simple request) ボタン → 正常に受け取れることを確認
/cors はヘッダなし、/cors-additional-header は Access-Control-Allow-Origin: * を付けて返している。

プリフライトリクエスト

条件を満たせない(主にユーザのデータに影響する)通信では、先に OPTION で安全性を確認してから本リクエストを送る。

実際に見てみる(プリフライト)

  1. /transfer-protocol に移動
  2. deno run server.js を実行
  3. 別ターミナルで deno run client.js を実行
  4. http://localhost:8000 を開き、開発者ツールを開く
  5. try cors (prefright request) ボタン → Network / Console を確認
POST で Content-Type: application/json を持つため単純リクエストにならず、先にプリフライトで必要な許可を確認している。

まとめ(CORS)

  • オリジンをまたぐアクセスを許すなら CORSの設定を行う
  • 条件を満たせないと プリフライト(安全確認の通信)が起きる
  • 外部のWebAPI を呼ぶときは CORS の設定が必要になることがある

FINALE

実装で意識すること


まとめ


実装のときは

  • メソッドは、更新・個人情報なら POST、取得だけなら GET
  • サーバ側は、原則そのメソッドの仕様を守って実装する
  • ヘッダは基本ノータッチ。ブラウザ任せでよい
自作サーバは別オリジンから叩かれないので、サーバ側のCORSはあまり気にしなくてよい。
クライアントで外部APIを叩くときは、fetch の mode を cors にすればおおむね動く。

おわりに

もっと深く知りたい人は、参考文献で自学してみよう ◎


参考文献