Skip to content

Instantly share code, notes, and snippets.

@mimosa
Created September 28, 2021 10:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mimosa/0879c321fb04bfbcc5a83f4bd92a114b to your computer and use it in GitHub Desktop.
Save mimosa/0879c321fb04bfbcc5a83f4bd92a114b to your computer and use it in GitHub Desktop.
Resource Sign Service
❯ rspec resource_sign_service_spec.rb
----| Hash test |----
{:a=>{:b=>"b", :c=>"c"}, :d=>"d"}  vs  {:d=>"d", :a=>{:c=>"c", :b=>"b"}}
+dIsjfhtier7LrkhmcNC9g==  vs  +dIsjfhtier7LrkhmcNC9g==
________________________________________________________________________________________
.----| Array test |----
[{:a=>{:b=>"b", :c=>"c"}, :d=>"d"}, {:d=>"d", :a=>{:c=>"c", :b=>"b"}}]  vs  [{:d=>"d", :a=>{:c=>"c", :b=>"b"}}, {:a=>{:b=>"b", :c=>"c"}, :d=>"d"}]
nGY1apVXDjKbeEtURBYe3A==  vs  nGY1apVXDjKbeEtURBYe3A==
________________________________________________________________________________________
.----| Json Text test |----
{"a":{"b":"b","c":"c"},"d":"d"}  vs  {"d":"d","a":{"c":"c","b":"b"}}
+dIsjfhtier7LrkhmcNC9g==  vs  +dIsjfhtier7LrkhmcNC9g==
________________________________________________________________________________________
.----| File binary test |----
/Users/wangha/Downloads/WechatIMG20.jpeg  vs  /Users/wangha/Downloads/WechatIMG20 copy.jpeg
x+yOEBqy4qnkkSbMqDm5Ug==  vs  x+yOEBqy4qnkkSbMqDm5Ug==
________________________________________________________________________________________
.

Finished in 0.05251 seconds (files took 0.25969 seconds to load)
4 examples, 0 failures
# frozen_string_literal: true
require 'openssl' unless defined?(OpenSSL::Digest)
require 'multi_json' unless defined?(MultiJson)
class ResourceSignService
def signature(content)
case content.class.name
when 'Hash'
arr = []
content.each { |k, v| arr << "#{signature k}:#{signature v}" }
signature(arr)
when 'Array'
str = ''
content.sort.each { |v| str += signature(v) }
signature(str)
when 'String'
content = MultiJson.load(content) if %r{^(\{|\[)(.*)(\]|\})$}.match?(content)
content.is_a?(String) ? signature_str(content) : signature(content)
else
case true
when content.respond_to?(:read)
signature_io(content)
when content.respond_to?(:to_h)
signature(content.to_h)
when content.respond_to?(:as_json)
signature(content.as_json)
when content.respond_to?(:to_s)
signature(content.to_s)
else
content.class.to_s
end
end
end
private
CHUNK_SIZE = 1 * 1024 * 1024 # one MB
def signature_str(str)
OpenSSL::Digest::MD5.base64digest(str)
end
def signature_io(io, digest: nil, chunk_size: CHUNK_SIZE)
digest ||= OpenSSL::Digest::MD5.new
loop do
chunk = io.read(chunk_size)
break unless chunk
digest.update(chunk)
end
io.rewind
digest.base64digest
end
end
# frozen_string_literal: true
require 'rspec/core' unless defined?(RSpec)
require './resource_sign_service' unless defined?(ResourceSignService)
RSpec.describe ResourceSignService do
let(:obj_a) { { a: { b: 'b', c: 'c' }, d: 'd' } }
let(:obj_b) { { d: 'd', a: { c: 'c', b: 'b' } } }
let(:arr_a) { [obj_a, obj_b] }
let(:arr_b) { [obj_b, obj_a] }
let(:json_a) { MultiJson.dump(obj_a) }
let(:json_b) { MultiJson.dump(obj_b) }
let(:file_path_a) { '/Users/wangha/Downloads/WechatIMG20.jpeg' }
let(:file_path_b) { '/Users/wangha/Downloads/WechatIMG20 copy.jpeg' }
describe 'match object with signature' do
it 'Hash' do
puts '----| Hash test |----'
puts "#{obj_a} vs #{obj_b}"
sign_a = subject.signature(obj_a)
sign_b = subject.signature(obj_b)
puts "#{sign_a} vs #{sign_b}"
puts '_' * 88
expect(sign_a).to eq(sign_b)
end
it 'Array' do
puts '----| Array test |----'
puts "#{arr_a} vs #{arr_b}"
sign_a = subject.signature(arr_a)
sign_b = subject.signature(arr_b)
puts "#{sign_a} vs #{sign_b}"
puts '_' * 88
expect(sign_a).to eq(sign_b)
end
it 'Json' do
puts '----| Json Text test |----'
puts "#{json_a} vs #{json_b}"
sign_a = subject.signature(json_a)
sign_b = subject.signature(json_b)
puts "#{sign_a} vs #{sign_b}"
puts '_' * 88
expect(sign_a).to eq(sign_b)
end
xit 'File' do
puts '----| File binary test |----'
file_a = File.open(file_path_a, 'rb')
file_b = File.open(file_path_b, 'rb')
puts "#{file_path_a} vs #{file_path_b}"
sign_a = subject.signature(file_a)
sign_b = subject.signature(file_b)
puts "#{sign_a} vs #{sign_b}"
puts '_' * 88
expect(sign_a).to eq(sign_b)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment