carbon-copy 0.1.1 → 0.1.2
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 +7 -0
- data/.gitignore +1 -0
- data/Gemfile +5 -1
- data/Gemfile.lock +57 -21
- data/README.md +1 -1
- data/Rakefile +62 -0
- data/lib/carbon-copy.rb +1 -1
- data/lib/carbon-copy/cache_server.rb +14 -17
- data/lib/carbon-copy/request_cacher.rb +9 -8
- data/spec/request_spec.rb +70 -71
- metadata +19 -30
- data/spec/cache_server_spec.rb +0 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b524ab6407840385ee6745889d25d51df0e79c93c21927a463d377ce1bb0b262
|
4
|
+
data.tar.gz: 5d6bde51dead477acc082ba705688871cdbe1056414a52e83aa081e913bb4486
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ce54a722ebd0467a0ff9c59c3852f4140b451d7c4087747b1d47b4ff3f8291fe93a9df5d12bb98a3d512b8427dd3671ca1a5adc3568b625b562660f6287aa22f
|
7
|
+
data.tar.gz: f6cc06c2c00860a8025c9fdcdcc31828678c90c3314629999de72ad7dbd5933cce3ceebc2e98678e9bd54e9fdc658439077c5692b0a16872581552479c737c63
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,37 +1,73 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
carbon-copy (0.
|
4
|
+
carbon-copy (0.1.2)
|
5
5
|
|
6
6
|
GEM
|
7
|
-
remote:
|
7
|
+
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
bump (0.9.0)
|
10
|
+
coderay (1.1.3)
|
11
|
+
diff-lcs (1.4.4)
|
12
|
+
domain_name (0.5.20190701)
|
13
|
+
unf (>= 0.0.5, < 1.0.0)
|
14
|
+
http-accept (1.7.0)
|
15
|
+
http-cookie (1.0.3)
|
16
|
+
domain_name (~> 0.5)
|
17
|
+
method_source (1.0.0)
|
18
|
+
mime-types (3.3.1)
|
19
|
+
mime-types-data (~> 3.2015)
|
20
|
+
mime-types-data (3.2020.0512)
|
21
|
+
mustermann (1.1.1)
|
22
|
+
ruby2_keywords (~> 0.0.1)
|
23
|
+
netrc (0.11.0)
|
24
|
+
pry (0.13.1)
|
25
|
+
coderay (~> 1.1)
|
26
|
+
method_source (~> 1.0)
|
27
|
+
rack (2.2.3)
|
28
|
+
rack-protection (2.0.8.1)
|
13
29
|
rack
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
rspec
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
30
|
+
rake (13.0.1)
|
31
|
+
rest-client (2.1.0)
|
32
|
+
http-accept (>= 1.7.0, < 2.0)
|
33
|
+
http-cookie (>= 1.0.2, < 2.0)
|
34
|
+
mime-types (>= 1.16, < 4.0)
|
35
|
+
netrc (~> 0.8)
|
36
|
+
rspec (3.9.0)
|
37
|
+
rspec-core (~> 3.9.0)
|
38
|
+
rspec-expectations (~> 3.9.0)
|
39
|
+
rspec-mocks (~> 3.9.0)
|
40
|
+
rspec-core (3.9.2)
|
41
|
+
rspec-support (~> 3.9.3)
|
42
|
+
rspec-expectations (3.9.2)
|
43
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
44
|
+
rspec-support (~> 3.9.0)
|
45
|
+
rspec-mocks (3.9.1)
|
46
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
47
|
+
rspec-support (~> 3.9.0)
|
48
|
+
rspec-support (3.9.3)
|
49
|
+
ruby2_keywords (0.0.2)
|
50
|
+
sinatra (2.0.8.1)
|
51
|
+
mustermann (~> 1.0)
|
52
|
+
rack (~> 2.0)
|
53
|
+
rack-protection (= 2.0.8.1)
|
54
|
+
tilt (~> 2.0)
|
55
|
+
tilt (2.0.10)
|
56
|
+
unf (0.1.4)
|
57
|
+
unf_ext
|
58
|
+
unf_ext (0.0.7.7)
|
29
59
|
|
30
60
|
PLATFORMS
|
31
61
|
ruby
|
32
62
|
|
33
63
|
DEPENDENCIES
|
64
|
+
bump
|
34
65
|
carbon-copy!
|
66
|
+
pry
|
67
|
+
rake
|
35
68
|
rest-client
|
36
69
|
rspec
|
37
70
|
sinatra
|
71
|
+
|
72
|
+
BUNDLED WITH
|
73
|
+
2.1.4
|
data/README.md
CHANGED
data/Rakefile
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
require "bump"
|
4
|
+
|
5
|
+
NAME = Dir["*.gemspec"].first.split(".").first.freeze
|
6
|
+
VERSION = CarbonCopy::VERSION
|
7
|
+
GEM_FILE = "#{NAME}-#{VERSION}.gem".freeze
|
8
|
+
GEMSPEC_FILE = "#{NAME}.gemspec".freeze
|
9
|
+
|
10
|
+
require "rdoc/task"
|
11
|
+
RDoc::Task.new do |rdoc|
|
12
|
+
rdoc.main = "README.md"
|
13
|
+
rdoc.markup = "tomdoc"
|
14
|
+
rdoc.rdoc_dir = "doc"
|
15
|
+
rdoc.rdoc_files.include("README.md", "lib/**/*.rb")
|
16
|
+
end
|
17
|
+
|
18
|
+
require "rspec/core/rake_task"
|
19
|
+
RSpec::Core::RakeTask.new(:spec)
|
20
|
+
task default: :spec
|
21
|
+
|
22
|
+
namespace :bump do
|
23
|
+
current_version = Bump::Bump.current
|
24
|
+
|
25
|
+
%w[major minor patch pre].each do |bump|
|
26
|
+
version = Bump::Bump.next_version(bump)
|
27
|
+
desc "Bump v#{current_version} to v#{version}"
|
28
|
+
task bump do
|
29
|
+
Bump::Bump.run(bump, commit: false)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Bump v#{current_version} to $VERSION"
|
34
|
+
task :set do
|
35
|
+
unless /\S/.match?(ENV["VERSION"])
|
36
|
+
puts "ERROR: version can't be blank"
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
|
40
|
+
Bump::Bump.run("set", commit: false, version: ENV["VERSION"])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
desc "Build #{GEM_FILE} into the pkg directory"
|
45
|
+
task :build do
|
46
|
+
sh "mkdir -p pkg"
|
47
|
+
sh "gem build #{GEMSPEC_FILE}"
|
48
|
+
sh "mv #{GEM_FILE} pkg"
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "Create tag v#{VERSION} and build and push #{GEM_FILE} to Rubygems"
|
52
|
+
task release: [:spec, :build] do
|
53
|
+
unless /^\* master$/.match?(`git branch`)
|
54
|
+
puts "You must be on the master branch to release!"
|
55
|
+
exit!
|
56
|
+
end
|
57
|
+
sh "git commit --allow-empty -a -e -m 'Release #{VERSION}'"
|
58
|
+
sh "git tag -f v#{VERSION}"
|
59
|
+
sh "git push origin master"
|
60
|
+
sh "git push origin v#{VERSION}"
|
61
|
+
sh "gem push pkg/#{GEM_FILE}"
|
62
|
+
end
|
data/lib/carbon-copy.rb
CHANGED
@@ -1,18 +1,17 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "socket"
|
2
|
+
require "openssl"
|
3
|
+
require "carbon-copy/request_cacher"
|
4
|
+
require "carbon-copy/request"
|
5
5
|
|
6
6
|
module CarbonCopy
|
7
7
|
class CacheServer
|
8
|
-
|
9
8
|
def initialize(port, request_cacher)
|
10
|
-
@port
|
9
|
+
@port = port
|
11
10
|
@request_cacher = request_cacher
|
12
11
|
end
|
13
12
|
|
14
13
|
def run
|
15
|
-
webserver = TCPServer.new(
|
14
|
+
webserver = TCPServer.new("127.0.0.1", @port)
|
16
15
|
puts "Running Carbon Copy on localhost port #{@port}"
|
17
16
|
while (session = webserver.accept)
|
18
17
|
Thread.new(session, &method(:handle))
|
@@ -20,16 +19,14 @@ module CarbonCopy
|
|
20
19
|
end
|
21
20
|
|
22
21
|
def handle(session)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
p e.backtrace
|
32
|
-
end
|
22
|
+
request = Request.new(session)
|
23
|
+
request.parse
|
24
|
+
response = @request_cacher.connect(request)
|
25
|
+
session.write(response)
|
26
|
+
session.close
|
27
|
+
rescue => e
|
28
|
+
p e.message
|
29
|
+
p e.backtrace
|
33
30
|
end
|
34
31
|
end
|
35
32
|
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
require
|
1
|
+
require "digest/md5"
|
2
|
+
require "fileutils"
|
2
3
|
|
3
4
|
module CarbonCopy
|
4
5
|
class RequestCacher
|
@@ -15,7 +16,7 @@ module CarbonCopy
|
|
15
16
|
|
16
17
|
# Determine final path
|
17
18
|
def path(request)
|
18
|
-
uri =
|
19
|
+
uri = request.uri == "/" ? "" : request.uri.tr("\/", "_")
|
19
20
|
hash = Digest::MD5.new << request.header_str
|
20
21
|
# Cache directory structure
|
21
22
|
"""
|
@@ -24,14 +25,14 @@ module CarbonCopy
|
|
24
25
|
#{request.verb.downcase}
|
25
26
|
#{uri}_
|
26
27
|
#{hash}
|
27
|
-
""".gsub(/\n|\s/,
|
28
|
+
""".gsub(/\n|\s/, "")
|
28
29
|
end
|
29
30
|
|
30
31
|
# Ensure cached directories are created
|
31
32
|
def verify_cached_dir(request)
|
32
|
-
|
33
|
+
FileUtils.mkdir_p(cache_dir) unless File.exist?(cache_dir)
|
33
34
|
host_cache = "#{cache_dir}/#{request.host}"
|
34
|
-
|
35
|
+
FileUtils.mkdir_p(host_cache) unless File.exist?(host_cache)
|
35
36
|
end
|
36
37
|
|
37
38
|
def get_response(request)
|
@@ -70,12 +71,12 @@ module CarbonCopy
|
|
70
71
|
verify_cached_dir(request)
|
71
72
|
cached_path = path(request)
|
72
73
|
|
73
|
-
if File.
|
74
|
+
if File.exist?(cached_path) && !File.zero?(cached_path)
|
74
75
|
puts "Getting file #{cached_path} from cache"
|
75
|
-
IO.read(
|
76
|
+
IO.read(cached_path)
|
76
77
|
else
|
77
78
|
resp = get_response(request)
|
78
|
-
File.open(
|
79
|
+
File.open(cached_path, "w") do |f|
|
79
80
|
f.puts resp
|
80
81
|
end
|
81
82
|
resp
|
data/spec/request_spec.rb
CHANGED
@@ -1,90 +1,89 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "spec_helper"
|
2
|
+
require "carbon-copy/request"
|
3
3
|
|
4
4
|
module CarbonCopy
|
5
|
-
describe Request do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
5
|
+
describe Request do
|
6
|
+
describe "#parse_headers" do
|
7
|
+
let(:rs) { Request.new(double) }
|
8
|
+
|
9
|
+
it "should parse easy header strings" do
|
10
|
+
st = StringIO.new
|
11
|
+
st << "TestHeader: Header Result"
|
12
|
+
st << "\r\n\r\n"
|
13
|
+
st.rewind
|
14
|
+
rs.parse_headers(st).should eq({"TestHeader" => "Header Result"})
|
15
|
+
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
17
|
+
it "should parse multi-line headers" do
|
18
|
+
st = StringIO.new
|
19
|
+
st << "TestHeader: Header Result\n"
|
20
|
+
st << "TestHeaders: Header Result"
|
21
|
+
st << "\r\n\r\n"
|
22
|
+
st.rewind
|
23
|
+
rs.parse_headers(st).should eq({
|
24
|
+
"TestHeader" => "Header Result",
|
25
|
+
"TestHeaders" => "Header Result"
|
26
|
+
})
|
27
|
+
end
|
27
28
|
end
|
28
|
-
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
describe 'just host' do
|
34
|
-
let(:request) { create_host_IO("GET /apple.com HTTP/1.1\n") }
|
30
|
+
describe "#parse" do
|
31
|
+
let(:rs) { Request.new(request).parse }
|
35
32
|
|
36
|
-
|
37
|
-
|
38
|
-
end
|
33
|
+
describe "just host" do
|
34
|
+
let(:request) { create_host_IO("GET /apple.com HTTP/1.1\n") }
|
39
35
|
|
40
|
-
|
41
|
-
|
36
|
+
specify { rs.host.should eq("apple.com") }
|
37
|
+
specify { rs.uri.should eq("/") }
|
38
|
+
end
|
42
39
|
|
43
|
-
|
44
|
-
|
45
|
-
specify { rs.url.should eq('apple.com') }
|
46
|
-
specify { rs.uri.should eq('/') }
|
47
|
-
end
|
40
|
+
describe "host with port" do
|
41
|
+
let(:request) { create_host_IO("GET /apple.com:3000 HTTP/1.1\n") }
|
48
42
|
|
49
|
-
|
50
|
-
|
43
|
+
specify { rs.port.should eq("3000") }
|
44
|
+
specify { rs.host.should eq("apple.com") }
|
45
|
+
specify { rs.url.should eq("apple.com") }
|
46
|
+
specify { rs.uri.should eq("/") }
|
47
|
+
end
|
51
48
|
|
52
|
-
|
53
|
-
|
54
|
-
specify { rs.url.should eq('apple.com/awesome') }
|
55
|
-
specify { rs.uri.should eq('/awesome') }
|
56
|
-
end
|
49
|
+
describe "host with port and path" do
|
50
|
+
let(:request) { create_host_IO("GET /apple.com:18/awesome HTTP/1.1\n") }
|
57
51
|
|
58
|
-
|
59
|
-
|
52
|
+
specify { rs.port.should eq("18") }
|
53
|
+
specify { rs.host.should eq("apple.com") }
|
54
|
+
specify { rs.url.should eq("apple.com/awesome") }
|
55
|
+
specify { rs.uri.should eq("/awesome") }
|
56
|
+
end
|
60
57
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
58
|
+
describe "host with get string" do
|
59
|
+
let(:request) { create_host_IO("POST /fazebook.com/google?p=test HTTP/1.1\n") }
|
60
|
+
|
61
|
+
specify { rs.verb.should eq("POST") }
|
62
|
+
specify { rs.port.should eq("80") }
|
63
|
+
specify { rs.url.should eq("fazebook.com/google?p=test") }
|
64
|
+
specify { rs.request_str.should eq("POST /google?p=test HTTP/1.1\r") }
|
65
|
+
end
|
66
66
|
|
67
|
-
|
68
|
-
|
67
|
+
describe "host with path" do
|
68
|
+
let(:request) { create_host_IO("GET /apple.com/google/face/ HTTP/1.1\n") }
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
70
|
+
specify { rs.verb.should eq("GET") }
|
71
|
+
specify { rs.port.should eq("80") }
|
72
|
+
specify { rs.url.should eq("apple.com/google/face/") }
|
73
|
+
specify { rs.version.should eq("1.1") }
|
74
|
+
specify { rs.host.should eq("apple.com") }
|
75
|
+
specify { rs.uri.should eq("/google/face/") }
|
76
|
+
specify { rs.request_str.should eq("GET /google/face/? HTTP/1.1\r") }
|
77
|
+
end
|
77
78
|
end
|
78
|
-
end
|
79
79
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
80
|
+
def create_host_IO(host)
|
81
|
+
req = StringIO.new
|
82
|
+
host.split("\n").each do |host|
|
83
|
+
req << "#{host}\n"
|
84
|
+
end
|
85
|
+
req.rewind
|
86
|
+
req
|
84
87
|
end
|
85
|
-
req.rewind
|
86
|
-
req
|
87
88
|
end
|
88
|
-
|
89
|
-
end
|
90
89
|
end
|
metadata
CHANGED
@@ -1,62 +1,55 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: carbon-copy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
5
|
-
prerelease:
|
4
|
+
version: 0.1.2
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Kevin Webster
|
9
|
-
autorequire:
|
8
|
+
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2020-08-13 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rspec
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rest-client
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - ">="
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - ">="
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: sinatra
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - ">="
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
description: easily cache them REST calls
|
@@ -67,50 +60,46 @@ executables:
|
|
67
60
|
extensions: []
|
68
61
|
extra_rdoc_files: []
|
69
62
|
files:
|
70
|
-
- .gitignore
|
71
|
-
- .rspec
|
63
|
+
- ".gitignore"
|
64
|
+
- ".rspec"
|
72
65
|
- Gemfile
|
73
66
|
- Gemfile.lock
|
74
67
|
- README.md
|
68
|
+
- Rakefile
|
75
69
|
- bin/carbon-copy
|
76
70
|
- carbon-copy.gemspec
|
77
71
|
- lib/carbon-copy.rb
|
78
72
|
- lib/carbon-copy/cache_server.rb
|
79
73
|
- lib/carbon-copy/request.rb
|
80
74
|
- lib/carbon-copy/request_cacher.rb
|
81
|
-
- spec/cache_server_spec.rb
|
82
75
|
- spec/integration_spec.rb
|
83
76
|
- spec/request_cacher_spec.rb
|
84
77
|
- spec/request_spec.rb
|
85
78
|
- spec/spec_helper.rb
|
86
79
|
homepage: https://github.com/rabidpraxis/carbon-copy
|
87
80
|
licenses: []
|
88
|
-
|
81
|
+
metadata: {}
|
82
|
+
post_install_message:
|
89
83
|
rdoc_options: []
|
90
84
|
require_paths:
|
91
85
|
- lib
|
92
86
|
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
-
none: false
|
94
87
|
requirements:
|
95
|
-
- -
|
88
|
+
- - ">="
|
96
89
|
- !ruby/object:Gem::Version
|
97
90
|
version: '0'
|
98
91
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
-
none: false
|
100
92
|
requirements:
|
101
|
-
- -
|
93
|
+
- - ">="
|
102
94
|
- !ruby/object:Gem::Version
|
103
95
|
version: '0'
|
104
96
|
requirements: []
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
specification_version: 3
|
97
|
+
rubygems_version: 3.1.2
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
109
100
|
summary: REST cache
|
110
101
|
test_files:
|
111
|
-
- spec/cache_server_spec.rb
|
112
102
|
- spec/integration_spec.rb
|
113
103
|
- spec/request_cacher_spec.rb
|
114
104
|
- spec/request_spec.rb
|
115
105
|
- spec/spec_helper.rb
|
116
|
-
has_rdoc:
|
data/spec/cache_server_spec.rb
DELETED
File without changes
|