Slide 1

Slide 1 text

HTTP, Web, API IBUFOBJOUFSO !

Slide 2

Slide 2 text

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 !

Slide 3

Slide 3 text

͜ͷߨٛͰ͸ • HTTP, Web • シンタックス • セマンティクス • ウェブの事情 • API • REST • GraphQL • gRPC IBUFOBJOUFSO !

Slide 4

Slide 4 text

Πϯλʔωοτ࠷ߴʂ ChatGPT: ͦΕ͸؆୯ʹʮ͸͍ʯ·ͨ͸ʮ͍͍͑ʯͰ౴͑ΒΕΔ࣭໰Ͱ͸͋Γ·ͤΜ͕ɺݸਓతͳҙݟΛड़΂Δͱʮ͸͍ʯͱ౴͑·͢ɻ Πϯλʔωοτ͸৘ใͷڞ༗ɺίϛϡχέʔγϣϯɺֶशɺΤϯλʔςΠϝϯτͳͲͷ໘Ͱඇৗʹ༗ӹͰ͢ɻ ͨͩ͠ɺϓϥΠόγʔ΍ηΩϡϦςΟͷϦεΫ΋ଘࡏ͠·͢ͷͰɺ͜ΕΒΛߟྀ͢Δ͜ͱ΋ॏཁͰ͢ɻ • インターネットはすごい • ブログを書いて、読んでもらうことができる • マンガや⼩説を読むことができる。更新通知も受け取れる • なんならそれらを提供するサービスを監視することもできる • では、そのすごいインターネットはどんなふうに実現されている? IBUFOBJOUFSO !

Slide 5

Slide 5 text

ϓϩτίϧ • = 約束ごと • TCP/IP, HTTP, DNS, TLS, SMTP, 3 • インターネットの参加者はプロトコルに従っている • サーバ(Google やはてな) • クライアント(ブラウザ、スマートフォンアプリ) • ルータ、… • これらのプロトコルは RFC によって定義される • = Request for Comments IBUFOBJOUFSO !

Slide 6

Slide 6 text

γϯλοΫεͱηϚϯςΟΫε • シンタックス(Syntax) • プロトコルの参加者が、どんなフォーマットでやりとりする か • セマンティクス(Semantics) • シンタックスに従ってやりとりされるデータをどう解釈する か IBUFOBJOUFSO !

Slide 7

Slide 7 text

HTTP Hypertext Transfer Protocol IBUFOBJOUFSO !

Slide 8

Slide 8 text

Hypertext Transfer Protocol http://www.example.com/ • ハイパーテキスト • リンクしたり画像を埋め込んだりできるテキスト • HTML によって表現されるもの • …のためのプロトコル IBUFOBJOUFSO !

Slide 9

Slide 9 text

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 !

Slide 10

Slide 10 text

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 !"

Slide 11

Slide 11 text

Uniform Resource Locator (URL) • ブラウザで「開く」と… • HTTP(S) でリソースを取得する • motemen.hatenablog.com の 443 ポート • /search?q=git • データ (HTML) を解釈して表⽰する IBUFOBJOUFSO !!

Slide 12

Slide 12 text

ਓؒ΋ HTTP/1.1 Λ஻ͬͯΈΔ • http://hatena.blog/ へのアクセス $ nc hatena.blog 80 GET / HTTP/1.1 Host: hatena.blog ↵ IBUFOBJOUFSO !"

Slide 13

Slide 13 text

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== 301 Moved Permanently

301 Moved Permanently


CloudFront IBUFOBJOUFSO !"

Slide 14

Slide 14 text

HTTPS ΋஻ͬͯΈΔ • HTTP over TLS • https://hatena.blog/ へのアクセス $ openssl s_client -connect hatena.blog:443 GET / HTTP/1.1 Host: hatena.blog ↵ IBUFOBJOUFSO !"

Slide 15

Slide 15 text

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 !"

Slide 16

Slide 16 text

HTTP ͷηϚϯςΟΫε • リクエスト • メソッドとターゲット • レスポンス • ステータス • 共通 • ヘッダー • ボディ IBUFOBJOUFSO !"

Slide 17

Slide 17 text

HTTP/1.1 γϯλοΫε ϦΫΤετ HTTP/1.1 : Ϩεϙϯε HTTP/1.1 000 : IBUFOBJOUFSO !"

Slide 18

Slide 18 text

