changed README.md
 
@@ -90,12 90,20 @@ end
90
90
91
91
If you plan to use the HTTP(S) server, you also need to add `plug` and `cowboy` to your deps/apps.
92
92
93
For Cowboy 1.x
93
94
```elixir
94
95
def deps do
95
96
[..., {:plug, "~> 1.3"}, {:cowboy, "~> 1.1"}]
96
97
end
97
98
```
98
99
100
For Cowboy 2.x
101
```elixir
102
def deps do
103
[..., {:plug, "~> 1.3"}, {:cowboy, "~> 2.4"}]
104
end
105
```
106
99
107
```elixir
100
108
def application do
101
109
[applications: [..., :plug, :cowboy]]
changed hex_metadata.config
 
@@ -3,12 3,17 @@
3
3
{<<"description">>,<<"JSON-RPC 2.0 for Elixir.">>}.
4
4
{<<"elixir">>,<<"~> 1.3">>}.
5
5
{<<"files">>,
6
- [<<"mix.exs">>,<<"README.md">>,<<"LICENSE">>,<<"lib/jsonrpc2.ex">>,
7
- <<"lib/jsonrpc2/clients/http.ex">>,<<"lib/jsonrpc2/clients/tcp.ex">>,
6
[<<"mix.exs">>,<<"README.md">>,<<"LICENSE">>,<<"lib">>,<<"lib/jsonrpc2">>,
7
<<"lib/jsonrpc2.ex">>,<<"lib/jsonrpc2/clients">>,
8
<<"lib/jsonrpc2/clients/http.ex">>,<<"lib/jsonrpc2/clients/tcp">>,
9
<<"lib/jsonrpc2/clients/tcp.ex">>,
8
10
<<"lib/jsonrpc2/clients/tcp/protocol.ex">>,<<"lib/jsonrpc2/request.ex">>,
9
- <<"lib/jsonrpc2/response.ex">>,<<"lib/jsonrpc2/serializers/jiffy.ex">>,
10
- <<"lib/jsonrpc2/server/handler.ex">>,<<"lib/jsonrpc2/servers/http.ex">>,
11
- <<"lib/jsonrpc2/servers/http/plug.ex">>,<<"lib/jsonrpc2/servers/tcp.ex">>,
11
<<"lib/jsonrpc2/response.ex">>,<<"lib/jsonrpc2/serializers">>,
12
<<"lib/jsonrpc2/serializers/jiffy.ex">>,<<"lib/jsonrpc2/server">>,
13
<<"lib/jsonrpc2/server/handler.ex">>,<<"lib/jsonrpc2/servers">>,
14
<<"lib/jsonrpc2/servers/http">>,<<"lib/jsonrpc2/servers/http.ex">>,
15
<<"lib/jsonrpc2/servers/http/plug.ex">>,<<"lib/jsonrpc2/servers/tcp">>,
16
<<"lib/jsonrpc2/servers/tcp.ex">>,
12
17
<<"lib/jsonrpc2/servers/tcp/protocol.ex">>]}.
13
18
{<<"licenses">>,[<<"Apache 2.0">>]}.
14
19
{<<"links">>,
 
@@ -36,6 41,11 @@
36
41
{<<"optional">>,true},
37
42
{<<"repository">>,<<"hexpm">>},
38
43
{<<"requirement">>,<<"~> 1.6">>}],
44
[{<<"app">>,<<"cowboy">>},
45
{<<"name">>,<<"cowboy">>},
46
{<<"optional">>,true},
47
{<<"repository">>,<<"hexpm">>},
48
{<<"requirement">>,<<"~> 1.1 or ~> 2.4">>}],
39
49
[{<<"app">>,<<"plug">>},
40
50
{<<"name">>,<<"plug">>},
41
51
{<<"optional">>,true},
 
@@ -46,4 56,4 @@
46
56
{<<"optional">>,true},
47
57
{<<"repository">>,<<"hexpm">>},
48
58
{<<"requirement">>,<<"~> 0.3">>}]]}.
49
- {<<"version">>,<<"1.0.3">>}.
59
{<<"version">>,<<"1.1.0">>}.
changed lib/jsonrpc2.ex
 
@@ -141,22 141,22 @@ defmodule JSONRPC2 do
141
141
"""
142
142
143
143
@typedoc "A JSON-RPC 2.0 method."
144
- @type method :: String.t
144
@type method :: String.t()
145
145
146
146
@typedoc "A decoded JSON object."
147
147
@type json ::
148
- nil |
149
- true |
150
- false |
151
- float |
152
- integer |
153
- String.t |
154
- [json] |
155
- %{optional(String.t) => json}
148
nil
149
| true
150
| false
151
| float
152
| integer
153
| String.t()
154
| [json]
155
| %{optional(String.t()) => json}
156
156
157
157
@typedoc "A JSON-RPC 2.0 params value."
158
- @type params :: [json] | %{optional(String.t) => json}
158
@type params :: [json] | %{optional(String.t()) => json}
159
159
160
160
@typedoc "A JSON-RPC 2.0 request ID."
161
- @type id :: String.t | number
161
@type id :: String.t() | number
162
162
end
changed lib/jsonrpc2/clients/http.ex
 
@@ -3,7 3,7 @@ defmodule JSONRPC2.Clients.HTTP do
3
3
A client for JSON-RPC 2.0 using an HTTP transport with JSON in the body.
4
4
"""
5
5
6
- @type batch_result :: {:ok, JSONRPC2.Response.id_and_response} | {:error, any}
6
@type batch_result :: {:ok, JSONRPC2.Response.id_and_response()} | {:error, any}
7
7
8
8
@doc """
9
9
Make a call to `url` for JSON-RPC 2.0 `method` with `params`.
 
@@ -13,8 13,8 @@ defmodule JSONRPC2.Clients.HTTP do
13
13
14
14
See [hackney](https://github.com/benoitc/hackney) for more information on the available options.
15
15
"""
16
- @spec call(String.t, JSONRPC2.method, JSONRPC2.params, any, atom, list) ::
17
- {:ok, any} | {:error, any}
16
@spec call(String.t(), JSONRPC2.method(), JSONRPC2.params(), any, atom, list) ::
17
{:ok, any} | {:error, any}
18
18
def call(url, method, params, headers \\ [], http_method \\ :post, hackney_opts \\ []) do
19
19
serializer = Application.get_env(:jsonrpc2, :serializer)
20
20
{:ok, payload} = JSONRPC2.Request.serialized_request({method, params, 0}, serializer)
 
@@ -46,8 46,7 @@ defmodule JSONRPC2.Clients.HTTP do
46
46
47
47
See [hackney](https://github.com/benoitc/hackney) for more information on the available options.
48
48
"""
49
- @spec notify(String.t, JSONRPC2.method, JSONRPC2.params, any, atom, list) ::
50
- :ok | {:error, any}
49
@spec notify(String.t(), JSONRPC2.method(), JSONRPC2.params(), any, atom, list) :: :ok | {:error, any}
51
50
def notify(url, method, params, headers \\ [], http_method \\ :post, hackney_opts \\ []) do
52
51
serializer = Application.get_env(:jsonrpc2, :serializer)
53
52
{:ok, payload} = JSONRPC2.Request.serialized_request({method, params}, serializer)
 
@@ -67,10 66,11 @@ defmodule JSONRPC2.Clients.HTTP do
67
66
68
67
See [hackney](https://github.com/benoitc/hackney) for more information on the available options.
69
68
"""
70
- @spec batch(String.t, [JSONRPC2.Request.request], any, atom, list) ::
71
- [batch_result] | :ok | {:error, any}
69
@spec batch(String.t(), [JSONRPC2.Request.request()], any, atom, list) ::
70
[batch_result] | :ok | {:error, any}
72
71
def batch(url, requests, headers \\ [], http_method \\ :post, hackney_opts \\ []) do
73
72
serializer = Application.get_env(:jsonrpc2, :serializer)
73
74
74
{:ok, payload} =
75
75
Enum.map(requests, &JSONRPC2.Request.request/1)
76
76
|> serializer.encode()
changed lib/jsonrpc2/clients/tcp.ex
 
@@ -7,13 7,13 @@ defmodule JSONRPC2.Clients.TCP do
7
7
8
8
@default_timeout 5_000
9
9
10
- @type host :: binary | :inet.socket_address | :inet.hostname
10
@type host :: binary | :inet.socket_address() | :inet.hostname()
11
11
12
12
@type request_id :: any
13
13
14
14
@type call_option ::
15
- {:string_id, boolean} |
16
- {:timeout, pos_integer}
15
{:string_id, boolean}
16
| {:timeout, pos_integer}
17
17
18
18
@type call_options :: [call_option]
19
19
 
@@ -26,7 26,7 @@ defmodule JSONRPC2.Clients.TCP do
26
26
[here](https://github.com/lpgauth/shackle#client_options), as well as `pool_opts`, detailed
27
27
[here](https://github.com/lpgauth/shackle#pool_options).
28
28
"""
29
- @spec start(host, :inet.port_number, atom, Keyword.t, Keyword.t) :: :ok
29
@spec start(host, :inet.port_number(), atom, Keyword.t(), Keyword.t()) :: :ok
30
30
def start(host, port, name, client_opts \\ [], pool_opts \\ []) do
31
31
host = if is_binary(host), do: to_charlist(host), else: host
32
32
 
@@ -37,7 37,9 @@ defmodule JSONRPC2.Clients.TCP do
37
37
{:ok, ip} -> ip
38
38
{:error, :einval} -> host
39
39
end
40
- host -> host
40
41
host ->
42
host
41
43
end
42
44
43
45
client_opts = Keyword.merge([ip: ip, port: port, socket_options: [:binary, packet: :line]], client_opts)
 
@@ -63,10 65,10 @@ defmodule JSONRPC2.Clients.TCP do
63
65
For backwards compatibility reasons, you may also provide a boolean for the `options` parameter,
64
66
which will set `string_id` to the given boolean.
65
67
"""
66
- @spec call(atom, JSONRPC2.method, JSONRPC2.params, boolean | call_options) :: {:ok, any} | {:error, any}
68
@spec call(atom, JSONRPC2.method(), JSONRPC2.params(), boolean | call_options) ::
69
{:ok, any} | {:error, any}
67
70
def call(name, method, params, options \\ [])
68
71
69
-
70
72
def call(name, method, params, string_id) when is_boolean(string_id) do
71
73
call(name, method, params, string_id: string_id)
72
74
end
 
@@ -95,8 97,8 @@ defmodule JSONRPC2.Clients.TCP do
95
97
For backwards compatibility reasons, you may also provide a boolean for the `options` parameter,
96
98
which will set `string_id` to the given boolean.
97
99
"""
98
- @spec cast(atom, JSONRPC2.method, JSONRPC2.params, boolean | cast_options) ::
99
- {:ok, request_id} | {:error, :backlog_full}
100
@spec cast(atom, JSONRPC2.method(), JSONRPC2.params(), boolean | cast_options) ::
101
{:ok, request_id} | {:error, :backlog_full}
100
102
def cast(name, method, params, options \\ [])
101
103
102
104
def cast(name, method, params, string_id) when is_boolean(string_id) do
 
@@ -124,8 126,7 @@ defmodule JSONRPC2.Clients.TCP do
124
126
125
127
This function returns a `request_id`, but it should not be used with `receive_response/1`.
126
128
"""
127
- @spec notify(atom, JSONRPC2.method, JSONRPC2.params) ::
128
- {:ok, request_id} | {:error, :backlog_full}
129
@spec notify(atom, JSONRPC2.method(), JSONRPC2.params()) :: {:ok, request_id} | {:error, :backlog_full}
129
130
def notify(name, method, params) do
130
131
:shackle.cast(name, {:notify, method, params}, nil, 0)
131
132
end
changed lib/jsonrpc2/clients/tcp/protocol.ex
 
@@ -45,7 45,9 @@ defmodule JSONRPC2.Clients.TCP.Protocol do
45
45
{:ok, {nil, result}} ->
46
46
_ =
47
47
Logger.error([
48
- inspect(__MODULE__), " received response with null ID: ", inspect(result)
48
inspect(__MODULE__),
49
" received response with null ID: ",
50
inspect(result)
49
51
])
50
52
51
53
{:ok, [], state}
 
@@ -56,7 58,9 @@ defmodule JSONRPC2.Clients.TCP.Protocol do
56
58
{:error, error} ->
57
59
_ =
58
60
Logger.error([
59
- inspect(__MODULE__), " received invalid response, error: ", inspect(error)
61
inspect(__MODULE__),
62
" received invalid response, error: ",
63
inspect(error)
60
64
])
61
65
62
66
{:ok, [], state}
 
@@ -68,6 72,6 @@ defmodule JSONRPC2.Clients.TCP.Protocol do
68
72
end
69
73
70
74
defp external_request_id(request_counter) do
71
- rem(request_counter, 2147483647)
75
rem(request_counter, 2_147_483_647)
72
76
end
73
77
end
changed lib/jsonrpc2/request.ex
 
@@ -4,8 4,8 @@ defmodule JSONRPC2.Request do
4
4
"""
5
5
6
6
@type request ::
7
- {JSONRPC2.method, JSONRPC2.params} |
8
- {JSONRPC2.method, JSONRPC2.params, JSONRPC2.id}
7
{JSONRPC2.method(), JSONRPC2.params()}
8
| {JSONRPC2.method(), JSONRPC2.params(), JSONRPC2.id()}
9
9
10
10
@doc """
11
11
Returns a serialized `request` using `serializer`.
 
@@ -24,7 24,7 @@ defmodule JSONRPC2.Request do
24
24
def request(request)
25
25
26
26
def request({method, params})
27
- when is_binary(method) and (is_list(params) or is_map(params)) do
27
when is_binary(method) and (is_list(params) or is_map(params)) do
28
28
%{
29
29
"jsonrpc" => "2.0",
30
30
"method" => method,
 
@@ -33,7 33,7 @@ defmodule JSONRPC2.Request do
33
33
end
34
34
35
35
def request({method, params, id})
36
- when (is_number(id) or is_binary(id)) do
36
when is_number(id) or is_binary(id) do
37
37
{method, params}
38
38
|> request()
39
39
|> Map.put("id", id)
changed lib/jsonrpc2/response.ex
 
@@ -4,12 4,12 @@ defmodule JSONRPC2.Response do
4
4
"""
5
5
6
6
@type id_and_response ::
7
- {JSONRPC2.id | nil, {:ok, any} | {:error, code :: integer, message :: String.t, data :: any}}
7
{JSONRPC2.id() | nil, {:ok, any} | {:error, code :: integer, message :: String.t(), data :: any}}
8
8
9
9
@doc """
10
10
Deserialize the given `response` using `serializer`.
11
11
"""
12
- @spec deserialize_response(String.t, module) :: {:ok, id_and_response} | {:error, any}
12
@spec deserialize_response(String.t(), module) :: {:ok, id_and_response} | {:error, any}
13
13
def deserialize_response(response, serializer) do
14
14
case serializer.decode(response) do
15
15
{:ok, response} -> id_and_response(response)
changed lib/jsonrpc2/server/handler.ex
 
@@ -46,12 46,12 @@ defmodule JSONRPC2.Server.Handler do
46
46
* `{:jsonrpc2, code, message}` or `{:jsonrpc2, code, message, data}` to return a custom error,
47
47
with or without extra data.
48
48
"""
49
- @callback handle_request(method :: JSONRPC2.method, params :: JSONRPC2.params) ::
50
- JSONRPC2.json | no_return
49
@callback handle_request(method :: JSONRPC2.method(), params :: JSONRPC2.params()) ::
50
JSONRPC2.json() | no_return
51
51
52
52
defmacro __using__(_) do
53
53
quote do
54
- @spec handle(String.t) :: {:reply, String.t} | :noreply
54
@spec handle(String.t()) :: {:reply, String.t()} | :noreply
55
55
def handle(json) do
56
56
serializer = Application.get_env(:jsonrpc2, :serializer)
57
57
 
@@ -61,16 61,10 @@ defmodule JSONRPC2.Server.Handler do
61
61
end
62
62
63
63
@doc false
64
- def handle(module, serializer, json) do
64
def handle(module, serializer, json) when is_binary(json) do
65
65
case serializer.decode(json) do
66
66
{:ok, decoded_request} ->
67
- case parse(decoded_request) do
68
- batch_rpc when is_list(batch_rpc) and length(batch_rpc) > 0 ->
69
- merge_responses(Enum.map(batch_rpc, &dispatch(module, &1)))
70
-
71
- rpc ->
72
- dispatch(module, rpc)
73
- end
67
parse(decoded_request) |> collate_for_dispatch(module)
74
68
75
69
{:error, _error} ->
76
70
standard_error_response(:parse_error, nil)
 
@@ -81,6 75,20 @@ defmodule JSONRPC2.Server.Handler do
81
75
|> encode_response(module, serializer, json)
82
76
end
83
77
78
def handle(module, serializer, json) do
79
parse(json)
80
|> collate_for_dispatch(module)
81
|> encode_response(module, serializer, json)
82
end
83
84
defp collate_for_dispatch(batch_rpc, module) when is_list(batch_rpc) and length(batch_rpc) > 0 do
85
merge_responses(Enum.map(batch_rpc, &dispatch(module, &1)))
86
end
87
88
defp collate_for_dispatch(rpc, module) do
89
dispatch(module, rpc)
90
end
91
84
92
defp parse(requests) when is_list(requests) do
85
93
for request <- requests, do: parse(request)
86
94
end
 
@@ -103,10 111,8 @@ defmodule JSONRPC2.Server.Handler do
103
111
end
104
112
105
113
defp valid_request?(version, method, params, id) do
106
- version == "2.0" and
107
- is_binary(method) and
108
- (is_list(params) or is_map(params)) and
109
- (id in [:undefined, :nil] or is_binary(id) or is_number(id))
114
version == "2.0" and is_binary(method) and (is_list(params) or is_map(params)) and
115
(id in [:undefined, nil] or is_binary(id) or is_number(id))
110
116
end
111
117
112
118
defp merge_responses(responses) do
 
@@ -122,8 128,17 @@ defmodule JSONRPC2.Server.Handler do
122
128
try do
123
129
result_response(module.handle_request(method, params), id)
124
130
rescue
125
- FunctionClauseError ->
126
- standard_error_response(:method_not_found, id)
131
e in FunctionClauseError ->
132
# if that error originates from the very module.handle_request call - handle, otherwise - reraise
133
case e do
134
%FunctionClauseError{function: :handle_request, module: ^module} ->
135
standard_error_response(:method_not_found, %{method: method, params: params}, id)
136
137
other_e ->
138
original_stacktrace = System.stacktrace()
139
log_error(module, method, params, :error, other_e)
140
Kernel.reraise(other_e, original_stacktrace)
141
end
127
142
catch
128
143
:throw, error when error in @throwable_errors ->
129
144
standard_error_response(error, id)
 
@@ -138,11 153,7 @@ defmodule JSONRPC2.Server.Handler do
138
153
error_response(code, message, data, id)
139
154
140
155
kind, payload ->
141
- _ =
142
- Logger.error([
143
- "Error in handler ", inspect(module), " for method ", method, " with params: ",
144
- inspect(params), ":\n\n", Exception.format(kind, payload, System.stacktrace())
145
- ])
156
log_error(module, method, params, kind, payload)
146
157
147
158
standard_error_response(:internal_error, id)
148
159
end
 
@@ -152,16 163,31 @@ defmodule JSONRPC2.Server.Handler do
152
163
standard_error_response(:invalid_request, nil)
153
164
end
154
165
166
defp log_error(module, method, params, kind, payload) do
167
_ =
168
Logger.error([
169
"Error in handler ",
170
inspect(module),
171
" for method ",
172
method,
173
" with params: ",
174
inspect(params),
175
":\n\n",
176
Exception.format(kind, payload, System.stacktrace())
177
])
178
end
179
155
180
defp result_response(_result, :undefined) do
156
181
:noreply
157
182
end
158
183
159
184
defp result_response(result, id) do
160
- {:reply, %{
161
- "jsonrpc" => "2.0",
162
- "result" => result,
163
- "id" => id
164
- }}
185
{:reply,
186
%{
187
"jsonrpc" => "2.0",
188
"result" => result,
189
"id" => id
190
}}
165
191
end
166
192
167
193
defp standard_error_response(error_type, id) do
 
@@ -232,8 258,14 @@ defmodule JSONRPC2.Server.Handler do
232
258
{:error, reason} ->
233
259
_ =
234
260
Logger.info([
235
- "Handler ", inspect(module), " returned invalid reply:\n Reason: ", inspect(reason),
236
- "\n Received: ", inspect(reply), "\n Request: ", json
261
"Handler ",
262
inspect(module),
263
" returned invalid reply:\n Reason: ",
264
inspect(reason),
265
"\n Received: ",
266
inspect(reply),
267
"\n Request: ",
268
json
237
269
])
238
270
239
271
standard_error_response(:internal_error, nil)
changed lib/jsonrpc2/servers/http.ex
 
@@ -6,8 6,7 @@ defmodule JSONRPC2.Servers.HTTP do
6
6
handler within a Plug-based web app (such as Phoenix), please see `JSONRPC2.Servers.HTTP.Plug`.
7
7
"""
8
8
9
- alias Plug.Adapters.Cowboy
10
- alias JSONRPC2.Servers.HTTP.Plug
9
alias JSONRPC2.Servers.HTTP.Plug, as: JSONRPC2Plug
11
10
12
11
@doc """
13
12
Returns a supervisor child spec for the given `handler` via `scheme` with `cowboy_opts`.
 
@@ -20,10 19,10 @@ defmodule JSONRPC2.Servers.HTTP do
20
19
21
20
If the server `ref` is not set in `cowboy_opts`, `handler.HTTP` or `handler.HTTPS` is the default.
22
21
"""
23
- @spec child_spec(:http | :https, module, list) :: Supervisor.Spec.spec
22
@spec child_spec(:http | :https, module, list) :: Supervisor.Spec.spec()
24
23
def child_spec(scheme, handler, cowboy_opts \\ []) do
25
24
cowboy_opts = cowboy_opts [ref: ref(scheme, handler)]
26
- Cowboy.child_spec(scheme, Plug, handler, cowboy_opts)
25
cowboy_adapter().child_spec(scheme, JSONRPC2Plug, handler, cowboy_opts)
27
26
end
28
27
29
28
@doc """
 
@@ -37,7 36,7 @@ defmodule JSONRPC2.Servers.HTTP do
37
36
@spec http(module, list) :: {:ok, pid} | {:error, term}
38
37
def http(handler, cowboy_opts \\ []) do
39
38
cowboy_opts = cowboy_opts [ref: ref(:http, handler)]
40
- Cowboy.http(Plug, handler, cowboy_opts)
39
cowboy_adapter().http(JSONRPC2Plug, handler, cowboy_opts)
41
40
end
42
41
43
42
@doc """
 
@@ -53,7 52,7 @@ defmodule JSONRPC2.Servers.HTTP do
53
52
@spec https(module, list) :: {:ok, pid} | {:error, term}
54
53
def https(handler, cowboy_opts \\ []) do
55
54
cowboy_opts = cowboy_opts [ref: ref(:https, handler)]
56
- Cowboy.https(Plug, handler, cowboy_opts)
55
cowboy_adapter().https(JSONRPC2Plug, handler, cowboy_opts)
57
56
end
58
57
59
58
defp ref(scheme, handler) do
 
@@ -69,6 68,28 @@ defmodule JSONRPC2.Servers.HTTP do
69
68
"""
70
69
@spec shutdown(atom) :: :ok | {:error, :not_found}
71
70
def shutdown(ref) do
72
- Cowboy.shutdown(ref)
71
cowboy_adapter().shutdown(ref)
72
end
73
74
defp cowboy_adapter() do
75
cowboy_spec =
76
Application.loaded_applications()
77
|> List.keyfind(:cowboy, 0)
78
79
if cowboy_spec do
80
cowboy_spec
81
|> elem(2)
82
|> List.to_string()
83
|> Version.parse!()
84
|> Version.match?("~> 2.0")
85
|> case do
86
true -> Plug.Adapters.Cowboy2
87
false -> Plug.Adapters.Cowboy
88
end
89
else
90
:ok = Application.load(:cowboy)
91
92
cowboy_adapter()
93
end
73
94
end
74
95
end
changed lib/jsonrpc2/servers/http/plug.ex
 
@@ -21,7 21,15 @@ defmodule JSONRPC2.Servers.HTTP.Plug do
21
21
22
22
@doc false
23
23
def call(%{method: "POST"} = conn, handler) do
24
- {:ok, req_body, conn} = Plug.Conn.read_body(conn)
24
req_body =
25
cond do
26
Plug.Conn.get_req_header(conn, "content-type")
27
|> Enum.member?("application/json") && conn.params != %{} && conn.params != %Plug.Conn.Unfetched{} ->
28
conn.params
29
30
true ->
31
get_plain_body(conn)
32
end
25
33
26
34
resp_body =
27
35
case handler.handle(req_body) do
 
@@ -38,4 46,9 @@ defmodule JSONRPC2.Servers.HTTP.Plug do
38
46
conn
39
47
|> Plug.Conn.resp(404, "")
40
48
end
49
50
defp get_plain_body(conn) do
51
{:ok, req_body, _} = Plug.Conn.read_body(conn)
52
req_body
53
end
41
54
end
changed lib/jsonrpc2/servers/tcp.ex
 
@@ -20,7 20,7 @@ defmodule JSONRPC2.Servers.TCP do
20
20
* `timeout` - disconnect after this amount of milliseconds without a packet from a client.
21
21
Defaults to 1 hour.
22
22
"""
23
- @spec start_listener(module, :inet.port_number, Keyword.t) :: {:ok, pid}
23
@spec start_listener(module, :inet.port_number(), Keyword.t()) :: {:ok, pid}
24
24
def start_listener(handler, port, opts \\ []) do
25
25
apply(:ranch, :start_listener, ranch_args(handler, port, opts))
26
26
end
 
@@ -41,7 41,7 @@ defmodule JSONRPC2.Servers.TCP do
41
41
* `timeout` - disconnect after this amount of milliseconds without a packet from a client.
42
42
Defaults to 1 hour.
43
43
"""
44
- @spec child_spec(module, :inet.port_number, Keyword.t) :: {:ok, pid}
44
@spec child_spec(module, :inet.port_number(), Keyword.t()) :: {:ok, pid}
45
45
def child_spec(handler, port, opts \\ []) do
46
46
apply(:ranch, :child_spec, ranch_args(handler, port, opts))
47
47
end
changed lib/jsonrpc2/servers/tcp/protocol.ex
 
@@ -25,12 25,12 @@ defmodule JSONRPC2.Servers.TCP.Protocol do
25
25
transport.setopts(socket, active: :once)
26
26
27
27
{:ok, _} =
28
- Task.start fn ->
28
Task.start(fn ->
29
29
case jsonrpc2_handler.handle(data) do
30
30
{:reply, reply} -> transport.send(socket, [reply, "\r\n"])
31
31
:noreply -> :noreply
32
32
end
33
- end
33
end)
34
34
35
35
{:noreply, state, timeout}
36
36
end
 
@@ -47,7 47,10 @@ defmodule JSONRPC2.Servers.TCP.Protocol do
47
47
def handle_info(message, state) do
48
48
_ =
49
49
Logger.info([
50
- inspect(__MODULE__), " with state:\n", inspect(state), "\nreceived unexpected message:\n",
50
inspect(__MODULE__),
51
" with state:\n",
52
inspect(state),
53
"\nreceived unexpected message:\n",
51
54
inspect(message)
52
55
])
changed mix.exs
 
@@ -1,54 1,73 @@
1
1
defmodule JSONRPC2.Mixfile do
2
2
use Mix.Project
3
3
4
- @version "1.0.3"
4
@version "1.1.0"
5
5
6
6
def project do
7
- [app: :jsonrpc2,
8
- version: @version,
9
- elixir: "~> 1.3",
10
- deps: deps(),
11
- elixirc_paths: elixirc_paths(Mix.env),
12
- description: description(),
13
- package: package(),
14
- name: "JSONRPC2",
15
- docs: [source_ref: "v#{@version}", main: "readme",
16
- canonical: "http://hexdocs.pm/jsonrpc2",
17
- source_url: "https://github.com/fanduel/jsonrpc2-elixir",
18
- extras: ["README.md"]],
19
- dialyzer: [plt_add_apps: [:shackle, :ranch, :plug, :hackney]],
20
- xref: [exclude: [Poison, :hackney, :jiffy, :ranch, :shackle, :shackle_pool, Plug.Conn,
21
- Plug.Adapters.Cowboy]]]
7
[
8
app: :jsonrpc2,
9
version: @version,
10
elixir: "~> 1.3",
11
deps: deps(),
12
elixirc_paths: elixirc_paths(Mix.env()),
13
description: description(),
14
package: package(),
15
name: "JSONRPC2",
16
docs: [
17
source_ref: "v#{@version}",
18
main: "readme",
19
canonical: "http://hexdocs.pm/jsonrpc2",
20
source_url: "https://github.com/fanduel/jsonrpc2-elixir",
21
extras: ["README.md"]
22
],
23
dialyzer: [plt_add_apps: [:shackle, :ranch, :plug, :hackney]],
24
xref: [
25
exclude: [
26
Poison,
27
:hackney,
28
:jiffy,
29
:ranch,
30
:shackle,
31
:shackle_pool,
32
Plug.Conn,
33
Plug.Adapters.Cowboy,
34
Plug.Adapters.Cowboy2
35
]
36
]
37
]
22
38
end
23
39
24
40
def application do
25
- [applications: [:logger],
26
- env: [serializer: Poison]]
41
[applications: [:logger], env: [serializer: Poison]]
27
42
end
28
43
29
44
defp deps do
30
- [{:poison, "~> 3.0 or ~> 2.0", optional: true},
31
- {:jiffy, "~> 0.14", optional: true},
32
- {:ranch, "~> 1.2", optional: true},
33
- {:shackle, "~> 0.3", optional: true},
34
- {:plug, "~> 1.1", optional: true},
35
- {:hackney, "~> 1.6", optional: true},
36
- {:cowboy, "~> 1.1", only: :test},
37
- {:ex_doc, "~> 0.12", only: :dev},
38
- {:dialyxir, "~> 0.3", only: :dev}]
45
[
46
{:poison, "~> 3.0 or ~> 2.0", optional: true},
47
{:jiffy, "~> 0.14", optional: true},
48
{:ranch, "~> 1.2", optional: true},
49
{:shackle, "~> 0.3", optional: true},
50
{:plug, "~> 1.1", optional: true},
51
{:hackney, "~> 1.6", optional: true},
52
{:cowboy, "~> 1.1 or ~> 2.4", optional: true},
53
{:ex_doc, "~> 0.12", only: :dev},
54
{:dialyxir, "~> 0.3", only: :dev}
55
]
39
56
end
40
57
41
58
defp elixirc_paths(:test), do: ["lib", "test/support"]
42
- defp elixirc_paths(_), do: ["lib"]
59
defp elixirc_paths(_), do: ["lib"]
43
60
44
61
defp description do
45
62
"JSON-RPC 2.0 for Elixir."
46
63
end
47
64
48
65
defp package do
49
- [maintainers: ["Eric Entin"],
50
- licenses: ["Apache 2.0"],
51
- links: %{"GitHub" => "https://github.com/fanduel/jsonrpc2-elixir"},
52
- files: ~w(mix.exs README.md LICENSE lib)]
66
[
67
maintainers: ["Eric Entin"],
68
licenses: ["Apache 2.0"],
69
links: %{"GitHub" => "https://github.com/fanduel/jsonrpc2-elixir"},
70
files: ~w(mix.exs README.md LICENSE lib)
71
]
53
72
end
54
73
end