Skip to content

Commit

Permalink
Replace non UTF-8 characters before JSON encoding
Browse files Browse the repository at this point in the history
  • Loading branch information
wallin committed Sep 19, 2017
1 parent 1c8484c commit 06f6f52
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 1 deletion.
1 change: 1 addition & 0 deletions lib/castle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
require 'castle/failover_auth_response'
require 'castle/client'
require 'castle/header_formatter'
require 'castle/replace_invalid_characters'
require 'castle/secure_mode'
require 'castle/extractors/client_id'
require 'castle/extractors/headers'
Expand Down
18 changes: 18 additions & 0 deletions lib/castle/replace_invalid_characters.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module Castle
class ReplaceInvalidCharacters
def self.call(hash)
return hash unless hash.is_a?(Hash)
hash.each_with_object({}) do |(k, v), h|
h[k] = if v.is_a?(Hash)
call(v)
elsif v.is_a?(String)
v.encode('UTF-8', invalid: :replace, undef: :replace)
else
v
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/castle/request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def build(endpoint, args, method)
request = Net::HTTP.const_get(method.to_s.capitalize).new(
"#{@config.api_endpoint.path}/#{endpoint}", @headers
)
request.body = args.to_json
request.body = ::Castle::ReplaceInvalidCharacters.call(args).to_json
add_basic_auth(request)
request
end
Expand Down
49 changes: 49 additions & 0 deletions spec/lib/castle/replace_invalid_characters_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# frozen_string_literal: true

require 'spec_helper'

describe Castle::ReplaceInvalidCharacters do
subject { described_class.call(input) }

context 'when input is a string' do
let(:input) { '1234' }

it { is_expected.to eq input }
end

context 'when input is an array' do
let(:input) { [1, 2, 3, '4'] }

it { is_expected.to eq input }
end

context 'when input is a hash' do
let(:input) { { user_id: 1 } }

it { is_expected.to eq input }
end

context 'when input is nil' do
let(:input) { nil }

it { is_expected.to eq input }
end

context 'when input is a nested hash' do
let(:input) { { user: { id: 1 } } }

it { is_expected.to eq input }
end

context 'when input is a hash with invalid UTF-8 characters' do
let(:input) { { user_id: "inv\xC4lid" } }

it { is_expected.to eq(user_id: 'inv�lid') }
end

context 'when input is a nested hash with invalid UTF-8 characters' do
let(:input) { { user: { id: "inv\xC4lid" } } }

it { is_expected.to eq(user: { id: 'inv�lid' }) }
end
end
6 changes: 6 additions & 0 deletions spec/lib/castle/request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@
it { expect(request.path).to eql('/v1/endpoint') }
it { expect(request.to_hash['sample-header']).to eql(['1']) }
it { expect(request.to_hash['authorization'][0]).to match(/Basic \w/) }

context 'with non-UTF-8 charaters' do
let(:params) { { name: "\xC4" } }

it { expect(request.body).to eq '{"name":"�"}' }
end
end
end
end

0 comments on commit 06f6f52

Please sign in to comment.