Upgrade to Pro — share decks privately, control downloads, hide ads and more …

はてなリモートインターン2021 Web API 講義資料

Hatena
October 08, 2021

はてなリモートインターン2021 Web API 講義資料

Hatena

October 08, 2021
Tweet

More Decks by Hatena

Other Decks in Technology

Transcript

  1. Web API
    IBUFOBJOUFSO

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  4. )551
    )ZQFSUFYU5SBOTGFS1SPUPDPM

    View full-size slide

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

    
    26*$ס嘅嶖⴫

    View full-size slide

  6. )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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  10. 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>

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  22. )&"%&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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  30. ج؞ٖؓם26*$
    ˝ 5-4
    ˝ 355ـ٤غبؘؕؠמ׻׾냕鵭⴫ &BSMZ%BUB

    ˝ 14, ◄⯥⪦鵟ꐶ

    ˝ ꐶס⫋⮵榫

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  34. "1*
    "QQMJDBUJPO1SPHSBNNJOH*OUFSGBDF

    View full-size slide

  35. -46%T -BSHF4FUPG6OLOPXO%FWFMPQFST

    ˝ 僃㛻⪜硜丗氳ם"1*؅䬠❠׌׾
    44,%T 4NBMM4FUPG,OPXO%FWFMPQFST

    ˝ ؠٚؕؓ٤عמ僃鸵⴫׊ג"1*؅䬠❠׌׾

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  38. (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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  41. 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
    }

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  44. 1SPUPDPM#VFST
    ˝ 啶鵰⴫׈׿גظ٭ذ؅بٛؓٚؕث׌׾☼磝ײ
    ˝ فؕػٛنؚ٭ُشع
    ˝ *%- *OUFSGBDF%FTDSJQUJPO-BOHVBHF

    ˝ .protoنٜؒؕ
    ˝ 31$؅ئَ٭ع׊יַ׾

    View full-size slide

  45. syntax = "proto3";
    package account;
    service Account {
    rpc Signup(SignupRequest) returns (SignupReply);
    }
    message SignupRequest {
    string name = 1;
    string password = 2;
    }
    message SignupReply {
    string token = 1;
    }

    View full-size slide

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

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  49. 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;
    }

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  52. ؛وب٘٤
    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];
    }

    View full-size slide

  53. ئ٭لتכتعٛ٭ّ
    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) {}
    }

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  56. H31$ئ٭ف٭؅⛼׾

    View full-size slide

  57. 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;
    }

    View full-size slide

  58. 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

    View full-size slide

  59. 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")
    )

    View full-size slide

  60. 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{}
    }

    View full-size slide

  61. 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()
    }

    View full-size slide

  62. -FU˖TUSZgrpc_cli

    View full-size slide

  63. 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

    View full-size slide

  64. 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"'

    View full-size slide