Slide 1

Slide 1 text

Web API IBUFOBJOUFSO

Slide 2

Slide 2 text

׆ס铺紶ךע ˝ )551 ˝ 3&45 ˝ (SBQI2- ˝ H31$

Slide 3

Slide 3 text

"1* "QQMJDBUJPO1SPHSBNNJOH*OUFSGBDF ˝ HMJCD ˝ document.getElementById ˝ GET https:!"api.twitter.com/1.1/statuses/ show.json?id=210462857140252672

Slide 4

Slide 4 text

)551 )ZQFSUFYU5SBOTGFS1SPUPDPM

Slide 5

Slide 5 text

)551סذّؕٚؕ٤  )551  )551  )551  (PPHMFֿ41%:؅ 氦辐  (PPHMFֿ26*$؅ 氦辐  41%:؅⩕מ׊ג)551ס嘅嶖⴫  )551PWFS26*$؅)551מ䷉ ⺲  26*$ס嘅嶖⴫

Slide 6

Slide 6 text

)551 ˝ 3'$)ZQFSUFYU5SBOTGFS1SPUPDPM)551 ˝ 3'$)ZQFSUFYU5SBOTGFS1SPUPDPM)551 ˝ 3'$)ZQFSUFYU5SBOTGFS1SPUPDPM )551 .FTTBHF4ZOUBYBOE3PVUJOH ˝ 3'$)ZQFSUFYU5SBOTGFS1SPUPDPM )551 4FNBOUJDTBOE$POUFOU ˝ 3'$)ZQFSUFYU5SBOTGFS1SPUPDPM )551 $POEJUJPOBM3FRVFTUT ˝ 3'$)ZQFSUFYU5SBOTGFS1SPUPDPM )551 3BOHF3FRVFTUT ˝ 3'$)ZQFSUFYU5SBOTGFS1SPUPDPM )551 $BDIJOH ˝ 3'$)ZQFSUFYU5SBOTGFS1SPUPDPM )551 "VUIFOUJDBUJPO

Slide 7

Slide 7 text

)551סجُ٤طؔؠت ˝ ْخشغכذ٭أشعٛؠؙتع ˝ تط٭ذتٝتَ٤ت ˝ ىشر٭ ˝ ٍظؔ

Slide 8

Slide 8 text

63- 6OJGPSN3FTPVSDF-PDBUPS https:!"localhost:8000/search?q=text#hello εΩʔϜ:!"ϗετ:ϙʔτ/ύε?ΫΤϦ#ϑϥάϝϯτ 8)"58(63--JWJOH4UBOEBSE

Slide 9

Slide 9 text

/FUDBUך)551ٛؠؙتع $ nc www.hatena.ne.jp 80 !" EOF GET / HTTP/1.1 Host: www.hatena.ne.jp EOF

Slide 10

Slide 10 text

HTTP/1.1 301 Moved Permanently Server: awselb/2.0 Date: Mon, 03 Aug 2020 01:58:38 GMT Content-Type: text/html Content-Length: 150 Connection: keep-alive Location: https:!"www.hatena.ne.jp:443/ 301 Moved Permanently!#title>!#head>

301 Moved Permanently!#h1>!#center> !#body> !#html>

Slide 11

Slide 11 text

5-4ך䫘禈׊י)551ٛؠؙتع $ openssl s_client -connect www.hatena.ne.jp:443 HEAD / HTTP/1.1 Host: www.hatena.ne.jp

Slide 12

Slide 12 text

)551 ٛؠؙتع METHOD target HTTP/1.1 Header: Value body ٝتَ٤ت HTTP/1.1 000 Reason Header: Value body

Slide 13

Slide 13 text

ٛؠؙتع车 METHOD target HTTP/1.1 GET POST PUT HEAD DELETE OPTIONS TRACE CONNECT PATCH / /search?q=text HTTP/1.0 HTTP/1.1

Slide 14

Slide 14 text

ىشر٭ Host: www.hatena.ne.jp

Slide 15

Slide 15 text

تط٭ذت车 HTTP/1.1 000 Reason ˝ 1xx*OGPSNBUJPOBM ˝ 2xx4VDDFTTGVM ˝ 3xx3FEJSFDUJPO ˝ 4xx$MJFOU&SSPS ˝ 5xx4FSWFS&SSPS

