Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
はてなインターンシップ2024 HTTP, Web, API 講義資料
Search
Hatena
October 31, 2024
1.9k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
はてなインターンシップ2024 HTTP, Web, API 講義資料
Hatena
October 31, 2024
More Decks by Hatena
See All by Hatena
60分で学ぶクラウドとSRE・サービス運用 / GeekCAMPAcademia 2026-05
hatena
1
74
エンジニアリング マネージャーの育成と評価軸の考え方
hatena
0
600
Perlブートキャンプ
hatena
0
5k
はてなサマーインターンシップ2025 Web API 講義資料
hatena
0
1k
はてなサマーインターンシップ2025 フロントエンド 講義資料
hatena
21
11k
はてなサマーインターンシップ2025 コンテナ + Kubernetesハンズオン 講義資料
hatena
0
720
はてなサマーインターンシップ2025 クラウドと運用 講義資料
hatena
0
770
はてなサマーインターンシップ2025 RDBMSの基礎 講義資料
hatena
0
830
はてなサマーインターンシップ2025 セキュリティ 講義資料
hatena
0
760
Featured
See All Featured
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
Embracing the Ebb and Flow
colly
88
5.1k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.3k
Agile Actions for Facilitating Distributed Teams - ADO2019
mkilby
0
200
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
140
GitHub's CSS Performance
jonrohan
1033
470k
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
460
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
62
44k
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4k
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.2k
Abbi's Birthday
coloredviolet
2
8k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Transcript
HTTP, Web, API IBUFOBJOUFSO !
import OpenAI from "openai"; const client = new OpenAI(); async
function main() { const stream = await client.chat.completions.create({ model: "gpt-4", messages: [ { role: "user", content: "Πϯλʔωοτ࠷ߴʁ͍͔͍͍͑Ͱ͑ͯɻ" }, ], stream: true, }); for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content || ""); } } main(); IBUFOBJOUFSO !
͜ͷߨٛͰ • HTTP, Web • シンタックス • セマンティクス • ウェブの事情
• API • REST • GraphQL • gRPC IBUFOBJOUFSO !
Πϯλʔωοτ࠷ߴʂ ChatGPT: ͦΕ؆୯ʹʮ͍ʯ·ͨʮ͍͍͑ʯͰ͑ΒΕΔ࣭Ͱ͋Γ·ͤΜ͕ɺݸਓతͳҙݟΛड़Δͱʮ͍ʯͱ͑·͢ɻ Πϯλʔωοτใͷڞ༗ɺίϛϡχέʔγϣϯɺֶशɺΤϯλʔςΠϝϯτͳͲͷ໘Ͱඇৗʹ༗ӹͰ͢ɻ ͨͩ͠ɺϓϥΠόγʔηΩϡϦςΟͷϦεΫଘࡏ͠·͢ͷͰɺ͜ΕΒΛߟྀ͢Δ͜ͱॏཁͰ͢ɻ • インターネットはすごい • ブログを書いて、読んでもらうことができる •
マンガや⼩説を読むことができる。更新通知も受け取れる • なんならそれらを提供するサービスを監視することもできる • では、そのすごいインターネットはどんなふうに実現されている? IBUFOBJOUFSO !
ϓϩτίϧ • = 約束ごと • TCP/IP, HTTP, DNS, TLS, SMTP,
3 • インターネットの参加者はプロトコルに従っている • サーバ(Google やはてな) • クライアント(ブラウザ、スマートフォンアプリ) • ルータ、… • これらのプロトコルは RFC によって定義される • = Request for Comments IBUFOBJOUFSO !
γϯλοΫεͱηϚϯςΟΫε • シンタックス(Syntax) • プロトコルの参加者が、どんなフォーマットでやりとりする か • セマンティクス(Semantics) • シンタックスに従ってやりとりされるデータをどう解釈する
か IBUFOBJOUFSO !
HTTP Hypertext Transfer Protocol IBUFOBJOUFSO !
Hypertext Transfer Protocol http://www.example.com/ • ハイパーテキスト • リンクしたり画像を埋め込んだりできるテキスト • HTML
によって表現されるもの • …のためのプロトコル IBUFOBJOUFSO !
HTTP ͷλΠϜϥΠϯ 1991 HTTP/%.' 1996 HTTP/%.' 1997 HTTP/%.% 2009 Google
が SPDY を発表 2013 Google が QUIC を発表 2015 SPDY を元にしたHTTP/%の 標準化 2018 HTTP-over-QUIC を HTTP/%に改名 2021 QUIC の標準化 2022 HTTP/% の標準化 IBUFOBJOUFSO !
HTTP/1.1: HTTP ͷجૅ • RFC &''(: HTTP Semantics • RFC
&''': HTTP Caching • RFC &''8: HTTP/'.' • Deprecated: • RFC 8(?@ Hypertext Transfer Protocol -- HTTP/'.' • RFC 8?'? Hypertext Transfer Protocol -- HTTP/'.' • RFC G8H( Hypertext Transfer Protocol (HTTP/'.'): Message Syntax and Routing • RFC G8H' Hypertext Transfer Protocol (HTTP/'.'): Semantics and Content • RFC G8H8 Hypertext Transfer Protocol (HTTP/'.'): Conditional Requests • RFC G8HH Hypertext Transfer Protocol (HTTP/'.'): Range Requests • RFC G8HN Hypertext Transfer Protocol (HTTP/'.'): Caching • RFC G8HO Hypertext Transfer Protocol (HTTP/'.'): Authentication IBUFOBJOUFSO !"
Uniform Resource Locator (URL) • ブラウザで「開く」と… • HTTP(S) でリソースを取得する •
motemen.hatenablog.com の 443 ポート • /search?q=git • データ (HTML) を解釈して表⽰する IBUFOBJOUFSO !!
ਓؒ HTTP/1.1 ΛͬͯΈΔ • http://hatena.blog/ へのアクセス $ nc hatena.blog 80
GET / HTTP/1.1 Host: hatena.blog ↵ IBUFOBJOUFSO !"
HTTP/1.1 301 Moved Permanently Server: CloudFront Date: Tue, 06 Aug
2024 15:05:29 GMT Content-Type: text/html Content-Length: 167 Connection: keep-alive Location: https://hatena.blog/ X-Cache: Redirect from cloudfront Via: 1.1 8c817b46442ccacdcf3e583dbee62638.cloudfront.net (CloudFront) X-Amz-Cf-Pop: KIX56-P3 X-Amz-Cf-Id: ELtBOsBNUbrwkgpoiVQpEqXNxcOEmWWlcDPIIf31oudnwEgn9MNysw== <html> <head><title>301 Moved Permanently</title></head> <body> <center><h1>301 Moved Permanently</h1></center> <hr><center>CloudFront</center> </body> </html> IBUFOBJOUFSO !"
HTTPS ͬͯΈΔ • HTTP over TLS • https://hatena.blog/ へのアクセス $
openssl s_client -connect hatena.blog:443 GET / HTTP/1.1 Host: hatena.blog ↵ IBUFOBJOUFSO !"
HTTP ͷεΠεΞʔϛʔφΠϑ: curl $ curl --head --location --verbose http://hatena.blog/ >
HEAD / HTTP/1.1 > Host: hatena.blog > User-Agent: curl/8.6.0 > Accept: */* > < HTTP/1.1 301 Moved Permanently ... curl --help all で楽しもう IBUFOBJOUFSO !"
HTTP ͷηϚϯςΟΫε • リクエスト • メソッドとターゲット • レスポンス • ステータス
• 共通 • ヘッダー • ボディ IBUFOBJOUFSO !"
HTTP/1.1 γϯλοΫε ϦΫΤετ <method> <target> HTTP/1.1 <field>: <value> <body> Ϩεϙϯε
HTTP/1.1 000 <reason> <field>: <value> <body> IBUFOBJOUFSO !"
ϦΫΤετߦ <method> <target> HTTP/1.1 GET POST PUT HEAD DELETE OPTIONS
TRACE CONNECT PATCH /entry/1 /search?q=text / HTTP/1.0 HTTP/1.1 IBUFOBJOUFSO !"
εςʔλεߦ HTTP/1.1 000 Reason • 1xx Informational • 2xx Successful
• 3xx Redirection • 4xx Client Error • 5xx Server Error IBUFOBJOUFSO !"
ϘσΟ HTML <!DOCTYPE html> <html lang="ja"> ... JSON { "id":
"42", "created": 1723707520, ... } PNG ը૾ ?PNG\0d\1a\00\00\00\0dIHDR... IBUFOBJOUFSO !"
ϔομʔ Host: hatena.blog Content-Type: text/html Content-Length: 167 Location: https://hatena.blog/ •
メッセージを拡張したり、メタデータとして機能したり IBUFOBJOUFSO !"
Content-Type • Content-Type: text/html — HTML • Content-Type: application/json —
JSON • Content-Type: image/png — PNG 画像 IBUFOBJOUFSO !!
ίϯςϯτωΰγΤʔγϣϯ 同じ URL へのアクセスでも… • Accept: text/html • リンク遷移など •
Accept: image/* • <img> 要素からのリクエストなど IBUFOBJOUFSO !"
Server-Sent Events • Content-Type: text/event-stream • サーバ側からプッシュ形式でデータをクライアントに送信す る var source
= new EventSource("updates.cgi"); source.onmessage = function (event) { alert(event.data); }; IBUFOBJOUFSO !"
ϘσΟͷѹॖ • クライアント Accept-Encoding: gzip, deflate • サーバ Content-Encoding: gzip
• gzip • compress • deflate • identity • br IBUFOBJOUFSO !"
ΫοΩʔ ! • サーバ Set-Cookie: key=value; Expires=Wed, 09 Jun 2024
10:18:14 GMT • クライアント Cookie: key=value • HTTP は本来ステートレス → 「セッション」の導⼊ • ブラウザにクッキーを⾷べさせることで次回以降のリクエストに情 報を持ち越す IBUFOBJOUFSO !"
Ωϟογϡ ! Cache-Control: public, max-age=14400 Cache-Control: private Vary: Accept-Encoding IBUFOBJOUFSO
!"
HTTP/2 RFC %&'( Hypertext Transfer Protocol Version ; (HTTP/;) IBUFOBJOUFSO
!"
HTTP/1.1 ͷ • 背景: 複雑化する Web アプリケーション環境 • たくさんのアセット (JavaScript、画像、…)
• モバイル機器からのアクセス • リクエスト-レスポンスのやりとりが TCP コネクションを専有 • ドメインあたりのコネクションは 6 つほどに制限されている • 「重い」リクエストがあると次のリクエストができない • ヘッダーの冗⻑性 IBUFOBJOUFSO !"
IBUFOBJOUFSO !"
HTTP/2 • セマンティクスは HTTP//./ と共通 • バイナリフレームでやりとり • ひとつの TCP
コネクションを複数のストリームに分割 • 複数のリソースを⼀度にやり取りできる • 複雑な制御ができる • ヘッダーも圧縮 IBUFOBJOUFSO !"
HPACK RFC %&'( HPACK: Header Compression for HTTP/; Index Header
Name Header Value / :authority 0 :method GET 1 :method POST 2 :path / 3 :path /index.html 4 :scheme http 5 :scheme https 6 :status 200 IBUFOBJOUFSO !"
HTTP/3 • QUIC トランスポート • UDP 上に TCP と TLS
の機能を再現 • HTTP-over-QUIC • HTTP/B を QUIC トランスポート上で実装 • QPACK • コネクションマイグレーション $ open https://http3.is IBUFOBJOUFSO !!
HTTP • セマンティクス • HTTP/-.- • シンタックス • HTTP/2, HTTP/5
• モチベーション • 仕組み IBUFOBJOUFSO !"
API Application Programming Interface IBUFOBJOUFSO !"
Application Programming Interface • OS ⇔ アプリケーション • glibc: システムコール
• ブラウザ ⇔ JavaScript アプリケーション • DOM (Document Object Model): HTML ⽂書を JS から操作 • Web サービス ⇔ Web フロントエンド、アプリ、別システム • REST • GraphQL • gRPC IBUFOBJOUFSO !"
LSUDs (Large Set of Unknown Developers) • 最⼤公約数的な API を提供する
SSKDs (Small Set of Known Developers) • クライアントに最適化した API を提供する IBUFOBJOUFSO !"
REST Representational State Transfer • HTTP の仕組みをうまく使う • リソース指向 https://api.github.com/repos/hatena/example/
issues/1 IBUFOBJOUFSO !"
CRUD HTTP メソッド Create POST Read GET Update PUT /
PATCH Delete DELETE IBUFOBJOUFSO !"
ྫ: GitHub ͷΠγϡʔίϝϯτ • POST /repos/:owner/:repo/issues/:issue_number/comments • GET /repos/:owner/:repo/issues/comments/:comment_id •
PATCH /repos/:owner/:repo/issues/comments/:comment_id • DELETE /repos/:owner/:repo/issues/comments/:comment_id ྫ: OpenAI ͷϑΝΠϯνϡʔχϯά • POST /v1/fine_tuning/jobs • GET /v1/fine_tuning/jobs/{fine_tuning_job_id} • POST /v1/fine_tuning/jobs/{fine_tuning_job_id}/cancel IBUFOBJOUFSO !"
REST ͷಛ • 実装や原則がシンプル • 道具なく作りはじめられる • REST「⾵」になりがちではある • クライアント側から使いにくくなりがち
• オーバーフェッチ、アンダーフェッチ • 要求の変化への対応が難しくなりがち IBUFOBJOUFSO !"
OpenAPI • Swagger • REST API を記述するための仕様 • コード⽣成‧ドキュメント⽣成にも使える •
例: https://github.com/openai/openai-openapi IBUFOBJOUFSO !"
GraphQL • Meta によって開発された • クライアント側から必要なフィールドを指定する • スキーマからのコード⽣成ができる IBUFOBJOUFSO !"
SDL (Schema Definition Language) type Query { blog(id: String!): Blog
} type Blog { title: String! entries(first: Int!): [Entry!] } type Entry { title: String! body: String! name: String @deprecated(reason: "Use `title`.") } IBUFOBJOUFSO !!
ྫ: GitHub API ͷΫΤϦ $ gh api graphql --verbose -f
query='query { viewer { login repositories(last: 3, visibility: PUBLIC) { nodes { name } } } }' { "data": { "viewer": { "login": "motemen", "repositories": { "nodes": [ { "name": "pokemon-data" }, { "name": "pamo3-card-to-pokesol-text" }, { "name": "macos-obs-websocket-ocr" } ] } } } } IBUFOBJOUFSO !"
πʔϧηοτͷαϙʔτ • サーバ • スキーマからのコード⽣成 • リゾルバの実装 • クライアント •
UI ライブラリとの連携 • 型定義の⽣成 • キャッシュの管理 • GraphiQL IBUFOBJOUFSO !"
GraphQL ͷಛ • クライアントは必要⼗分なデータを取得できる • クライアントはスキーマに基づいてリクエストを組み⽴てる • サーバ側は複雑になりがち • ⾃由に書けすぎるので制限が必要
• ロギング IBUFOBJOUFSO !"
gRPC • Google によって開発された • RPC (Remote Procedure Call) のためのシステム
• 定義ファイルからのコード⽣成 • HTTP/S ベース • 双⽅向ストリーミングもサポート IBUFOBJOUFSO !"
Protocol Buffers • 構造化されたデータをシリアライズする仕組み • バイナリフォーマット • IDL (Interface Description
Language) • .protoファイル • RPC をサポートしている IBUFOBJOUFSO !"
syntax = "proto3"; package account; service Account { rpc Signup(SignupRequest)
returns (SignupReply); } message SignupRequest { string name = 1; string password = 2; } message SignupReply { string token = 1; } IBUFOBJOUFSO !"
ϝοηʔδܕ message SignupRequest { string name = 1; string password
= 2; } ϑΟʔϧυܕ ϑΟʔϧυ໊ = ϑΟʔϧυ൪߸; • フィールド番号が重要 IBUFOBJOUFSO !"
ޓੑ • フィールド番号 int32 old_field = 6 [deprecated = true];
reserved 2, 15, 9 to 11; reserved "foo", "bar"; IBUFOBJOUFSO !"
gRPC ʹ͓͚Δ API ઃܭ CRUD + List • CreateEntity •
GetEntity • UpdateEntity • DeleteEntity • ListEntities IBUFOBJOUFSO !"
gRPC αʔόʔΛ࡞Δ IBUFOBJOUFSO !"
syntax = "proto3"; option go_package = "./pb"; package welcome; service
Welcome { rpc Greet(GreetRequest) returns (GreetReply); } message GreetRequest { string name = 1; } message GreetReply { string message = 1; } IBUFOBJOUFSO !!
Protocol Compiler protoc $ brew install protobuf # for protoc
$ go install google.golang.org/protobuf/cmd/protoc-gen-go $ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc $ protoc --go_out=. --go-grpc_out=. welcome.proto IBUFOBJOUFSO !"
package main import ( "context" "flag" "fmt" "github.com/hatena/intern-grpc/pb" "google.golang.org/grpc" "google.golang.org/grpc/reflection"
"log" "net" "os" "os/signal" ) var ( port = flag.Int("port", 10000, "The server port") ) IBUFOBJOUFSO !"
type welcomeServer struct { pb.UnimplementedWelcomeServer } func (s *welcomeServer) Greet(
ctx context.Context, req *pb.GreetRequest ) (*pb.GreetReply, error) { return &pb.GreetReply{ Message: fmt.Sprintf("Welcome %s", req.Name), }, nil } func newServer() *welcomeServer { return &welcomeServer{} } IBUFOBJOUFSO !"
func main() { lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port)) if
err != nil { log.Fatalf("failed to listen: %v", err) } grpcServer := grpc.NewServer() pb.RegisterWelcomeServer(grpcServer, newServer()) reflection.Register(grpcServer) go func() { log.Printf("start gRPC server port: %v", *port) grpcServer.Serve(lis) }() quit := make(chan os.Signal) signal.Notify(quit, os.Interrupt) <-quit log.Printf("stopping gRPC server...") grpcServer.GracefulStop() } IBUFOBJOUFSO !"
Let’s try!: grpcurl IBUFOBJOUFSO !"
grpcurl $ docker compose up grpc_server-1 | 2024/08/06 14:47:05 start
gRPC server port: 10000 $ grpcurl -plaintext localhost:10000 list grpc.reflection.v1.ServerReflection grpc.reflection.v1alpha.ServerReflection welcome.Welcome IBUFOBJOUFSO !"
grpcurl $ grpcurl -plaintext localhost:10000 describe welcome.Welcome welcome.Welcome is a
service: service Welcome { rpc Greet ( .welcome.GreetRequest ) returns ( .welcome.GreetReply ); } $ grpcurl -plaintext localhost:10000 describe welcome.GreetRequest welcome.GreetRequest is a message: message GreetRequest { string name = 1; } $ grpcurl -plaintext -d '{"name":"motemen"}' localhost:10000 welcome.Welcome.Greet { "message": "Welcome motemen" } IBUFOBJOUFSO !"
API • いくつかの API について⾒てきた • REST • GraphQL •
gRPC • 特徴とトレードオフを理解して使おう IBUFOBJOUFSO !"
͓ΘΓ IBUFOBJOUFSO !"