Slide 1

Slide 1 text

Web API #hatenaintern)*)+

Slide 2

Slide 2 text

この講義では • ⽬的: Web API を俯瞰してこの講義以降の講義,調べ物をラクにする • そのために: • ⽤語の確認 • 知識の概要 • Web API をいくつかピックアップ

Slide 3

Slide 3 text

この講義で取り扱うもの • ⽬次 • API • Web API • REST • GraphQL • gRPC • コードを少し触ります

Slide 4

Slide 4 text

API Application Programming Interface

Slide 5

Slide 5 text

API の例 • システム 対 アプリケーション画像 • libdrm : 描画 • DRM(カーネル)を動かすための API • glibc : システムコール • 直接起動するのではなくラッパー関数を呼び出す • ブラウザ 対 Web アプリケーション • document.getElementById : 要素取得 • ブラウザなど 対  Web サーバー : Web API • REST • curl -s https:!"random.dog/woof.json 画像 This image is licensed under the Creative Commons Attribution- Share Alike ;.= International license. Attribution: Shmuel Csaba Otto Traian. source https://commons.wikimedia.org/wiki/ File:Linux_API.svg

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

Web API

Slide 8

Slide 8 text

REST • Representational State Transfer • HTTP の仕組みをうまく使う • ⼀意な URI を持つ • https:!"api.github.com/repos/hatena/example/ issues/1 • 提唱者である Roy T. Fielding ⽒の 2000 年頃の論⽂

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

GitHub のイシューコメント(再掲) • GET /repos/:owner/:repo/issues/ comments/:comment_id • POST /repos/:owner/:repo/issues/:issue_number/ comments • PATCH /repos/:owner/:repo/issues/ comments/:comment_id • DELETE /repos/:owner/:repo/issues/ comments/:comment_id

Slide 11

Slide 11 text

OpenAPI • Open API Spesification の略称 • Swagger • 元々 Swagger フレームワークの⼀部だったという歴史がある • REST API を記述するための仕様 • YAML や JSON で API の仕様を記述できる • ツールを使ってそのままドキュメントやコード⽣成をすることも できる

Slide 12

Slide 12 text

GraphQL

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

SDL (Schema Definition Language) interface Actor { login: String! } type Issue { author: Actor body: String! title: String! } type Repository { issue(number: Int!): Issue } type Query { repository(name: String!, owner: String!): Repository }

Slide 15

Slide 15 text

データの取得例 query GetFirstIssue { repository(name: "Hatena-Intern-2023", owner: "hatena") { issue(number: 1) { author { login } body title } } }

Slide 16

Slide 16 text

gRPC

Slide 17

Slide 17 text

gRPC • RPC • Remote Procedure Call の略 • gRPC • Google が開発したプロトコル • IDL をもとにしてサーバーおよびク ライアントの雛形を作成するのが特 徴 • g の意味はバージョンごとに違う

Slide 18

Slide 18 text

gRPC over HTTP/- • HTTP/& 上に構築されたもの • HEADERSフレームやDATAフレームを使って通信する • 1 つの TCP コネクション内に複数のストリームを持つことが できる

Slide 19

Slide 19 text

gRPC Web • Web ブラウザ向けに HTTP/1 と切り離したもの • サーバー側にもプロキシが必要 • Envoy などがよく使われる

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

proto ファイルの例 syntax = "proto3"; package account; service Account { rpc Signup(SignupRequest) returns (SignupReply); } message SignupRequest { string name = 1; string password = 2; } message SignupReply { string token = 1; }

Slide 22

Slide 22 text

メッセージ型 message SignupRequest { string name = 1; string password = 2; } ϑΟʔϧυܕ ϑΟʔϧυ໊ = ϑΟʔϧυ൪߸; • フィールド番号が重要 • シリアライズ時にはこのフィールド番号が使われる • 1-15 までは 1byte(16 〜 2047 は 2byte) • 19000-19999 は内部実装で予約済み

Slide 23

Slide 23 text

スカラー型 double float int32 int64 uint32 uint64 sint32 sint64 fixed32 fixed64 sfixed32 sfixed64 bool string bytes

Slide 24

Slide 24 text

その他の proto の⽂法 (1) repeated で配列を表現することができる message Result { repeated int32 score = 1; } map で辞書構造を表現できる map projects = 3; map は厳密には型ではくシンタックスシュガーで下記の構⽂と糖化です message MapField { key_type key = 1; value_type value = 2; } repeated MapField map_field = 1;

Slide 25

Slide 25 text

その他の proto の⽂法 (2) oneof は排他的に現れるフィールドを表現できる oneof test_oneof { string name = 4; SubMessage sub_message = 9; }

Slide 26

Slide 26 text

その他の proto の⽂法 (3) enum も定義できる message SearchRequest { string query = 1; int32 page_number = 2; int32 result_per_page = 3; enum Corpus { UNIVERSAL = 0; WEB = 1; IMAGES = 2; LOCAL = 3; NEWS = 4; PRODUCTS = 5; VIDEO = 6; } Corpus corpus = 4; }

Slide 27

Slide 27 text

外部ファイルの import import "google/protobuf/any.proto"; message Message { google.protobuf.Any field = 1; } • google.protobuf.Empty • google.protobuf.Duration • google.protobuf.Timestamp

Slide 28

Slide 28 text

スキーマ変更時の互換性 • ⼀度割り当てたフィールド番号は原則変更できない • 過去のバージョンの.protoファイルを読み込まれる恐れがあるため • フィールド番号などを使わない仕組みがいくつか⽤意されている deprecated int32 old_field = 6 [deprecated = true]; reserved reserved 2, 15, 9 to 11; reserved "foo", "bar";

Slide 29

Slide 29 text

オプション option go_package = "github.com/hatena/example/pb"; enum EnumAllowingAlias { option allow_alias = true; UNKNOWN = 0; STARTED = 1; RUNNING = 1; } message Example { int32 old_field = 6 [deprecated = true]; }

Slide 30

Slide 30 text

サービスとストリーム service RouteGuide { rpc GetFeature(Point) returns (Feature) {} rpc ListFeatures(Rectangle) returns (stream Feature) {} rpc RecordRoute(stream Point) returns (RouteSummary) {} rpc RouteChat(stream RouteNote) returns (stream RouteNote) {} }

Slide 31

Slide 31 text

RPC の種類 (1) • Unary RPCs (SimpleRPC) • single request single response • シンプルな通信 • Server streaming RPC • クライアント側はすべてのメッセージを受信すると処理を完 了する

Slide 32

Slide 32 text

RPC の種類 (2) • Client streaming RPC • クライアント側は複数のメッセージを送り単⼀のメッセージを受 信する • Bidirectional streaming RPC • 双⽅向ストリーミングのこと • クライアント側とサーバー側のストリームは独⽴している • そのためそれぞれ任意の順序でメッセージの読み書きができる

Slide 33

Slide 33 text

gRPC における API 設計 CRUD + List • CreateEntity • GetEntity • UpdateEntity • DeleteEntity • ListEntities

Slide 34

Slide 34 text

Cloud Functions の例 • CallFunction • CreateFunction • GetFunction • UpdateFunction • DeleteFunction • ListFunctions

Slide 35

Slide 35 text

gRPC サーバーを作る 会場: Hatena-Intern--.-/-Lecture/api/grpc_adventure/

Slide 36

Slide 36 text

proto ファイル まずは proto ファイルを作成して定義をしていきます 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; }

Slide 37

Slide 37 text

Protocol Compiler # protoc ͷηοτΞοϓ $ sudo apt update $ sudo apt install protobuf-compiler # macͷ৔߹ $ brew install protobuf # goͷϓϥάΠϯΛΠϯετʔϧ $ go install google.golang.org/protobuf/cmd/protoc-gen-go@latest $ go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

Slide 38

Slide 38 text

Protocol Compiler で Go の定義を書き出す $ mkdir pb $ protoc !"go_out ./pb \ !"go-grpc_out ./pb \ !"go_opt=paths=source_relative \ !"go-grpc_opt paths=source_relative welcome.proto

Slide 39

Slide 39 text

Protocol Compiler で Go の実装 (1) package main import ( "context" "fmt" "grpc_adventure/pb" !" module໊/σΟϨΫτϦ໊ "log" "net" "os" "os/signal" "google.golang.org/grpc" "google.golang.org/grpc/reflection" )

Slide 40

Slide 40 text

Protocol Compiler で Go の実装 (2) 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{} }

Slide 41

Slide 41 text

Protocol Compiler で Go の実装 (3) func main() { port !" 10000 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, 1) signal.Notify(quit, os.Interrupt) !$quit log.Printf("stopping gRPC server!!%") grpcServer.GracefulStop() }

Slide 42

Slide 42 text

Let’s try!: grpcurl

Slide 43

Slide 43 text

grpcurl # grpcurl ͷ install go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest # αʔϏεͷҰཡ grpcurl -plaintext localhost:10000 list # ϝιου΍ܕͷৄࡉ grpcurl -plaintext localhost:10000 describe welcome.Welcome.Greet grpcurl -plaintext localhost:10000 describe welcome.GreetRequest # αʔϏεͷݺͼग़͠ grpcurl -plaintext -d '{"name": "John Appleseed"}' localhost:10000 welcome.Welcome/Greet

Slide 44

Slide 44 text

おしまい