Slide 16

Slide 16 text

ٍظؔ ˝ Content-Type: text/html˒)5.- ˝ Content-Type: application/JSON˒+40/ ˝ Content-Type: application/x-www-form-urlencoded key=value&another_key=another_value

Slide 17

Slide 17 text

ٍظؔס㏆竊 Accept-Encoding: gzip, deflate Content-Encoding: gzip ˝ gzip ˝ compress ˝ deflate ˝ identity ˝ br

Slide 18

Slide 18 text

)551 3'$)ZQFSUFYU5SBOTGFS1SPUPDPM7FSTJPO )551

Slide 19

Slide 19 text

)551 ˝ 㓹儖氳םجُ٤طؔؠتע㚺؂׼םַ ˝ فؕػٛך׷׽כ׽׌׾ ˝ ץכחס5$1ؤؾؠب٘٤؅♞䘶氳מ邾丗סتعٛ٭ّמ⮆Ⱏ ׌׾ ˝ تعٛ٭ّס╈ךنٝ٭ّ؅׷׽⹦׽׌׾ ˝ تعٛ٭ّס⨣⩝䈱׷❣㰆꞊➟׵辐杯ך׀׾

Slide 20

Slide 20 text

نٝ٭ّ +-----------------------------------------------+ | Length (24) | +---------------+---------------+---------------+ | Type (8) | Flags (8) | +-+-------------+---------------+-------------------------------+ |R| Stream Identifier (31) | +=+=============================================================+ | Frame Payload (0!!") !!" +---------------------------------------------------------------+ )ZQFSUFYU5SBOTGFS1SPUPDPM7FSTJPO )551 'SBNF'PSNBU

Slide 21

Slide 21 text

%"5"نٝ٭ّ0x0 +---------------+ |Pad Length? (8)| +---------------+-----------------------------------------------+ | Data (*) !!" +---------------------------------------------------------------+ | Padding (*) !!" +---------------------------------------------------------------+ END_STREAM 0x1 ]PADDED 0x8

Slide 22

Slide 22 text

)&"%&34نٝ٭ّ0x1 +---------------+ |Pad Length? (8)| +-+-------------+-----------------------------------------------+ |E| Stream Dependency? (31) | +-+-------------+-----------------------------------------------+ | Weight? (8) | +-+-------------+-----------------------------------------------+ | Header Block Fragment (*) !!" +---------------------------------------------------------------+ | Padding (*) !!" +---------------------------------------------------------------+ END_STREAM 0x1 ]END_HEADERS 0x4 ]PADDED 0x8 ]PRIORITY 0x20

Slide 23

Slide 23 text

橎⛍ىشر٭ ٛؠؙتع ˝ :method ˝ :authority ˝ :scheme ˝ :path ٝتَ٤ت ˝ :status

Slide 24

Slide 24 text

)1"$, 3'$)1"$,)FBEFS$PNQSFTTJPOGPS)551 ˝ ـنُ٤瑞⺘ ˝ ꪐ氳ط٭هٜ ˝ Ⳃ氳ط٭هٜ

Slide 25

Slide 25 text

*OEFY )FBEFS/BNF )FBEFS7BMVF  :authority  :method GET  :method POST  :path /  :path /index.html  :scheme http  :scheme https  :status 200

Slide 26

Slide 26 text

)551 ˝ )551סجُ٤طؔؠت؅禴䧏 ˝ ץכחס5$1ؤؾؠب٘٤؅邾丗סتعٛ٭ّמ⮆Ⱏ ˝ 邾丗סٛخ٭ت؅┉䈱מ׷׽⹦׽ך׀׾ ˝ 邾ꥭם⯆䐒ֿך׀׾ ˝ ىشر٭׵㏆竊

Slide 27

Slide 27 text

)551 ˝ 26*$عٚ٤تَ٭ع ˝ 6%1┕מ5$1כ5-4ס嚀耆؅⫋杯 ˝ )551PWFS26*$ ˝ )551؅26*$عٚ٤تَ٭ع┕ך㲔逷 ˝ ┘釐מםזג嚀耆؅⯡ꢜ ˝ 21"$,

