grpc_kit 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: db6a319fa0f74330575752eb203e867d4882d869ec12f73643bf11bc3f147c8d
4
- data.tar.gz: 376c711925c3f8534d7e286ed1bc7015ae711f7d4e2998b89fd8a2a2a2a0daac
3
+ metadata.gz: 287f67b56117d3821a209c4be0892d6a9b7327fae3f7db509427afd2b53ef01b
4
+ data.tar.gz: f2e75960649d6f0c76fa6aae4d6370e0a7d4285d7154ca5bd1a640b5a1d458f0
5
5
  SHA512:
6
- metadata.gz: 6fa2789ac0febc6e8dfac1f57d59488d1ab4db39b32c0e529a3fb91240d890abe9021f65db6d539c0d8218dc89204ca284db3b1e302c02d5f2ff785e76d8e9a0
7
- data.tar.gz: a8d7f9a5446308d2d31fcde7f4de762a262b58a6068ded6b8a60a0787d68001b7f2cd555a7910977ab9c8cf9e8d811cbbb2da76b55aa1d96b26961af3112be75
6
+ metadata.gz: ccf9c72baa32cdecfe2d1fe8e7b1126ebb9c7e6604eef084d59ec478b34ad565912f8ebf648dadecf2cd4208441abe9cdfc31781a3f7460d542de395ee98e596
7
+ data.tar.gz: 5dbd7080945c3d1d47f4b19c488eb36a2cf60e71a28803344fc8f81d4054d42fa0cbe93929260d2e1709dd7f213c015188b8d209e34763de63a36d49b93f3e18
data/.rubocop.yml CHANGED
@@ -35,6 +35,9 @@ Style/TrailingCommaInArguments:
35
35
  Style/SafeNavigation:
36
36
  Enabled: false
37
37
 
38
+ Style/WhileUntilModifier:
39
+ Enabled: false
40
+
38
41
  Naming/PredicateName:
39
42
  NamePrefixBlacklist:
40
43
  - "is_"
data/.travis.yml CHANGED
@@ -1,5 +1,44 @@
1
- sudo: false
2
1
  language: ruby
2
+ cache:
3
+ - bundler
4
+ - apt
5
+ dist: trusty
6
+ sudo: required
7
+ compiler:
8
+ - clang
9
+ addons:
10
+ apt:
11
+ sources:
12
+ - ubuntu-toolchain-r-test
13
+ packages:
14
+ - g++-7
15
+ - autoconf
16
+ - automake
17
+ - autotools-dev
18
+ - libtool
19
+ - pkg-config
20
+ - zlib1g-dev
21
+ - libcunit1-dev
22
+ - libssl-dev
23
+ - libxml2-dev
24
+ - libev-dev
25
+ - libevent-dev
26
+ - libjansson-dev
27
+ - libjemalloc-dev
28
+ - libc-ares-dev
29
+ - cmake
30
+ - cmake-data
3
31
  rvm:
4
- - 2.4.3
5
- before_install: gem install bundler -v 1.16.0
32
+ - ruby-head
33
+ - 2.5.3
34
+ - 2.4.5
35
+ - 2.3.8
36
+ before_install:
37
+ - bin/nghttp2
38
+ - export LD_LIBRARY_PATH=$HOME/lib:$LD_LIBRARY_PATH
39
+ - export PKG_CONFIG_PATH=$HOME/lib/pkgconfig:$PKG_CONFIG_PATH
40
+ - gem install bundler -v 1.16.0
41
+
42
+ matrix:
43
+ allow_failures:
44
+ - rvm: ruby-head
data/README.md CHANGED
@@ -1,8 +1,11 @@
1
1
  # GrpcKit
2
2
 
