sentry-raven 2.9.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.craft.yml +14 -0
- data/.github/workflows/test.yml +77 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +44 -9
- data/.scripts/bump-version.sh +9 -0
- data/Gemfile +17 -25
- data/README.md +5 -4
- data/changelog.md +77 -1
- data/lib/raven/backtrace.rb +7 -5
- data/lib/raven/base.rb +5 -3
- data/lib/raven/breadcrumbs/activesupport.rb +10 -10
- data/lib/raven/breadcrumbs/logger.rb +4 -4
- data/lib/raven/breadcrumbs.rb +1 -1
- data/lib/raven/cli.rb +2 -2
- data/lib/raven/client.rb +28 -10
- data/lib/raven/configuration.rb +23 -8
- data/lib/raven/event.rb +5 -9
- data/lib/raven/instance.rb +12 -3
- data/lib/raven/integrations/delayed_job.rb +14 -15
- data/lib/raven/integrations/rack-timeout.rb +2 -3
- data/lib/raven/integrations/rack.rb +4 -3
- data/lib/raven/integrations/rails/active_job.rb +10 -7
- data/lib/raven/integrations/rails/controller_transaction.rb +1 -1
- data/lib/raven/integrations/rails/overrides/debug_exceptions_catcher.rb +2 -2
- data/lib/raven/integrations/rails.rb +1 -0
- data/lib/raven/interface.rb +2 -2
- data/lib/raven/interfaces/stack_trace.rb +1 -1
- data/lib/raven/linecache.rb +5 -2
- data/lib/raven/logger.rb +3 -2
- data/lib/raven/processor/cookies.rb +16 -6
- data/lib/raven/processor/post_data.rb +2 -0
- data/lib/raven/processor/removecircularreferences.rb +1 -0
- data/lib/raven/processor/sanitizedata.rb +65 -17
- data/lib/raven/processor/utf8conversion.rb +3 -1
- data/lib/raven/transports/http.rb +5 -5
- data/lib/raven/transports.rb +4 -0
- data/lib/raven/utils/exception_cause_chain.rb +1 -0
- data/lib/raven/utils/real_ip.rb +1 -1
- data/lib/raven/version.rb +2 -2
- data/sentry-raven.gemspec +3 -3
- metadata +8 -13
- data/.travis.yml +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 765b22e2ec433b8ab12697da42d40ba6c0f2f95956bd6ce93b0923b9160f386f
|
4
|
+
data.tar.gz: b4f97a6effa6828a10cb7844001852db042627dfe375aae61e93b92d10eb2ba7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25c1a39ce4a97b7e40fa66fc1dd1eb7ae4ef96a6e0956f7600db04717eb8c9f147d83317513ba072db31a4390b678b9c56f406f6ba02377f11b4810a3fef5128
|
7
|
+
data.tar.gz: 17adf7a479a1539a9fdc81003b2204c0334334cb54482812339af18cd7a75eb9830e22389fc0eed7e304787b993f8aaca92bb1d1c2f414e88a61858acadf08aa
|
data/.craft.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
minVersion: '0.9.0'
|
2
|
+
github:
|
3
|
+
owner: getsentry
|
4
|
+
repo: raven-ruby
|
5
|
+
changelogPolicy: simple
|
6
|
+
preReleaseCommand: ruby .scripts/bump-version.sh
|
7
|
+
statusProvider:
|
8
|
+
name: github
|
9
|
+
targets:
|
10
|
+
- name: github
|
11
|
+
- name: registry
|
12
|
+
type: sdk
|
13
|
+
config:
|
14
|
+
canonical: 'gem:sentry-raven'
|
@@ -0,0 +1,77 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
- release/**
|
8
|
+
pull_request:
|
9
|
+
jobs:
|
10
|
+
test:
|
11
|
+
name: Test on ruby ${{ matrix.ruby_version }} and rails ${{ matrix.rails_version }}
|
12
|
+
runs-on: ${{ matrix.os }}
|
13
|
+
strategy:
|
14
|
+
matrix:
|
15
|
+
rails_version: [0, 4.2, 5.2, 6.0]
|
16
|
+
ruby_version: [2.3, 2.4, 2.5, 2.6, 2.7, jruby, head]
|
17
|
+
os: [ubuntu-latest]
|
18
|
+
include:
|
19
|
+
- ruby_version: head
|
20
|
+
rails_version: 0
|
21
|
+
- ruby_version: 2.7
|
22
|
+
rails_version: 6.0
|
23
|
+
env: RUBYOPT="--enable-frozen-string-literal --debug=frozen-string-literal"
|
24
|
+
exclude:
|
25
|
+
- ruby_version: 2.3
|
26
|
+
rails_version: 6.0
|
27
|
+
- ruby_version: 2.4
|
28
|
+
rails_version: 6.0
|
29
|
+
- ruby_version: 2.7
|
30
|
+
rails_version: 4.2
|
31
|
+
- ruby_version: head
|
32
|
+
rails_version: 4.2
|
33
|
+
- ruby_version: head
|
34
|
+
rails_version: 5.2
|
35
|
+
- ruby_version: head
|
36
|
+
rails_version: 6.0
|
37
|
+
|
38
|
+
steps:
|
39
|
+
- uses: actions/checkout@v1
|
40
|
+
|
41
|
+
- name: Set up Ruby ${{ matrix.ruby_version }}
|
42
|
+
uses: ruby/setup-ruby@v1
|
43
|
+
with:
|
44
|
+
bundler: 1
|
45
|
+
ruby-version: ${{ matrix.ruby_version }}
|
46
|
+
|
47
|
+
- name: Build with Rails ${{ matrix.rails_version }}
|
48
|
+
env:
|
49
|
+
RAILS_VERSION: ${{ matrix.rails_version }}
|
50
|
+
run: |
|
51
|
+
bundle install --jobs 4 --retry 3
|
52
|
+
bundle exec rake
|
53
|
+
|
54
|
+
job_zeus:
|
55
|
+
name: Zeus
|
56
|
+
runs-on: ubuntu-latest
|
57
|
+
steps:
|
58
|
+
- uses: actions/checkout@v2
|
59
|
+
- uses: actions/setup-node@v1
|
60
|
+
- name: Set up Ruby
|
61
|
+
uses: ruby/setup-ruby@v1
|
62
|
+
with:
|
63
|
+
ruby-version: 2.6 # Not needed with a .ruby-version file
|
64
|
+
- run: bundle install
|
65
|
+
- name: Install Zeus
|
66
|
+
run: |
|
67
|
+
yarn global add @zeus-ci/cli
|
68
|
+
echo "::add-path::$(yarn global bin)"
|
69
|
+
- name: Upload to Zeus
|
70
|
+
env:
|
71
|
+
ZEUS_API_TOKEN: ${{ secrets.ZEUS_API_TOKEN }}
|
72
|
+
ZEUS_HOOK_BASE: ${{ secrets.ZEUS_HOOK_BASE }}
|
73
|
+
run: |
|
74
|
+
zeus job update -b $GITHUB_RUN_ID -j $GITHUB_RUN_NUMBER -r $GITHUB_SHA
|
75
|
+
gem build sentry-raven.gemspec
|
76
|
+
zeus upload -b $GITHUB_RUN_ID -j $GITHUB_RUN_NUMBER -t "application/tar+gem" ./*.gem
|
77
|
+
zeus job update --status=passed -b $GITHUB_RUN_ID -j $GITHUB_RUN_NUMBER -r $GITHUB_SHA
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -13,33 +13,45 @@ Metrics/ClassLength:
|
|
13
13
|
Metrics/AbcSize:
|
14
14
|
Max: 40
|
15
15
|
|
16
|
+
Metrics/BlockLength:
|
17
|
+
Enabled: false
|
18
|
+
|
16
19
|
Metrics/CyclomaticComplexity:
|
17
20
|
Max: 12
|
18
21
|
|
19
22
|
Metrics/PerceivedComplexity:
|
20
23
|
Max: 11
|
21
24
|
|
22
|
-
Metrics/LineLength:
|
23
|
-
Max: 155
|
24
|
-
|
25
25
|
Metrics/MethodLength:
|
26
26
|
Max: 30
|
27
27
|
|
28
|
-
Style/
|
28
|
+
Style/SymbolArray:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Style/PercentLiteralDelimiters:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Style/FrozenStringLiteralComment:
|
29
35
|
Enabled: false
|
30
36
|
|
31
|
-
|
37
|
+
Style/SignalException:
|
32
38
|
Enabled: false
|
33
39
|
|
34
40
|
Style/ClassAndModuleChildren:
|
35
41
|
Enabled: false
|
36
42
|
|
43
|
+
Style/RescueStandardError:
|
44
|
+
Enabled: false
|
45
|
+
|
37
46
|
Style/ParallelAssignment:
|
38
47
|
Enabled: false
|
39
48
|
|
40
49
|
Style/Documentation:
|
41
50
|
Enabled: false
|
42
51
|
|
52
|
+
Style/CommentedKeyword:
|
53
|
+
Enabled: false
|
54
|
+
|
43
55
|
Style/RescueModifier:
|
44
56
|
Enabled: false
|
45
57
|
|
@@ -52,10 +64,11 @@ Style/CaseEquality:
|
|
52
64
|
Style/DoubleNegation:
|
53
65
|
Enabled: false
|
54
66
|
|
55
|
-
Style/
|
56
|
-
|
57
|
-
|
58
|
-
|
67
|
+
Style/GuardClause:
|
68
|
+
Enabled: false
|
69
|
+
|
70
|
+
Style/RedundantBegin:
|
71
|
+
Enabled: false
|
59
72
|
|
60
73
|
Style/NumericLiterals:
|
61
74
|
Exclude:
|
@@ -64,6 +77,9 @@ Style/NumericLiterals:
|
|
64
77
|
Style/HashSyntax:
|
65
78
|
EnforcedStyle: hash_rockets
|
66
79
|
|
80
|
+
Style/IfUnlessModifier:
|
81
|
+
Enabled: false
|
82
|
+
|
67
83
|
Lint/RescueException:
|
68
84
|
Exclude:
|
69
85
|
- 'lib/raven/base.rb'
|
@@ -72,3 +88,22 @@ Lint/RescueException:
|
|
72
88
|
- 'lib/raven/integrations/rack.rb'
|
73
89
|
- 'lib/raven/integrations/sidekiq.rb'
|
74
90
|
- 'spec/raven/event_spec.rb'
|
91
|
+
|
92
|
+
Lint/SuppressedException:
|
93
|
+
Enabled: false
|
94
|
+
|
95
|
+
Lint/AssignmentInCondition:
|
96
|
+
Enabled: false
|
97
|
+
|
98
|
+
Layout/LineLength:
|
99
|
+
Max: 155
|
100
|
+
|
101
|
+
Naming/FileName:
|
102
|
+
Exclude:
|
103
|
+
- 'lib/sentry-raven-without-integrations.rb'
|
104
|
+
- 'lib/sentry-raven.rb'
|
105
|
+
- 'lib/raven/integrations/rack-timeout.rb'
|
106
|
+
|
107
|
+
Naming/MethodParameterName:
|
108
|
+
Enabled: false
|
109
|
+
|
data/Gemfile
CHANGED
@@ -2,37 +2,29 @@ source "https://rubygems.org/"
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
|
6
|
-
gem "rails", "< 5"
|
7
|
-
gem "rspec-rails", "> 3"
|
8
|
-
elsif ENV["RAILS_VERSION"] && (ENV["RAILS_VERSION"].to_i == 0)
|
9
|
-
# no-op. No Rails.
|
10
|
-
else
|
11
|
-
gem "rails", "< 6"
|
12
|
-
gem "rspec-rails", "> 3"
|
13
|
-
end
|
5
|
+
rails_version = ENV["RAILS_VERSION"].to_f
|
14
6
|
|
15
|
-
if
|
16
|
-
gem "
|
17
|
-
gem "
|
18
|
-
gem "rack", "~> 1.6.8"
|
19
|
-
gem "sidekiq", "< 3.2"
|
20
|
-
gem "rack-timeout", "0.3.0"
|
21
|
-
else
|
22
|
-
gem "rack"
|
23
|
-
gem "sidekiq"
|
24
|
-
gem "rack-timeout"
|
7
|
+
if rails_version != 0
|
8
|
+
gem "rails", "~> #{rails_version}"
|
9
|
+
gem "rspec-rails", "~> 4.0"
|
25
10
|
end
|
11
|
+
|
12
|
+
gem "sidekiq"
|
13
|
+
|
14
|
+
gem "rack"
|
15
|
+
gem "rack-timeout"
|
16
|
+
|
26
17
|
gem "pry"
|
27
|
-
gem "pry-coolline"
|
28
18
|
gem "benchmark-ips"
|
29
|
-
gem "benchmark-ipsa"
|
19
|
+
gem "benchmark-ipsa"
|
30
20
|
gem "ruby-prof", platform: :mri
|
31
21
|
gem "rake", "> 12"
|
32
|
-
gem "rubocop", "~> 0.
|
33
|
-
gem "rspec", "
|
34
|
-
gem "capybara" # rspec system tests
|
22
|
+
gem "rubocop", "~> 0.81.0"
|
23
|
+
gem "rspec", "~> 3.9.0"
|
24
|
+
gem "capybara", "~> 3.15.0" # rspec system tests
|
35
25
|
gem "puma" # rspec system tests
|
36
26
|
|
37
27
|
gem "timecop"
|
38
|
-
gem "test-unit"
|
28
|
+
gem "test-unit"
|
29
|
+
gem "simplecov"
|
30
|
+
gem "codecov"
|
data/README.md
CHANGED
@@ -8,18 +8,19 @@
|
|
8
8
|
# Raven-Ruby, the Ruby Client for Sentry
|
9
9
|
|
10
10
|
[](https://rubygems.org/gems/sentry-raven)
|
11
|
-
|
11
|
+

|
12
|
+
[](https://codecov.io/gh/getsentry/raven-ruby/branch/master)
|
12
13
|
[](https://rubygems.org/gems/sentry-raven/)
|
13
14
|
[](https://dependabot.com/compatibility-score.html?dependency-name=sentry-raven&package-manager=bundler&version-scheme=semver)
|
14
15
|
|
15
16
|
|
16
|
-
[Documentation](https://docs.
|
17
|
+
[Documentation](https://docs.sentry.io/clients/ruby/) | [Bug Tracker](https://github.com/getsentry/raven-ruby/issues) | [Forum](https://forum.sentry.io/) | IRC: irc.freenode.net, #sentry
|
17
18
|
|
18
19
|
The official Ruby-language client and integration layer for the [Sentry](https://github.com/getsentry/sentry) error reporting API.
|
19
20
|
|
20
21
|
## Requirements
|
21
22
|
|
22
|
-
We test on Ruby
|
23
|
+
We test on Ruby 2.3, 2.4, 2.5, 2.6 and 2.7 at the latest patchlevel/teeny version. We also support JRuby 9.0. Our Rails integration works with Rails 4.2+, including Rails 5 and Rails 6.
|
23
24
|
|
24
25
|
## Getting Started
|
25
26
|
|
@@ -133,4 +134,4 @@ For more information, see [Context](https://docs.sentry.io/clients/ruby/context/
|
|
133
134
|
* [Documentation](https://docs.sentry.io/clients/ruby/)
|
134
135
|
* [Bug Tracker](https://github.com/getsentry/raven-ruby/issues)
|
135
136
|
* [Forum](https://forum.sentry.io/)
|
136
|
-
|
137
|
+
- [Discord](https://discord.gg/ez5KZN7)
|
data/changelog.md
CHANGED
@@ -1,3 +1,79 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## Unreleased
|
4
|
+
|
5
|
+
## 3.0.1
|
6
|
+
|
7
|
+
* fix: Improve SanitizeData processor (#984)
|
8
|
+
* fix: Masking cookies as key/pair instead of a single string (#983)
|
9
|
+
* fix: Transports classes' requiring issue (#986)
|
10
|
+
* fix: Frozen string issues (#977)
|
11
|
+
* feat: Officially support Rails 6 (#982)
|
12
|
+
|
13
|
+
3.0.0
|
14
|
+
----
|
15
|
+
|
16
|
+
* SDK now requires Ruby >= 2.3
|
17
|
+
* REF: Retain any literal "HTTP-" in header names [@elliterate, #950]
|
18
|
+
* REF: Delete JSON spec for recursive hashes [@ksylvest, #952]
|
19
|
+
* FEAT: Bump faraday version to latest [@ksylvest, #946]
|
20
|
+
|
21
|
+
2.13.0
|
22
|
+
----
|
23
|
+
|
24
|
+
* FIX: Sanitize event data before they are sent to async job. [@edariedl, #895]
|
25
|
+
* FIX: Serialization MongoDB ObjectId to JSON problem with gem delayed_job_mongoid conjunction. [@eagleas, #935]
|
26
|
+
* FEAT: Skip ActiveJob integration if there is a better one [@fsateler, #909]
|
27
|
+
* FIX: Bugs with send_event in asynchronous mode (#940) [@cstyles, #940]
|
28
|
+
|
29
|
+
2.12.3
|
30
|
+
----
|
31
|
+
|
32
|
+
* FIX: crash when Process.wait is used [@asBrettisay, #895]
|
33
|
+
|
34
|
+
2.12.2
|
35
|
+
----
|
36
|
+
|
37
|
+
* FIX: return tags/extra for [@rivayama, #931]
|
38
|
+
|
39
|
+
2.12.1
|
40
|
+
----
|
41
|
+
|
42
|
+
* FIX: undefined method `[]' for nil:NilClass [@HazAT, #932]
|
43
|
+
|
44
|
+
2.12.0
|
45
|
+
----
|
46
|
+
|
47
|
+
* FIX: Remove duplicate message when exception is emitted
|
48
|
+
* FIX: Frozen string bug in utf8conversation
|
49
|
+
* FEATURE: Allow block on tags_context and extra_context
|
50
|
+
|
51
|
+
2.11.3
|
52
|
+
----
|
53
|
+
|
54
|
+
* FIX: infinite backoff under pressure [@Bonias, #886]
|
55
|
+
|
56
|
+
2.11.2
|
57
|
+
----
|
58
|
+
|
59
|
+
* REF: Warn on 4xx error [@iloveitaly, #862]
|
60
|
+
|
61
|
+
2.11.1
|
62
|
+
----
|
63
|
+
|
64
|
+
* FIX: Call `to_s` on breadcrumb message [@halkeye, #914]
|
65
|
+
|
66
|
+
2.11.0
|
67
|
+
----
|
68
|
+
|
69
|
+
* FEATURE: Prepend the transaction around_action so libraries with controllers can alter the value. [@drcapulet, #887]
|
70
|
+
|
71
|
+
2.10.0
|
72
|
+
-----
|
73
|
+
|
74
|
+
* FEATURE: Added support for `SENTRY_ENVIRONMENT` [@mtsmfm, #910]
|
75
|
+
* FEATURE: Added support for `SENTRY_RELEASE` [@coorasse, #911]
|
76
|
+
|
1
77
|
2.9.0
|
2
78
|
-----
|
3
79
|
|
@@ -7,7 +83,7 @@
|
|
7
83
|
2.8.0
|
8
84
|
-----
|
9
85
|
|
10
|
-
* FEATURE: Added `config.before_send`. Provide a lambda or proc to this config setting, which will be `call`ed
|
86
|
+
* FEATURE: Added `config.before_send`. Provide a lambda or proc to this config setting, which will be `call`ed before sending an event to Sentry. Receives `event` and `hint` as parameters. `hint` is a hash `{:exception => ex | nil, :message => message | nil}`. [@hazat, #882]
|
11
87
|
|
12
88
|
2.7.4
|
13
89
|
-----
|
data/lib/raven/backtrace.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
## Inspired by Rails' and Airbrake's backtrace parsers.
|
2
4
|
|
3
5
|
module Raven
|
@@ -5,16 +7,16 @@ module Raven
|
|
5
7
|
class Backtrace
|
6
8
|
# Handles backtrace parsing line by line
|
7
9
|
class Line
|
8
|
-
RB_EXTENSION = ".rb"
|
10
|
+
RB_EXTENSION = ".rb"
|
9
11
|
# regexp (optional leading X: on windows, or JRuby9000 class-prefix)
|
10
12
|
RUBY_INPUT_FORMAT = /
|
11
13
|
^ \s* (?: [a-zA-Z]: | uri:classloader: )? ([^:]+ | <.*>):
|
12
14
|
(\d+)
|
13
15
|
(?: :in \s `([^']+)')?$
|
14
|
-
/x
|
16
|
+
/x.freeze
|
15
17
|
|
16
18
|
# org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:170)
|
17
|
-
JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)
|
19
|
+
JAVA_INPUT_FORMAT = /^(.+)\.([^\.]+)\(([^\:]+)\:(\d+)\)$/.freeze
|
18
20
|
|
19
21
|
# The file portion of the line (such as app/models/user.rb)
|
20
22
|
attr_reader :file
|
@@ -74,7 +76,7 @@ module Raven
|
|
74
76
|
|
75
77
|
def self.in_app_pattern
|
76
78
|
@in_app_pattern ||= begin
|
77
|
-
project_root = Raven.configuration.project_root
|
79
|
+
project_root = Raven.configuration.project_root&.to_s
|
78
80
|
Regexp.new("^(#{project_root}/)?#{Raven.configuration.app_dirs_pattern || APP_DIRS_PATTERN}")
|
79
81
|
end
|
80
82
|
end
|
@@ -84,7 +86,7 @@ module Raven
|
|
84
86
|
attr_writer :file, :number, :method, :module_name
|
85
87
|
end
|
86
88
|
|
87
|
-
APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)
|
89
|
+
APP_DIRS_PATTERN = /(bin|exe|app|config|lib|test)/.freeze
|
88
90
|
|
89
91
|
# holder for an Array of Backtrace::Line instances
|
90
92
|
attr_reader :lines
|
data/lib/raven/base.rb
CHANGED
@@ -85,12 +85,13 @@ module Raven
|
|
85
85
|
|
86
86
|
def load_integration(integration)
|
87
87
|
require "raven/integrations/#{integration}"
|
88
|
-
rescue Exception =>
|
89
|
-
logger.warn "Unable to load raven/integrations/#{integration}: #{
|
88
|
+
rescue Exception => e
|
89
|
+
logger.warn "Unable to load raven/integrations/#{integration}: #{e}"
|
90
90
|
end
|
91
91
|
|
92
92
|
def safely_prepend(module_name, opts = {})
|
93
93
|
return if opts[:to].nil? || opts[:from].nil?
|
94
|
+
|
94
95
|
if opts[:to].respond_to?(:prepend, true)
|
95
96
|
opts[:to].send(:prepend, opts[:from].const_get(module_name))
|
96
97
|
else
|
@@ -100,7 +101,8 @@ module Raven
|
|
100
101
|
|
101
102
|
def sys_command(command)
|
102
103
|
result = `#{command} 2>&1` rescue nil
|
103
|
-
return if result.nil? || result.empty? || $CHILD_STATUS.exitstatus != 0
|
104
|
+
return if result.nil? || result.empty? || ($CHILD_STATUS && $CHILD_STATUS.exitstatus != 0)
|
105
|
+
|
104
106
|
result.strip
|
105
107
|
end
|
106
108
|
end
|