Slide 28

Slide 28 text

)551PWFS26*$ ˝ 21"$, ˝ 瑞⺘⴫םלյ㓹儖ע)1"$,כ⺱׋ ˝ Ⳃ氳ط٭هٜס䣽ַ亠ס㚺催 ˝ ꪐ氳ط٭هٜס㵚䑴ىشر鴑ⱶ

Slide 29

Slide 29 text

26*$ ˝ 3'$7FSTJPO*OEFQFOEFOU1SPQFSUJFTPG26*$ ˝ 3'$26*$"6%1#BTFE.VMUJQMFYFEBOE4FDVSF 5SBOTQPSU ˝ 3'$6TJOH5-4UP4FDVSF26*$ ˝ 3'$26*$-PTT%FUFDUJPOBOE$POHFTUJPO$POUSPM

Slide 30

Slide 30 text

ج؞ٖؓם26*$ ˝ 5-4 ˝ 355ـ٤غبؘؕؠמ׻׾냕鵭⴫ &BSMZ%BUB ˝ 14, ◄⯥⪦鵟ꐶ ˝ ꐶס⫋⮵榫

Slide 31

Slide 31 text

ؤؾؠب٘٤ُؕءٝ٭ب٘٤ ˝ ⶡ┉סؾشع٠٭ؠقتמ䦔兠׈׿םַ ˝ ؙ٤غَؕ٤عסؓغٝت׷َ٭عֿ㚺催׈׿י׵䫘禈؅禴䧏 ך׀׾

Slide 32

Slide 32 text

ؓغٝتفٛظ٭ب٘٤ ˝ 鴜⟓⩕ؓغٝتֿ塜׊ַ׵ס־吾錞׌׾ ˝ عٚنؔشؠ㘃䆋䷍䱡 ؓ٤و䷍䱡 㵚瓀 ˝ 吾錞׈׿יַםַؓغٝتמ㵚׊יע鴜⟓ظ٭ذꄈ؅⯆꡾׌׾

Slide 33

Slide 33 text

)551 ˝ 6%1┕מ5$15-4؅㲔杯׌׾ ˝ )5514מ׻׾鵟⟓ֿ⯥䬠 ˝ 355מ׻׾Ⲗ曍⴫ ˝ /"5ٛفؕ٤ظؔ٤ءמ׻׾َ٭ع樑⺘㚺催םלֿ颯׀י׵䫘 禈ֿ禴䧏ך׀׾ ˝ ؓغٝت吾錞מ׻׾ؓ٤و䷍䱡㵚瓀

Slide 34

Slide 34 text

"1* "QQMJDBUJPO1SPHSBNNJOH*OUFSGBDF

Slide 35

Slide 35 text

-46%T -BSHF4FUPG6OLOPXO%FWFMPQFST ˝ 僃㛻⪜硜丗氳ם"1*؅䬠❠׌׾ 44,%T 4NBMM4FUPG,OPXO%FWFMPQFST ˝ ؠٚؕؓ٤عמ僃鸵⴫׊ג"1*؅䬠❠׌׾

Slide 36

Slide 36 text

3&45 3FQSFTFOUBUJPOBM4UBUF5SBOTGFS ˝ )551ס☼磝ײ؅ֹױׂ✳ֹ ˝ ٛخ٭ت䧗⺸ https:!"api.github.com/repos/hatena/example/ issues/1

Slide 37

Slide 37 text

$36% )551ْخشغ $SFBUF POST 3FBE GET 6QEBUF PUTPATCH %FMFUF DELETE

Slide 38

Slide 38 text

(JU)VCסؕبٖ٭ؤْ٤ع ˝ 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 39

Slide 39 text

0QFO"1* ˝ 4XBHHFS ˝ 3&45"1*؅鋗鳭׌׾ג״ס☼喋 ˝ ؤ٭غ榟䡗מ׵✳ֻ׾

Slide 40

Slide 40 text