3
+ [![Build Status](https://travis-ci.org/ganmacs/grpc_kit.svg?branch=master)](https://travis-ci.org/ganmacs/grpc_kit)
4
+ [![Gem Version](https://badge.fury.io/rb/grpc_kit.svg)](https://badge.fury.io/rb/grpc_kit)
5
+
3
6
  __UNDER DEVELOPMENT__
4
7
 
5
- A kit for creating [gRPC](https://grpc.io/) server/client.
8
+ A kit for creating [gRPC](https://grpc.io/) server/client in Ruby.
6
9
 
7
10
  ## Installation
8
11
 
data/TODO.md ADDED
@@ -0,0 +1,64 @@
1
+ ## Features
2
+
3
+ ### request response
4
+
5
+ - [x] recv/send msg
6
+ - [x] metadata (client)
7
+ - [x] metadata (server)
8
+ - [x] interceptor (client)
9
+ - [x] interceptor (server)
10
+ - [x] deadline (client)
11
+ - [x] deadline (server)
12
+
13
+ ### server streamer
14
+
15
+ - [x] recv/send msg
16
+ - [ ] metadata (client)
17
+ - [ ] metadata (server)
18
+ - [x] interceptor (client)
19
+ - [x] interceptor (server)
20
+ - [ ] deadline (client)
21
+ - [ ] deadline (server)
22
+
23
+ ### client streamer
24
+
25
+ - [x] recv/send msg
26
+ - [ ] metadata (client)
27
+ - [ ] metadata (server)
28
+ - [x] interceptor (client)
29
+ - [x] interceptor (server)
30
+ - [ ] deadline (client)
31
+ - [ ] deadline (server)
32
+
33
+ ### bidi_streamer
34
+
35
+ - [ ] recv/send msg
36
+ - [ ] metadata (client)
37
+ - [ ] metadata (server)
38
+ - [ ] interceptor (client)
39
+ - [ ] interceptor (server)
40
+ - [ ] deadline (client)
41
+ - [ ] deadline (server)
42
+
43
+ ## Error handling
44
+
45
+ - [x] resouce exhausted (body size is to large)
46
+ - [x] internal
47
+ - [ ] resouce exhausted (worker is exhausted)
48
+ - [ ] duration parse in header
49
+ - [ ] send `grpc-status` along with header frame if possible
50
+ - need to support https://nghttp2.org/documentation/nghttp2_submit_response.html, data_prd is not NULL
51
+ - [x] unimplemented error
52
+ - [ ] goaway
53
+ - [ ] cancel
54
+ - [ ] support h2's header continuation
55
+
56
+ ## Others
57
+
58
+ - [x] multi thread (griffin)
59
+ - [x] mutli process (griffin)
60
+ - [ ] connection persistent (client, griffin)
61
+ - [ ] send metadata in trailrs frame
62
+ - [ ] add server request spec
63
+ - [ ] add client request spec
64
+ - [ ] handle RST FRAME
data/bin/nghttp2 ADDED
@@ -0,0 +1,11 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ VERSION=1.33.0
6
+
7
+ curl -sSfLO https://github.com/nghttp2/nghttp2/releases/download/v"$VERSION"/nghttp2-"$VERSION".tar.gz
8
+ tar xf nghttp2-"$VERSION".tar.gz
9
+ cd nghttp2-"$VERSION"
10
+ ./configure --prefix="$HOME" --enable-lib-only
11
+ make && make install
data/grpc_kit.gemspec CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency 'googleapis-common-protos-types', '~> 1.0.2'
28
28
 
29
29
  spec.add_development_dependency 'bundler'
30
- spec.add_development_dependency 'grpc-tools'
30
+ spec.add_development_dependency 'grpc-tools', '~> 1.15.0'
31
31
  spec.add_development_dependency 'pry-byebug'
32
32
  spec.add_development_dependency 'rake'
33
33
  spec.add_development_dependency 'rspec'
@@ -5,31 +5,70 @@ require 'grpc_kit/status_codes'
5
5
  module GrpcKit
6
6
  module Errors
7
7
  # https://github.com/grpc/grpc/blob/23b5b1a5a9c7084c5b64d4998ee15af0f77bd589/doc/statuscodes.md
8
+
9
+ def self.from_status_code(code, message)
10
+ CODES.fetch(code).new(message)
11
+ end
12
+
8
13
  class BadStatus < StandardError
9
- def initialize(code, message)
10
- super("#{code} #{message}")
14
+ attr_reader :code, :reason
15
+
16
+ def initialize(code, reason)
11
17
  @code = code
12
- @message = message
18
+ @reason = reason
19
+ super("[#{GrpcKit::StatusCodes::CODE_NAME[code]}] #{reason}")
20
+ end
21
+ end
22
+
23
+ class Unknown < BadStatus
24
+ def initialize(mesage)
25
+ super(GrpcKit::StatusCodes::UNKNOWN, mesage)
13
26
  end
14
27
  end
15
28
 
16
- class DeadlienExceeded < BadStatus
17
- def initialize(msg)
18
- super(
19
- GrpcKit::StatusCodes::DEADLINE_EXCEEDED,
20
- msg.to_s,
21
- # "Deadline expires before server returns status: #{msg}"
22
- )
29
+ class DeadlineExceeded < BadStatus
30
+ def initialize(mesage)
31
+ super(GrpcKit::StatusCodes::DEADLINE_EXCEEDED, mesage)
23
32
  end
24
33
  end
25
34
 
26
35
  class Unimplemented < BadStatus
27
- def initialize(name)
28
- super(
29
- GrpcKit::StatusCodes::UNIMPLEMENTED,
30
- "Method not found at server: #{name}"
31
- )
36
+ def initialize(mesage)
37
+ super(GrpcKit::StatusCodes::UNIMPLEMENTED, mesage)
32
38
  end
33
39
  end
40
+
41
+ class ResourceExhausted < BadStatus
42
+ def initialize(mesage)
43
+ super(GrpcKit::StatusCodes::RESOURCE_EXHAUSTED, mesage)
44
+ end
45
+ end
46
+
47
+ class Internal < BadStatus
48
+ def initialize(mesage)
49
+ super(GrpcKit::StatusCodes::INTERNAL, mesage)
50
+ end
51
+ end
52
+
53
+ CODES = {
54
+ # GrpcKit::StatusCode::OK => 'OK',
55
+ # GrpcKit::StatusCode::CANCELLED => 'CANCELLED',
56
+ GrpcKit::StatusCodes::UNKNOWN => Unknown,
57
+ # GrpcKit::StatusCode::INVALID_ARGUMENT => 'INVALID_ARGUMENT',
58
+ GrpcKit::StatusCodes::DEADLINE_EXCEEDED => DeadlineExceeded,
59
+ # GrpcKit::StatusCode::NOT_FOUND => 'NOT_FOUND',
60
+ # GrpcKit::StatusCode::ALREADY_EXISTS => 'ALREADY_EXISTS',
61
+ # GrpcKit::StatusCode::PERMISSION_DENIED => 'PERMISSION_DENIED',
62
+ GrpcKit::StatusCodes::RESOURCE_EXHAUSTED => ResourceExhausted,
63
+ # GrpcKit::StatusCode::FAILED_PRECONDITION => 'FAILED_PRECONDITION',
64
+ # GrpcKit::StatusCode::ABORTED => 'ABORTED',
65
+ # GrpcKit::StatusCode::OUT_OF_RANGE => 'OUT_OF_RANGE',
66
+ GrpcKit::StatusCodes::UNIMPLEMENTED => Unimplemented,
67
+ GrpcKit::StatusCodes::INTERNAL => Internal,
68
+ # GrpcKit::StatusCode::UNAVAILABLE => 'UNAVAILABLE',
69
+ # GrpcKit::StatusCode::DATA_LOSS => 'DATA_LOSS',
70
+ # GrpcKit::StatusCode::UNAUTHENTICATED => 'UNAUTHENTICATED',
71
+ # GrpcKit::StatusCode::DO_NOT_USE => 'DO_NOT_USE',
72
+ }.freeze
34
73
  end
35
74
  end
@@ -39,7 +39,7 @@ module GrpcKit
39
39
  rpc_descs[rpc_desc.path] = rpc_desc
40
40
 
41
41
  define_method(rpc_desc.ruby_style_name) do |_, _|
42
- raise GrpcKit::Errors::Unimplemented, name.to_s
42
+ raise GrpcKit::Errors::Unimplemented, "Method not found: #{name}"
43
43
  end
44
44
  end
45
45
 
@@ -8,11 +8,11 @@ module GrpcKit
8
8
  class ClientStreamer < Streaming
9
9
  private
10
10
 
11
- def invoke(interceptor, call)
11
+ def invoke(interceptor, call, metadata)
12
12
  # We don't need a `:requests` parameter but,
13
13
  # it shuoldn't remove from paramters due to having a compatibility of grpc gem.
14
- interceptor.client_streamer(requests: nil, call: call, method: call.method, metadata: nil) do |s|
15
- yield(s)
14
+ interceptor.client_streamer(requests: nil, call: call, method: call.method, metadata: metadata) do
15
+ yield(call, metadata)
16
16
  end
17
17
  end
18
18
  end
@@ -21,8 +21,8 @@ module GrpcKit
21
21
  module Server
22
22
  class ClientStreamer < Streaming
23
23
  def invoke(interceptor, call)
24
- interceptor.client_streamer(call: call, method: call.method) do |s|
25
- yield(s)
24
+ interceptor.client_streamer(call: call, method: call.method) do
25
+ yield(call)
26
26
  end
27
27
  end
28
28
  end
@@ -8,11 +8,11 @@ module GrpcKit
8
8
  class ServerStreamer < Streaming
9
9
  private
10
10
 
11
- def invoke(interceptor, call)
11
+ def invoke(interceptor, call, metadata)
12
12
  # We don't need a `:request` parameter but,
13
13
  # it shuoldn't remove from paramters due to having a compatibility of grpc gem.
14
- interceptor.server_streamer(request: nil, call: call, method: call.method, metadata: nil) do |s|
15
- yield(s)
14
+ interceptor.server_streamer(request: nil, call: call, method: call.method, metadata: metadata) do
15
+ yield(call, metadata)
16
16
  end
17
17
  end
18
18
  end
@@ -23,8 +23,8 @@ module GrpcKit
23
23
  def invoke(interceptor, call)
24
24
  # We don't need a `:request` parameter but,
25
25
  # it shuoldn't remove from paramters due to having a compatibility of grpc gem.
26
- interceptor.server_streamer(request: nil, call: call, method: call.method) do |s|
27
- yield(s)
26
+ interceptor.server_streamer(request: nil, call: call, method: call.method) do
27
+ yield(call)
28
28
  end
29
29
  end
30
30
  end
@@ -11,25 +11,25 @@ module GrpcKit
11
11
  @interceptors = nil
12
12
  end
13
13
 
14
- def intercept(call, &block)
14
+ def intercept(call, metadata, &block)
15
15
  if @interceptors && !@interceptors.empty?
16
- do_intercept(@interceptors.dup, call, &block)
16
+ do_intercept(@interceptors.dup, call, metadata, &block)
17
17
  else
18
- yield(call)
18
+ yield(call, metadata)
19
19
  end
20
20
  end
21
21
 
22
22
  private
23
23
 
24
- def do_intercept(interceptors, call)
24
+ def do_intercept(interceptors, call, metadata)
25
25
  if interceptors.empty?
26
- return yield(call)
26
+ return yield(call, metadata)
27
27
  end
28
28
 
29
29
  interceptor = interceptors.pop
30
- invoke(interceptor, call) do |inter_call|
31
- do_intercept(interceptors, inter_call) do |c|
32
- yield(c)
30
+ invoke(interceptor, call, metadata) do |inter_call, meta|
31
+ do_intercept(interceptors, inter_call, meta) do |c, m|
32
+ yield(c, m)
33
33
  end
34
34
  end
35
35
  end
@@ -7,9 +7,9 @@ module GrpcKit
7
7
  module Client
8
8
  class ClientStreamer < Base
9
9
  def invoke(session, _request, authority:, metadata: {}, timeout: nil, **opts)
10
- cs = GrpcKit::Streams::Client.new(path: @config.path, protobuf: @config.protobuf, session: session, authority: authority)
10
+ cs = GrpcKit::Streams::Client.new(config: @config, session: session, authority: authority)
11
11
  call = GrpcKit::Rpcs::Call.new(metadata, @config.method_name, @config.service_name, cs)
12
- @config.interceptor.intercept(call) do |s|
12
+ @config.interceptor.intercept(call, metadata) do |s|
13
13
  s
14
14
  end
15
15
  end
@@ -19,7 +19,7 @@ module GrpcKit
19
19
  module Server
20
20
  class ClientStreamer < Base
21
21
  def invoke(stream, session)
22
- ss = GrpcKit::Streams::Server.new(stream: stream, protobuf: @config.protobuf, session: session)
22
+ ss = GrpcKit::Streams::Server.new(stream: stream, session: session, config: @config)
23
23
  call = GrpcKit::Rpcs::Call.new(stream.headers.metadata, @config.method_name, @config.service_name, ss)
24
24
 
25
25
  if @config.interceptor
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'grpc_kit/status_codes'
4
+
5
+ module GrpcKit
6
+ module Rpcs
7
+ module Client
8
+ class Error
9
+ # def invoke(session, request, authority:, error)
10
+ # end
11
+ end
12
+ end
13
+
14
+ module Server
15
+ class Error
16
+ def send_bad_status(stream, session, bad_status)
17
+ ss = GrpcKit::Streams::Server.new(stream: stream, protobuf: nil, session: session)
18
+ ss.send_status(status: bad_status.code, msg: bad_status.grpc_message)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,19 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'grpc_kit/rpcs/base'
4
+ require 'grpc_kit/status_codes'
4
5
 
5
6
  module GrpcKit
6
7
  module Rpcs
7
8
  module Client
8
9
  class RequestResponse < Base
9
10
  def invoke(session, request, authority:, metadata: {}, timeout: nil, **opts)
10
- cs = GrpcKit::Streams::Client.new(path: @config.path, protobuf: @config.protobuf, session: session, authority: authority)
11
+ cs = GrpcKit::Streams::Client.new(config: @config, session: session, authority: authority)
11
12
 
12
13
  call = GrpcKit::Rpcs::Call.new(metadata, @config.method_name, @config.service_name, cs)
13
14
  @config.interceptor.intercept(request, call, metadata) do |r, c, m|
14
15
  if timeout
15
16
  # XXX: when timeout.to_timeout is 0
16
- Timeout.timeout(timeout.to_timeout, GrpcKit::Errors::DeadlienExceeded) do
17
+ Timeout.timeout(timeout.to_timeout, GrpcKit::Errors::DeadlineExceeded) do
17
18
  c.send_msg(r, timeout: timeout.to_s, metadata: m, last: true)
18
19
  c.recv(last: true)
19
20
  end
@@ -29,10 +30,23 @@ module GrpcKit
29
30
  module Server
30
31
  class RequestResponse < Base
31
32
  def invoke(stream, session)
32
- ss = GrpcKit::Streams::Server.new(stream: stream, protobuf: @config.protobuf, session: session)
33
+ ss = GrpcKit::Streams::Server.new(stream: stream, session: session, config: @config)
33
34
  call = GrpcKit::Rpcs::Call.new(stream.headers.metadata, @config.method_name, @config.service_name, ss)
34
35
 
36
+ begin
37
+ do_invoke(ss, call)
38
+ rescue GrpcKit::Errors::BadStatus => e
39
+ ss.send_status(status: e.code, msg: e.reason, metadata: {}) # TODO: metadata should be set
40
+ rescue StandardError => e
41
+ ss.send_status(status: GrpcKit::StatusCodes::UNKNOWN, msg: e.message, metadata: {})
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def do_invoke(ss, call)
35
48
  request = ss.recv(last: true)
49
+
36
50
  resp =
37
51
  if @config.interceptor
38
52
  @config.interceptor.intercept(request, call) do |req, c|
@@ -7,11 +7,11 @@ module GrpcKit
7
7
  module Client
8
8
  class ServerStreamer < Base
9
9
  def invoke(session, request, authority:, metadata: {}, timeout: nil, **opts)
10
- cs = GrpcKit::Streams::Client.new(path: @config.path, protobuf: @config.protobuf, session: session, authority: authority)
10
+ cs = GrpcKit::Streams::Client.new(config: @config, session: session, authority: authority)
11
11
  call = GrpcKit::Rpcs::Call.new(metadata, @config.method_name, @config.service_name, cs)
12
12
 
13
- @config.interceptor.intercept(call) do |c|
14
- c.send_msg(request, last: true)
13
+ @config.interceptor.intercept(call, metadata) do |c, m|
14
+ c.send_msg(request, metadata: m, last: true)
15
15
  c
16
16
  end
17
17
  end
@@ -21,7 +21,7 @@ module GrpcKit
21
21
  module Server
22
22
  class ServerStreamer < Base
23
23
  def invoke(stream, session)
24
- ss = GrpcKit::Streams::Server.new(stream: stream, protobuf: @config.protobuf, session: session)
24
+ ss = GrpcKit::Streams::Server.new(stream: stream, session: session, config: @config)
25
25
  call = GrpcKit::Rpcs::Call.new(stream.headers.metadata, @config.method_name, @config.service_name, ss)
26
26
 
27
27
  if @config.interceptor
@@ -34,7 +34,7 @@ module GrpcKit
34
34
  @handler.send(@config.ruby_style_method_name, request, call)
35
35
  end
36
36
 
37
- stream.end_write
37
+ ss.send_trailer
38
38
  end
39
39
  end
40
40
  end
data/lib/grpc_kit/rpcs.rb CHANGED
@@ -4,6 +4,7 @@ require 'grpc_kit/rpcs/request_response'
4
4
  require 'grpc_kit/rpcs/client_streamer'
5
5
  require 'grpc_kit/rpcs/server_streamer'
6
6
  require 'grpc_kit/rpcs/bidi_streamer'
7
+ require 'grpc_kit/rpcs/error'
7
8
 
8
9
  module GrpcKit
9
10
  module Rpcs
@@ -8,8 +8,11 @@ module GrpcKit
8
8
  def initialize(interceptors: [])
9
9
  @sessions = []
10
10
  @rpc_descs = {}
11
+ @error_rpc = GrpcKit::Rpcs::Server::Error.new
11
12
  @interceptors = interceptors
12
13
  @mutex = Mutex.new
14
+
15
+ GrpcKit.logger.debug("Launched grpc_kit(v#{GrpcKit::VERSION})")
13
16
  end
14
17
 
15
18
  # @params handler [object]
@@ -24,7 +27,6 @@ module GrpcKit
24
27
  end
25
28
 
26
29
  def run(conn)
27
- GrpcKit.logger.debug("Run grpc_kit(v#{GrpcKit::VERSION})")
28
30
  establish_session(conn) do |s|
29
31
  s.submit_settings([])
30
32
  s.start
@@ -42,7 +44,7 @@ module GrpcKit
42
44
  def dispatch(stream, session)
43
45
  rpc = @rpc_descs[stream.headers.path]
44
46
  unless rpc
45
- raise "Unkown path #{path}"
47
+ return @error_rpc.send_bad_status(stream, session, GrpcKit::Errors::Unimplemented.new(stream.headers.path))
46
48
  end
47
49
 
48
50
  rpc.invoke(stream, session)
@@ -10,27 +10,30 @@ module GrpcKit
10
10
  @end_read = false
11
11
  @end_write = false
12
12
  @finish = false
13
- @write_byte_size = 0
14
13
  end
15
14
 
16
15
  def write(data, last: false)
16
+ return 0 if data.empty?
17
+
17
18
  end_write if last
18
- @write_byte_size += data.size
19
19
 
20
20
  if @buffer
21
21
  @buffer << data
22
22
  else
23
- @buffer = data
23
+ @buffer = data.dup
24
24
  end
25
+
26
+ data.bytesize
25
27
  end
26
28
 
27
29
  def read(len = nil, last: false)
28
- end_read if last
29
-
30
- if @buffer.nil?
30
+ if @buffer.nil? || @buffer.empty?
31
31
  return ''
32
32
  end
33
33
 
34
+ end_read if last
35
+
36
+ # TODO: more efficient code
34
37
  if len
35
38
  @buffer.slice!(0...len)
36
39
  else
@@ -33,7 +33,7 @@ module GrpcKit
33
33
  stream = @streams.fetch(stream_id)
34
34
 
35
35
  loop do
36
- if (!want_read? && !want_write?) || stream.end_stream?
36
+ if (!want_read? && !want_write?) || stream.close?
37
37
  break
38
38
  end
39
39
 
@@ -81,7 +81,7 @@ module GrpcKit
81
81
  stream = @streams[frame.stream_id]
82
82
 
83
83
  if frame.end_stream?
84
- stream.remote_end_stream = true
84
+ stream.close_remote
85
85
  end
86
86
 
87
87
  unless stream.inflight
@@ -92,7 +92,7 @@ module GrpcKit
92
92
  stream = @streams[frame.stream_id]
93
93
 
94
94
  if frame.end_stream?
95
- stream.remote_end_stream = true
95
+ stream.close_remote
96
96
  end
97
97
 
98
98
  # when DS9::Frames::Goaway
@@ -109,7 +109,7 @@ module GrpcKit
109
109
  when DS9::Frames::Data, DS9::Frames::Headers
110
110
  stream = @streams[frame.stream_id]
111
111
  if frame.end_stream?
112
- stream.local_end_stream = true
112
+ stream.close_local
113
113
  end
114
114
  end
115
115
 
@@ -122,7 +122,7 @@ module GrpcKit
122
122
  stream = @streams.delete(stream_id)
123
123
  return unless stream
124
124
 
125
- stream.end_stream
125
+ stream.close
126
126
  end
127
127
 
128
128
  # nghttp2_session_callbacks_set_on_data_chunk_recv_callback
@@ -137,9 +137,12 @@ module GrpcKit
137
137
  # def on_frame_not_send(frame, reason)
138
138
  # end
139
139
 
140
- # # for nghttp2_session_callbacks_set_on_header_callback
141
- # def on_header(name, value, frame, flags)
142
- # end
140
+ # for nghttp2_session_callbacks_set_on_header_callback
141
+ def on_header(name, value, frame, _flags)
142
+ GrpcKit.logger.debug("#{name} => #{value}")
143
+ stream = @streams[frame.stream_id]
144
+ stream.add_header(name, value)
145
+ end
143
146
 
144
147
  # # for nghttp2_session_callbacks_set_on_begin_headers_callback
145
148
  # def on_begin_header(name, value, frame, flags)
@@ -12,6 +12,7 @@ module GrpcKit
12
12
 
13
13
  # @params val [String]
14
14
  def self.decode(value)
15
+ value = value.dup
15
16
  size = value.size
16
17
  if size < 2
17
18
  raise "Invalid format: too short #{value}"
@@ -36,19 +36,18 @@ module GrpcKit
36
36
  when ':path'
37
37
  self.path = val
38
38
  when ':status'
39
- self.http_status = val.to_i
39
+ self.http_status = Integer(val)
40
40
  when 'content-type'
41
41
  # TODO
42
42
  metadata[key] = val
43
43
  when 'grpc-encoding'
44
44
  self.grpc_encoding = val
45
45
  when 'grpc-status'
46
- self.grpc_status = val.to_i
46
+ self.grpc_status = val
47
47
  when 'grpc-timeout'
48
48
  self.timeout = Duration.decode(val)
49
49
  when 'grpc-message'
50
- # TODO
51
- GrpcKit.logger.warn('grpc-message is unsupported header now')
50
+ self.status_message = val
52
51
  when 'grpc-status-details-bin'
53
52
  # TODO
54
53
  GrpcKit.logger.warn('grpc-status-details-bin is unsupported header now')