Skip to content

Commit 46a3ac8

Browse files
committed
reformat plug.ex
1 parent a445e82 commit 46a3ac8

File tree

1 file changed

+165
-168
lines changed

1 file changed

+165
-168
lines changed

lib/sentry/plug.ex

Lines changed: 165 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -1,210 +1,207 @@
1-
if(
2-
Code.ensure_loaded?(Plug),
3-
do:
4-
defmodule Sentry.Plug do
5-
@default_scrubbed_param_keys ["password", "passwd", "secret"]
6-
@default_scrubbed_header_keys ["authorization", "authentication"]
7-
@credit_card_regex ~r/^(?:\d[ -]*?){13,16}$/
8-
@scrubbed_value "*********"
9-
10-
@moduledoc """
11-
Provides basic functionality to handle Plug.ErrorHandler
12-
13-
#### Usage
14-
15-
Add the following to your router.ex:
16-
17-
use Plug.ErrorHandler
18-
use Sentry.Plug
19-
20-
### Sending Post Body Params
21-
22-
In order to send post body parameters you should first scrub them of sensitive
23-
information. By default, they will be scrubbed with
24-
`Sentry.Plug.default_body_scrubber/1`. It can be overridden by passing
25-
the `body_scrubber` option, which accepts a `Plug.Conn` and returns a map
26-
to send. Setting `:body_scrubber` to `nil` will not send any data back.
27-
If you would like to make use of Sentry's default scrubber behavior in a custom
28-
scrubber, it can be called directly. An example configuration may look like
29-
the following:
30-
31-
def scrub_params(conn) do
32-
# Makes use of the default body_scrubber to avoid sending password
33-
# and credit card information in plain text. To also prevent sending
34-
# our sensitive "my_secret_field" and "other_sensitive_data" fields,
35-
# we simply drop those keys.
36-
Sentry.Plug.default_body_scrubber(conn)
37-
|> Map.drop(["my_secret_field", "other_sensitive_data"])
38-
end
1+
if Code.ensure_loaded?(Plug) do
2+
defmodule Sentry.Plug do
3+
@default_scrubbed_param_keys ["password", "passwd", "secret"]
4+
@default_scrubbed_header_keys ["authorization", "authentication"]
5+
@credit_card_regex ~r/^(?:\d[ -]*?){13,16}$/
6+
@scrubbed_value "*********"
7+
8+
@moduledoc """
9+
Provides basic functionality to handle Plug.ErrorHandler
10+
11+
#### Usage
12+
13+
Add the following to your router.ex:
14+
15+
use Plug.ErrorHandler
16+
use Sentry.Plug
17+
18+
### Sending Post Body Params
19+
20+
In order to send post body parameters you should first scrub them of sensitive
21+
information. By default, they will be scrubbed with
22+
`Sentry.Plug.default_body_scrubber/1`. It can be overridden by passing
23+
the `body_scrubber` option, which accepts a `Plug.Conn` and returns a map
24+
to send. Setting `:body_scrubber` to `nil` will not send any data back.
25+
If you would like to make use of Sentry's default scrubber behavior in a custom
26+
scrubber, it can be called directly. An example configuration may look like
27+
the following:
28+
29+
def scrub_params(conn) do
30+
# Makes use of the default body_scrubber to avoid sending password
31+
# and credit card information in plain text. To also prevent sending
32+
# our sensitive "my_secret_field" and "other_sensitive_data" fields,
33+
# we simply drop those keys.
34+
Sentry.Plug.default_body_scrubber(conn)
35+
|> Map.drop(["my_secret_field", "other_sensitive_data"])
36+
end
3937
40-
Then pass it into Sentry.Plug:
38+
Then pass it into Sentry.Plug:
4139
42-
use Sentry.Plug, body_scrubber: &scrub_params/1
40+
use Sentry.Plug, body_scrubber: &scrub_params/1
4341
44-
You can also pass it in as a `{module, fun}` like so:
42+
You can also pass it in as a `{module, fun}` like so:
4543
46-
use Sentry.Plug, body_scrubber: {MyModule, :scrub_params}
44+
use Sentry.Plug, body_scrubber: {MyModule, :scrub_params}
4745
48-
*Please Note*: If you are sending large files you will want to scrub them out.
46+
*Please Note*: If you are sending large files you will want to scrub them out.
4947
50-
### Headers Scrubber
48+
### Headers Scrubber
5149
52-
By default Sentry will scrub Authorization and Authentication headers from all
53-
requests before sending them. It can be configured similarly to the body params
54-
scrubber, but is configured with the `:header_scrubber` key.
50+
By default Sentry will scrub Authorization and Authentication headers from all
51+
requests before sending them. It can be configured similarly to the body params
52+
scrubber, but is configured with the `:header_scrubber` key.
5553
56-
def scrub_headers(conn) do
57-
# default is: Sentry.Plug.default_header_scrubber(conn)
58-
#
59-
# We do not want to include Content-Type or User-Agent in reported
60-
# headers, so we drop them.
61-
Enum.into(conn.req_headers, %{})
62-
|> Map.drop(["content-type", "user-agent"])
63-
end
54+
def scrub_headers(conn) do
55+
# default is: Sentry.Plug.default_header_scrubber(conn)
56+
#
57+
# We do not want to include Content-Type or User-Agent in reported
58+
# headers, so we drop them.
59+
Enum.into(conn.req_headers, %{})
60+
|> Map.drop(["content-type", "user-agent"])
61+
end
6462
65-
Then pass it into Sentry.Plug:
63+
Then pass it into Sentry.Plug:
6664
67-
use Sentry.Plug, header_scrubber: &scrub_headers/1
65+
use Sentry.Plug, header_scrubber: &scrub_headers/1
6866
69-
It can also be passed in as a `{module, fun}` like so:
67+
It can also be passed in as a `{module, fun}` like so:
7068
71-
use Sentry.Plug, header_scrubber: {MyModule, :scrub_headers}
69+
use Sentry.Plug, header_scrubber: {MyModule, :scrub_headers}
7270
73-
To configure scrubbing body and header data, we can set both configuration keys:
71+
To configure scrubbing body and header data, we can set both configuration keys:
7472
75-
use Sentry.Plug, header_scrubber: &scrub_headers/1, body_scrubber: &scrub_params/1
73+
use Sentry.Plug, header_scrubber: &scrub_headers/1, body_scrubber: &scrub_params/1
7674
77-
### Including Request Identifiers
75+
### Including Request Identifiers
7876
79-
If you're using Phoenix, Plug.RequestId, or another method to set a request ID
80-
response header, and would like to include that information with errors
81-
reported by Sentry.Plug, the `:request_id_header` option allows you to set
82-
which header key Sentry should check. It will default to "x-request-id",
83-
which Plug.RequestId (and therefore Phoenix) also default to.
77+
If you're using Phoenix, Plug.RequestId, or another method to set a request ID
78+
response header, and would like to include that information with errors
79+
reported by Sentry.Plug, the `:request_id_header` option allows you to set
80+
which header key Sentry should check. It will default to "x-request-id",
81+
which Plug.RequestId (and therefore Phoenix) also default to.
8482
85-
use Sentry.Plug, request_id_header: "application-request-id"
86-
"""
83+
use Sentry.Plug, request_id_header: "application-request-id"
84+
"""
8785

88-
@default_plug_request_id_header "x-request-id"
86+
@default_plug_request_id_header "x-request-id"
8987

90-
defmacro __using__(env) do
91-
body_scrubber = Keyword.get(env, :body_scrubber, {__MODULE__, :default_body_scrubber})
88+
defmacro __using__(env) do
89+
body_scrubber = Keyword.get(env, :body_scrubber, {__MODULE__, :default_body_scrubber})
9290

93-
header_scrubber =
94-
Keyword.get(env, :header_scrubber, {__MODULE__, :default_header_scrubber})
91+
header_scrubber = Keyword.get(env, :header_scrubber, {__MODULE__, :default_header_scrubber})
9592

96-
request_id_header = Keyword.get(env, :request_id_header)
93+
request_id_header = Keyword.get(env, :request_id_header)
9794

98-
quote do
99-
# Ignore 404s for Plug routes
100-
defp handle_errors(conn, %{reason: %FunctionClauseError{function: :do_match}}) do
101-
nil
102-
end
95+
quote do
96+
# Ignore 404s for Plug routes
97+
defp handle_errors(conn, %{reason: %FunctionClauseError{function: :do_match}}) do
98+
nil
99+
end
103100

104-
if :code.is_loaded(Phoenix) do
105-
# Ignore 404s for Phoenix routes
106-
defp handle_errors(conn, %{reason: %Phoenix.Router.NoRouteError{}}) do
107-
nil
108-
end
101+
if :code.is_loaded(Phoenix) do
102+
# Ignore 404s for Phoenix routes
103+
defp handle_errors(conn, %{reason: %Phoenix.Router.NoRouteError{}}) do
104+
nil
109105
end
106+
end
110107

111-
defp handle_errors(conn, %{kind: kind, reason: reason, stack: stack}) do
112-
opts = [
113-
body_scrubber: unquote(body_scrubber),
114-
header_scrubber: unquote(header_scrubber),
115-
request_id_header: unquote(request_id_header)
116-
]
117-
118-
request = Sentry.Plug.build_request_interface_data(conn, opts)
119-
exception = Exception.normalize(kind, reason, stack)
120-
121-
Sentry.capture_exception(
122-
exception,
123-
stacktrace: stack,
124-
request: request,
125-
event_source: :plug,
126-
error_type: kind
127-
)
128-
end
108+
defp handle_errors(conn, %{kind: kind, reason: reason, stack: stack}) do
109+
opts = [
110+
body_scrubber: unquote(body_scrubber),
111+
header_scrubber: unquote(header_scrubber),
112+
request_id_header: unquote(request_id_header)
113+
]
114+
115+
request = Sentry.Plug.build_request_interface_data(conn, opts)
116+
exception = Exception.normalize(kind, reason, stack)
117+
118+
Sentry.capture_exception(
119+
exception,
120+
stacktrace: stack,
121+
request: request,
122+
event_source: :plug,
123+
error_type: kind
124+
)
129125
end
130126
end
127+
end
131128

132-
@spec build_request_interface_data(Plug.Conn.t(), keyword()) :: map()
133-
def build_request_interface_data(%Plug.Conn{} = conn, opts) do
134-
body_scrubber = Keyword.get(opts, :body_scrubber)
135-
header_scrubber = Keyword.get(opts, :header_scrubber)
136-
request_id = Keyword.get(opts, :request_id_header) || @default_plug_request_id_header
137-
138-
conn =
139-
Plug.Conn.fetch_cookies(conn)
140-
|> Plug.Conn.fetch_query_params()
141-
142-
%{
143-
url: "#{conn.scheme}://#{conn.host}:#{conn.port}#{conn.request_path}",
144-
method: conn.method,
145-
data: handle_data(conn, body_scrubber),
146-
query_string: conn.query_string,
147-
cookies: conn.req_cookies,
148-
headers: handle_data(conn, header_scrubber),
149-
env: %{
150-
"REMOTE_ADDR" => remote_address(conn.remote_ip),
151-
"REMOTE_PORT" => remote_port(conn.peer),
152-
"SERVER_NAME" => conn.host,
153-
"SERVER_PORT" => conn.port,
154-
"REQUEST_ID" => Plug.Conn.get_resp_header(conn, request_id) |> List.first()
155-
}
129+
@spec build_request_interface_data(Plug.Conn.t(), keyword()) :: map()
130+
def build_request_interface_data(%Plug.Conn{} = conn, opts) do
131+
body_scrubber = Keyword.get(opts, :body_scrubber)
132+
header_scrubber = Keyword.get(opts, :header_scrubber)
133+
request_id = Keyword.get(opts, :request_id_header) || @default_plug_request_id_header
134+
135+
conn =
136+
Plug.Conn.fetch_cookies(conn)
137+
|> Plug.Conn.fetch_query_params()
138+
139+
%{
140+
url: "#{conn.scheme}://#{conn.host}:#{conn.port}#{conn.request_path}",
141+
method: conn.method,
142+
data: handle_data(conn, body_scrubber),
143+
query_string: conn.query_string,
144+
cookies: conn.req_cookies,
145+
headers: handle_data(conn, header_scrubber),
146+
env: %{
147+
"REMOTE_ADDR" => remote_address(conn.remote_ip),
148+
"REMOTE_PORT" => remote_port(conn.peer),
149+
"SERVER_NAME" => conn.host,
150+
"SERVER_PORT" => conn.port,
151+
"REQUEST_ID" => Plug.Conn.get_resp_header(conn, request_id) |> List.first()
156152
}
157-
end
153+
}
154+
end
158155

159-
defp remote_address(address) do
160-
address
161-
|> :inet.ntoa()
162-
|> to_string()
163-
end
156+
defp remote_address(address) do
157+
address
158+
|> :inet.ntoa()
159+
|> to_string()
160+
end
164161

165-
defp remote_port({_, port}), do: port
162+
defp remote_port({_, port}), do: port
166163

167-
defp handle_data(_conn, nil), do: %{}
164+
defp handle_data(_conn, nil), do: %{}
168165

169-
defp handle_data(conn, {module, fun}) do
170-
apply(module, fun, [conn])
171-
end
166+
defp handle_data(conn, {module, fun}) do
167+
apply(module, fun, [conn])
168+
end
172169

173-
defp handle_data(conn, fun) when is_function(fun) do
174-
fun.(conn)
175-
end
170+
defp handle_data(conn, fun) when is_function(fun) do
171+
fun.(conn)
172+
end
176173

177-
@spec default_header_scrubber(Plug.Conn.t()) :: map()
178-
def default_header_scrubber(conn) do
179-
Enum.into(conn.req_headers, %{})
180-
|> Map.drop(@default_scrubbed_header_keys)
181-
end
174+
@spec default_header_scrubber(Plug.Conn.t()) :: map()
175+
def default_header_scrubber(conn) do
176+
Enum.into(conn.req_headers, %{})
177+
|> Map.drop(@default_scrubbed_header_keys)
178+
end
182179

183-
@spec default_body_scrubber(Plug.Conn.t()) :: map()
184-
def default_body_scrubber(conn) do
185-
scrub_map(conn.params)
186-
end
180+
@spec default_body_scrubber(Plug.Conn.t()) :: map()
181+
def default_body_scrubber(conn) do
182+
scrub_map(conn.params)
183+
end
187184

188-
defp scrub_map(map) do
189-
Enum.map(map, fn {key, value} ->
190-
value =
191-
cond do
192-
Enum.member?(@default_scrubbed_param_keys, key) ->
193-
@scrubbed_value
185+
defp scrub_map(map) do
186+
Enum.map(map, fn {key, value} ->
187+
value =
188+
cond do
189+
Enum.member?(@default_scrubbed_param_keys, key) ->
190+
@scrubbed_value
194191

195-
is_binary(value) && Regex.match?(@credit_card_regex, value) ->
196-
@scrubbed_value
192+
is_binary(value) && Regex.match?(@credit_card_regex, value) ->
193+
@scrubbed_value
197194

198-
is_map(value) && !Map.has_key?(value, :__struct__) ->
199-
scrub_map(value)
195+
is_map(value) && !Map.has_key?(value, :__struct__) ->
196+
scrub_map(value)
200197

201-
true ->
202-
value
203-
end
198+
true ->
199+
value
200+
end
204201

205-
{key, value}
206-
end)
207-
|> Enum.into(%{})
208-
end
202+
{key, value}
203+
end)
204+
|> Enum.into(%{})
209205
end
210-
)
206+
end
207+
end

0 commit comments

Comments
 (0)