ϦΫΤετߦ HTTP/1.1 GET POST PUT HEAD DELETE OPTIONS TRACE CONNECT PATCH /entry/1 /search?q=text / HTTP/1.0 HTTP/1.1 IBUFOBJOUFSO !"

Slide 19

Slide 19 text

εςʔλεߦ HTTP/1.1 000 Reason • 1xx Informational • 2xx Successful • 3xx Redirection • 4xx Client Error • 5xx Server Error IBUFOBJOUFSO !"

Slide 20

Slide 20 text

ϘσΟ HTML ... JSON { "id": "42", "created": 1723707520, ... } PNG ը૾ ?PNG\0d\1a\00\00\00\0dIHDR... IBUFOBJOUFSO !"

Slide 21

Slide 21 text

ϔομʔ Host: hatena.blog Content-Type: text/html Content-Length: 167 Location: https://hatena.blog/ • メッセージを拡張したり、メタデータとして機能したり IBUFOBJOUFSO !"

Slide 22

Slide 22 text

Content-Type • Content-Type: text/html — HTML • Content-Type: application/json — JSON • Content-Type: image/png — PNG 画像 IBUFOBJOUFSO !!

Slide 23

Slide 23 text

ίϯςϯτωΰγΤʔγϣϯ 同じ URL へのアクセスでも… • Accept: text/html • リンク遷移など • Accept: image/* • 要素からのリクエストなど IBUFOBJOUFSO !"

Slide 24

Slide 24 text

Server-Sent Events • Content-Type: text/event-stream • サーバ側からプッシュ形式でデータをクライアントに送信す る var source = new EventSource("updates.cgi"); source.onmessage = function (event) { alert(event.data); }; IBUFOBJOUFSO !"

Slide 25

Slide 25 text

ϘσΟͷѹॖ • クライアント Accept-Encoding: gzip, deflate • サーバ Content-Encoding: gzip • gzip • compress • deflate • identity • br IBUFOBJOUFSO !"

Slide 26

Slide 26 text

ΫοΩʔ ! • サーバ Set-Cookie: key=value; Expires=Wed, 09 Jun 2024 10:18:14 GMT • クライアント Cookie: key=value • HTTP は本来ステートレス → 「セッション」の導⼊ • ブラウザにクッキーを⾷べさせることで次回以降のリクエストに情 報を持ち越す IBUFOBJOUFSO !"

Slide 27

Slide 27 text

Ωϟογϡ ! Cache-Control: public, max-age=14400 Cache-Control: private Vary: Accept-Encoding IBUFOBJOUFSO !"

Slide 28

Slide 28 text

HTTP/2 RFC %&'( Hypertext Transfer Protocol Version ; (HTTP/;) IBUFOBJOUFSO !"

Slide 29

Slide 29 text

HTTP/1.1 ͷ໰୊఺ • 背景: 複雑化する Web アプリケーション環境 • たくさんのアセット (JavaScript、画像、…) • モバイル機器からのアクセス • リクエスト-レスポンスのやりとりが TCP コネクションを専有 • ドメインあたりのコネクションは 6 つほどに制限されている • 「重い」リクエストがあると次のリクエストができない • ヘッダーの冗⻑性 IBUFOBJOUFSO !"

Slide 30

Slide 30 text

IBUFOBJOUFSO !"

Slide 31

Slide 31 text

HTTP/2 • セマンティクスは HTTP//./ と共通 • バイナリフレームでやりとり • ひとつの TCP コネクションを複数のストリームに分割 • 複数のリソースを⼀度にやり取りできる • 複雑な制御ができる • ヘッダーも圧縮 IBUFOBJOUFSO !"

Slide 32

Slide 32 text

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 !"

Slide 33

Slide 33 text

HTTP/3 • QUIC トランスポート • UDP 上に TCP と TLS の機能を再現 • HTTP-over-QUIC • HTTP/B を QUIC トランスポート上で実装 • QPACK • コネクションマイグレーション $ open https://http3.is IBUFOBJOUFSO !!

Slide 34

Slide 34 text

HTTP • セマンティクス • HTTP/-.- • シンタックス • HTTP/2, HTTP/5 • モチベーション • 仕組み IBUFOBJOUFSO !"

Slide 35

Slide 35 text

API Application Programming Interface IBUFOBJOUFSO !"

Slide 36

Slide 36 text

Application Programming Interface • OS ⇔ アプリケーション • glibc: システムコール • ブラウザ ⇔ JavaScript アプリケーション • DOM (Document Object Model): HTML ⽂書を JS から操作 • Web サービス ⇔ Web フロントエンド、アプリ、別システム • REST • GraphQL • gRPC IBUFOBJOUFSO !"

Slide 37

Slide 37 text

LSUDs (Large Set of Unknown Developers) • 最⼤公約数的な API を提供する SSKDs (Small Set of Known Developers) • クライアントに最適化した API を提供する IBUFOBJOUFSO !"

Slide 38

Slide 38 text

REST Representational State Transfer • HTTP の仕組みをうまく使う • リソース指向 https://api.github.com/repos/hatena/example/ issues/1 IBUFOBJOUFSO !"

Slide 39

Slide 39 text

CRUD HTTP メソッド Create POST Read GET Update PUT / PATCH Delete DELETE IBUFOBJOUFSO !"

Slide 40

Slide 40 text

ྫ: 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 !"

Slide 41

Slide 41 text

REST ͷಛ௃ • 実装や原則がシンプル • 道具なく作りはじめられる • REST「⾵」になりがちではある • クライアント側から使いにくくなりがち • オーバーフェッチ、アンダーフェッチ • 要求の変化への対応が難しくなりがち IBUFOBJOUFSO !"

Slide 42

Slide 42 text

OpenAPI • Swagger • REST API を記述するための仕様 • コード⽣成‧ドキュメント⽣成にも使える • 例: https://github.com/openai/openai-openapi IBUFOBJOUFSO !"

Slide 43

Slide 43 text

GraphQL • Meta によって開発された • クライアント側から必要なフィールドを指定する • スキーマからのコード⽣成ができる IBUFOBJOUFSO !"

Slide 44

Slide 44 text

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 !!

Slide 45

Slide 45 text

ྫ: 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 !"

Slide 46

Slide 46 text

πʔϧηοτͷαϙʔτ • サーバ • スキーマからのコード⽣成 • リゾルバの実装 • クライアント • UI ライブラリとの連携 • 型定義の⽣成 • キャッシュの管理 • GraphiQL IBUFOBJOUFSO !"

Slide 47

Slide 47 text

GraphQL ͷಛ௃ • クライアントは必要⼗分なデータを取得できる • クライアントはスキーマに基づいてリクエストを組み⽴てる • サーバ側は複雑になりがち • ⾃由に書けすぎるので制限が必要 • ロギング IBUFOBJOUFSO !"

Slide 48

Slide 48 text

gRPC • Google によって開発された • RPC (Remote Procedure Call) のためのシステム • 定義ファイルからのコード⽣成 • HTTP/S ベース • 双⽅向ストリーミングもサポート IBUFOBJOUFSO !"

Slide 49

Slide 49 text

Protocol Buffers • 構造化されたデータをシリアライズする仕組み • バイナリフォーマット • IDL (Interface Description Language) • .protoファイル • RPC をサポートしている IBUFOBJOUFSO !"

Slide 50

Slide 50 text

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 !"

Slide 51

Slide 51 text

ϝοηʔδܕ message SignupRequest { string name = 1; string password = 2; } ϑΟʔϧυܕ ϑΟʔϧυ໊ = ϑΟʔϧυ൪߸; • フィールド番号が重要 IBUFOBJOUFSO !"

Slide 52

Slide 52 text

ޓ׵ੑ • フィールド番号 int32 old_field = 6 [deprecated = true]; reserved 2, 15, 9 to 11; reserved "foo", "bar"; IBUFOBJOUFSO !"

Slide 53

Slide 53 text

gRPC ʹ͓͚Δ API ઃܭ CRUD + List • CreateEntity • GetEntity • UpdateEntity • DeleteEntity • ListEntities IBUFOBJOUFSO !"

Slide 54

Slide 54 text

gRPC αʔόʔΛ࡞Δ IBUFOBJOUFSO !"

Slide 55

Slide 55 text

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 !!

Slide 56

Slide 56 text

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 !"

Slide 57

Slide 57 text

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 !"

Slide 58

Slide 58 text

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 !"

Slide 59

Slide 59 text

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 !"

Slide 60

Slide 60 text

Let’s try!: grpcurl IBUFOBJOUFSO !"

Slide 61

Slide 61 text

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 !"

Slide 62

Slide 62 text

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 !"

Slide 63

Slide 63 text

API • いくつかの API について⾒てきた • REST • GraphQL • gRPC • 特徴とトレードオフを理解して使おう IBUFOBJOUFSO !"

Slide 64

Slide 64 text

͓ΘΓ IBUFOBJOUFSO !"