(SBQI2- ˝ 'BDFCPPLמ׻זיꝧ氦׈׿ג ˝ ؠٚؕؓ٤ع⣐־׼䑒釐םنؔ٭ٜغ؅䧗㲊׌׾ ˝ ت؞٭ُ־׼סؤ٭غ榟䡗ֿך׀׾

Slide 41

Slide 41 text

4%- 4DIFNB%FOJUJPO-BOHVBHF 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 42

Slide 42 text

ؠؙٛ query GetFirstIssue { repository(name: "Hatena-Intern-2020", owner: "hatena") { issue(number: 1) { author { login } body title } } }

Slide 43

Slide 43 text

H31$

Slide 44

Slide 44 text

H31$PWFS)551 ˝ )551┕מ啶疣׈׿ג׵ס ˝ HEADERSنٝ٭ّ׷DATAنٝ٭ّ H31$8FC ˝ 8FCهٚؗا⺸ׄמ)551כ⮉׽ꦕ׊ג׵ס ˝ ئ٭ف٭⣐מ׵وٞ؞بֿ䑒釐

Slide 45

Slide 45 text

1SPUPDPM#VFST ˝ 啶鵰⴫׈׿גظ٭ذ؅بٛؓٚؕث׌׾☼磝ײ ˝ فؕػٛنؚ٭ُشع ˝ *%- *OUFSGBDF%FTDSJQUJPO-BOHVBHF ˝ .protoنٜؒؕ ˝ 31$؅ئَ٭ع׊יַ׾

Slide 46

Slide 46 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; }

Slide 47

Slide 47 text

ْشج٭ة㑔 message SignupRequest { string name = 1; string password = 2; } ϑΟʔϧυܕ ϑΟʔϧυ໊ = ϑΟʔϧυ൪߸; ˝ نؔ٭ٜغ樑⺘ֿꄆ釐 ˝ ױךעCZUF ˝ ע◀硜岷ײ

Slide 48

Slide 48 text

ت؜ٚ٭㑔 double float int32 int64 uint32 uint64 sint32 sint64 fixed32 fixed64 sfixed32 sfixed64 bool string bytes

Slide 49

Slide 49 text

repeated Result results = 1; map projects = 3; oneof test_oneof { string name = 4; SubMessage sub_message = 9; }

Slide 50

Slide 50 text

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 51

Slide 51 text

import "google/protobuf/any.proto"; message Message { google.protobuf.Any field = 1; } ˝ google.protobuf.Empty ˝ google.protobuf.Duration ˝ google.protobuf.Timestamp

Slide 52

Slide 52 text

◍䬵䓪 ˝ نؔ٭ٜغ樑⺘ int32 old_field = 6 [deprecated = true]; reserved 2, 15, 9 to 11; reserved "foo", "bar";

Slide 53

Slide 53 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 54

Slide 54 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 55

Slide 55 text

H31$מֽׄ׾"1*錃銶 $36%-JTU ˝ CreateEntity ˝ GetEntity ˝ UpdateEntity ˝ DeleteEntity ˝ ListEntities

Slide 56

Slide 56 text

$MPVE'VODUJPOTס❆ ˝ CallFunction ˝ CreateFunction ˝ GetFunction ˝ UpdateFunction ˝ DeleteFunction ˝ ListFunctions

Slide 57

Slide 57 text

H31$ئ٭ف٭؅⛼׾

Slide 58

Slide 58 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; }

Slide 59

Slide 59 text

1SPUPDPM$PNQJMFS protoc $ # protoc ͸ brew install protobuf ΍ apt install protobuf-compiler ͳͲͰ $ 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

Slide 60

Slide 60 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") )

Slide 61

Slide 61 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{} }

Slide 62

Slide 62 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() }

Slide 63

Slide 63 text

-FU˖TUSZgrpc_cli

Slide 64

Slide 64 text

grpc_cli $ docker run !"rm !"publish 10000:10000 hatena/intern-2020-grpc-adventure:latest $ docker run !"rm hatena/grpc_cli:latest ls host.docker.internal:10000 -l

Slide 65

Slide 65 text

grpc_cli $ grpc_cli ls localhost:10000 -l $ grpc_cli type localhost:10000 welcome.GreetRequest $ grpc_cli call localhost:10000 welcome.Welcome.Greet 'name: "John Appleseed"'