cameleon 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. data/.document +5 -0
  2. data/Gemfile +13 -0
  3. data/LICENSE.txt +20 -0
  4. data/README.md +105 -0
  5. data/Rakefile +53 -0
  6. data/VERSION +1 -0
  7. data/bin/cameleon +6 -0
  8. data/cameleon.gemspec +106 -0
  9. data/lib/cameleon/action.rb +29 -0
  10. data/lib/cameleon/app.rb +13 -0
  11. data/lib/cameleon/cli/gallery.rb +18 -0
  12. data/lib/cameleon/cli/generate.rb +30 -0
  13. data/lib/cameleon/cli/new.rb +15 -0
  14. data/lib/cameleon/cli/server.rb +34 -0
  15. data/lib/cameleon/cli.rb +66 -0
  16. data/lib/cameleon/renderer.rb +99 -0
  17. data/lib/cameleon.rb +45 -0
  18. data/template/gallery/response/gallery/erb/default.txt +2 -0
  19. data/template/gallery/response/gallery/json/_switch.rb +15 -0
  20. data/template/gallery/response/gallery/json/bar.json +1 -0
  21. data/template/gallery/response/gallery/json/default.json +1 -0
  22. data/template/gallery/response/gallery/json/foo.json +1 -0
  23. data/template/gallery/response/gallery/params/_switch.rb +10 -0
  24. data/template/gallery/response/gallery/params/bar.txt +1 -0
  25. data/template/gallery/response/gallery/params/default.txt +1 -0
  26. data/template/gallery/response/gallery/params/foo.txt +1 -0
  27. data/template/gallery/response/gallery/rest/_switch.rb +16 -0
  28. data/template/gallery/response/gallery/rest/delete.txt +1 -0
  29. data/template/gallery/response/gallery/rest/get.txt +1 -0
  30. data/template/gallery/response/gallery/rest/put_or_post.txt +1 -0
  31. data/template/gallery/response/gallery/simple/default.txt +1 -0
  32. data/template/gallery/response/gallery/xml/_switch.rb +18 -0
  33. data/template/gallery/response/gallery/xml/bar.xml +1 -0
  34. data/template/gallery/response/gallery/xml/default.xml +1 -0
  35. data/template/gallery/response/gallery/xml/foo.xml +1 -0
  36. data/template/generate/_switch.rb +5 -0
  37. data/template/generate/default +1 -0
  38. data/template/new/cameleon.yml +1 -0
  39. data/template/new/response/_root/_switch.rb +8 -0
  40. data/template/new/response/_root/default +3 -0
  41. data/test/helper.rb +18 -0
  42. data/test/test_cameleon.rb +4 -0
  43. metadata +193 -0
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ gem "erubis"
3
+ gem "rack"
4
+ gem "hashie"
5
+ gem "json"
6
+ gem "nokogiri"
7
+
8
+ group :development do
9
+ gem "shoulda", ">= 0"
10
+ gem "bundler", "~> 1.0.0"
11
+ gem "jeweler", "~> 1.6.4"
12
+ gem "rcov", ">= 0"
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 daixque
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,105 @@
1
+ Cameleon
2
+ =======================================
3
+
4
+ Cameleon (not Chameleon!) is HTTP mock server framework based on Rack. You can easily create HTTP server for mockup or stub of external system for your application.
5
+
6
+ All you have to do to create a new interface is simply make directory and put text file into the directory.
7
+
8
+ Features:
9
+
10
+ - Simple API for "_switch.rb" (for selecting response file)
11
+ - Communicate in JSON, XML or any format over HTTP
12
+ - Easy to create RESTful API
13
+
14
+
15
+ ## Installation
16
+ You can install Cameleon using RubyGems as below:
17
+
18
+ $ gem install cameleon
19
+
20
+
21
+ ## Getting started
22
+ First, create a new Cameleon project.
23
+
24
+ $ cameleon new your_project_name.
25
+
26
+ Then move the directory now you created, and launch cameleon server.
27
+
28
+ $ cd your_project_name
29
+ $ cameleon server
30
+
31
+ OK, your server is now running. Test your server using curl.
32
+
33
+ $ curl http://localhost:9292
34
+ Hey, I am cameleon!
35
+ Edit response folder to change response whatever you want.
36
+ see README.md more detail.
37
+
38
+
39
+ ## Usage
40
+ ### creating HTTP interface
41
+ Think about creating HTTP interface such like below:
42
+
43
+ - URL: /path/to/interface
44
+ - response: "ok"
45
+
46
+ Then all you have to do are below:
47
+
48
+ $ mkdir -p response/path/to/interface
49
+ $ cd response/path/to/interface
50
+ $ echo "ok" > default.txt
51
+
52
+ Test the interface:
53
+
54
+ $ curl http://localhost:9292/path/to/interface
55
+ ok
56
+
57
+ ### generate command
58
+ Or simply, you can create a interface using "cameleon generate" command.
59
+ If you want to create a new interface "/path/to/foo", type:
60
+
61
+ $ cameleon generate path/to/foo
62
+
63
+ and test it.
64
+
65
+ $ curl http://localhost:9292/path/to/foo
66
+ edit me: response/path/to/foo/default
67
+
68
+ So edit the file as you need.
69
+
70
+ ### _switch.rb
71
+ If you want to change the response by HTTP request, you shold create "_switch.rb" in your response directory.
72
+
73
+ Below shows a sample of "_switch.rb".
74
+
75
+ # you can access URL parameters by 'params'
76
+ case params[:key]
77
+ when "foo"
78
+ # curl http://localhost:9292/gallery/params?key=foo
79
+ render "foo.txt"
80
+ when "bar"
81
+ # You can also use POST or PUT. See 'rest' more about hadling HTTP methods.
82
+ # curl -XPOST http://localhost:9292/gallery/params -d"key=bar"
83
+ render "bar.txt"
84
+ end
85
+
86
+ # if else, render "default" (any extention acceptable) file.
87
+
88
+
89
+ ## Gallery
90
+ You can get various samples using "cameleon gallery" command.
91
+ $ cd YOUR_CAMELEON_HOME
92
+ $ cameleon gallery
93
+
94
+ Check out response/gallery directory and "_switch.rb" to know usage of APIs.
95
+
96
+
97
+ ## License
98
+ Cameleon is released under the MIT license.
99
+
100
+
101
+ ## Copyright
102
+ Copyright (c) 2011 [daisuke sugimori][1] ([@daixque][2]).
103
+
104
+ [1]: http://opentechnica.blogspot.com/
105
+ [2]: http://twitter.com/daixque
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "cameleon"
18
+ gem.homepage = "http://github.com/daixque/cameleon"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{Cameleon is HTTP mock server framework.}
21
+ gem.description = %Q{Cameleon is HTTP mock server framework based on Rack. You can easily create HTTP server for mockup or stub of external system for your application.}
22
+ gem.email = "daixque@gmail.com"
23
+ gem.authors = ["daixque"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rake/testtask'
29
+ Rake::TestTask.new(:test) do |test|
30
+ test.libs << 'lib' << 'test'
31
+ test.pattern = 'test/**/test_*.rb'
32
+ test.verbose = true
33
+ end
34
+
35
+ require 'rcov/rcovtask'
36
+ Rcov::RcovTask.new do |test|
37
+ test.libs << 'test'
38
+ test.pattern = 'test/**/test_*.rb'
39
+ test.verbose = true
40
+ test.rcov_opts << '--exclude "gems/*"'
41
+ end
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "cameleon #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/bin/cameleon ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
5
+ require 'rubygems'
6
+ require 'cameleon/cli'
data/cameleon.gemspec ADDED
@@ -0,0 +1,106 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{cameleon}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{daixque}]
12
+ s.date = %q{2011-09-11}
13
+ s.description = %q{Cameleon is HTTP mock server framework based on Rack. You can easily create HTTP server for mockup or stub of external system for your application.}
14
+ s.email = %q{daixque@gmail.com}
15
+ s.executables = [%q{cameleon}]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE.txt",
18
+ "README.md"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ "Gemfile",
23
+ "LICENSE.txt",
24
+ "README.md",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/cameleon",
28
+ "cameleon.gemspec",
29
+ "lib/cameleon.rb",
30
+ "lib/cameleon/action.rb",
31
+ "lib/cameleon/app.rb",
32
+ "lib/cameleon/cli.rb",
33
+ "lib/cameleon/cli/gallery.rb",
34
+ "lib/cameleon/cli/generate.rb",
35
+ "lib/cameleon/cli/new.rb",
36
+ "lib/cameleon/cli/server.rb",
37
+ "lib/cameleon/renderer.rb",
38
+ "template/gallery/response/gallery/erb/default.txt",
39
+ "template/gallery/response/gallery/json/_switch.rb",
40
+ "template/gallery/response/gallery/json/bar.json",
41
+ "template/gallery/response/gallery/json/default.json",
42
+ "template/gallery/response/gallery/json/foo.json",
43
+ "template/gallery/response/gallery/params/_switch.rb",
44
+ "template/gallery/response/gallery/params/bar.txt",
45
+ "template/gallery/response/gallery/params/default.txt",
46
+ "template/gallery/response/gallery/params/foo.txt",
47
+ "template/gallery/response/gallery/rest/_switch.rb",
48
+ "template/gallery/response/gallery/rest/delete.txt",
49
+ "template/gallery/response/gallery/rest/get.txt",
50
+ "template/gallery/response/gallery/rest/put_or_post.txt",
51
+ "template/gallery/response/gallery/simple/default.txt",
52
+ "template/gallery/response/gallery/xml/_switch.rb",
53
+ "template/gallery/response/gallery/xml/bar.xml",
54
+ "template/gallery/response/gallery/xml/default.xml",
55
+ "template/gallery/response/gallery/xml/foo.xml",
56
+ "template/generate/_switch.rb",
57
+ "template/generate/default",
58
+ "template/new/cameleon.yml",
59
+ "template/new/response/_root/_switch.rb",
60
+ "template/new/response/_root/default",
61
+ "test/helper.rb",
62
+ "test/test_cameleon.rb"
63
+ ]
64
+ s.homepage = %q{http://github.com/daixque/cameleon}
65
+ s.licenses = [%q{MIT}]
66
+ s.require_paths = [%q{lib}]
67
+ s.rubygems_version = %q{1.8.6}
68
+ s.summary = %q{Cameleon is HTTP mock server framework.}
69
+
70
+ if s.respond_to? :specification_version then
71
+ s.specification_version = 3
72
+
73
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
74
+ s.add_runtime_dependency(%q<erubis>, [">= 0"])
75
+ s.add_runtime_dependency(%q<rack>, [">= 0"])
76
+ s.add_runtime_dependency(%q<hashie>, [">= 0"])
77
+ s.add_runtime_dependency(%q<json>, [">= 0"])
78
+ s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
79
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
80
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
81
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
82
+ s.add_development_dependency(%q<rcov>, [">= 0"])
83
+ else
84
+ s.add_dependency(%q<erubis>, [">= 0"])
85
+ s.add_dependency(%q<rack>, [">= 0"])
86
+ s.add_dependency(%q<hashie>, [">= 0"])
87
+ s.add_dependency(%q<json>, [">= 0"])
88
+ s.add_dependency(%q<nokogiri>, [">= 0"])
89
+ s.add_dependency(%q<shoulda>, [">= 0"])
90
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
91
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
92
+ s.add_dependency(%q<rcov>, [">= 0"])
93
+ end
94
+ else
95
+ s.add_dependency(%q<erubis>, [">= 0"])
96
+ s.add_dependency(%q<rack>, [">= 0"])
97
+ s.add_dependency(%q<hashie>, [">= 0"])
98
+ s.add_dependency(%q<json>, [">= 0"])
99
+ s.add_dependency(%q<nokogiri>, [">= 0"])
100
+ s.add_dependency(%q<shoulda>, [">= 0"])
101
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
102
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
103
+ s.add_dependency(%q<rcov>, [">= 0"])
104
+ end
105
+ end
106
+
@@ -0,0 +1,29 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'erubis'
3
+
4
+ class Cameleon
5
+ class Action
6
+ def find_default_file
7
+ Dir.entries(@base_path).find { |f| f =~ /^default\./ }
8
+ end
9
+
10
+ def handle(req)
11
+ @base_path = File.join("response", req.path)
12
+ if req.path == "/"
13
+ @base_path += "_root"
14
+ end
15
+ @params = req.params
16
+ @body = req.body.read
17
+ switch_filepath = File.join @base_path, "_switch.rb"
18
+ renderer = nil
19
+ if !File.exists?(@base_path)
20
+ return [404, {}, ["dir not found: #{@base_path}"]]
21
+ elsif File.exists?(switch_filepath)
22
+ renderer = Renderer.run_switch(@base_path, req, switch_filepath)
23
+ else
24
+ renderer = Renderer.render_file(@base_path, req)
25
+ end
26
+ renderer.build_response
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,13 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Cameleon
4
+ class App
5
+ def call(env)
6
+ Cameleon.import File.join(Cameleon.root, "lib/cameleon/action.rb")
7
+ Cameleon.import File.join(Cameleon.root, "lib/cameleon/renderer.rb")
8
+ action = Cameleon::Action.new
9
+ req = Rack::Request.new(env)
10
+ action.handle(req)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'cameleon'
4
+ require 'fileutils'
5
+
6
+ def new
7
+ unless Cameleon.config
8
+ $stderr.puts "not cameleon home"
9
+ exit(1)
10
+ end
11
+
12
+ base_dir = File.join(Cameleon.root, 'template/gallery')
13
+ Dir.glob("#{base_dir}/*").map do |f|
14
+ FileUtils.cp_r f, "."
15
+ end
16
+ end
17
+
18
+ new
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'cameleon'
4
+ require 'erubis'
5
+ require 'fileutils'
6
+
7
+ def generate
8
+ unless Cameleon.config
9
+ $stderr.puts "not cameleon home"
10
+ exit(1)
11
+ end
12
+
13
+ path = ARGV.shift
14
+ dir_path = File.join "response", path
15
+ FileUtils.mkdir_p dir_path
16
+
17
+ template_dir = File.join Cameleon.root, "/template/generate"
18
+ Dir.glob("#{template_dir}/*").map do |path|
19
+ basename = File.basename(path)
20
+ target_file_path = File.join dir_path, basename
21
+ src = File.read path
22
+ erb = Erubis::Eruby.new src
23
+ body = erb.result(binding)
24
+ File.open(target_file_path, "w") do |f|
25
+ f.puts body
26
+ end
27
+ end
28
+ end
29
+
30
+ generate
@@ -0,0 +1,15 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'cameleon'
4
+ require 'fileutils'
5
+
6
+ def new
7
+ project_name = ARGV.shift
8
+ FileUtils.mkdir_p project_name
9
+ base_dir = File.join(Cameleon.root, 'template/new')
10
+ Dir.glob("#{base_dir}/*").map do |f|
11
+ FileUtils.cp_r f, project_name
12
+ end
13
+ end
14
+
15
+ new
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'cameleon'
4
+ require 'hashie'
5
+ require 'yaml'
6
+
7
+ def start(config)
8
+ version = ">= 0"
9
+
10
+ if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
11
+ version = $1
12
+ ARGV.shift
13
+ end
14
+
15
+ gem 'rack', version
16
+ require 'rack'
17
+ require 'rack/builder'
18
+ require 'rack/handler/webrick'
19
+ app = Rack::Builder.new {
20
+ use Rack::Chunked
21
+ run Cameleon::App.new
22
+ }
23
+ trap(:INT) {
24
+ Rack::Handler::WEBrick.shutdown
25
+ }
26
+ Rack::Handler::WEBrick.run app, :Port => (config.port || 9292)
27
+ end
28
+
29
+ config = Cameleon.config
30
+ unless config
31
+ $stderr.puts "[ERROR] cameleon.yml is not found."
32
+ exit(1)
33
+ end
34
+ start config
@@ -0,0 +1,66 @@
1
+ # -*- coding: utf-8 -*-
2
+ # command line interface for cameleon
3
+
4
+ require 'cameleon'
5
+ require 'optparse'
6
+
7
+ def parse_options(argv)
8
+ OptionParser.new { |opt|
9
+ opt.on("-v", "--version") {
10
+ version = File.read "#{Cameleon.root}/VERSION"
11
+ puts "cameleon #{version}"
12
+ exit(0)
13
+ }
14
+ opt.on("-h", "--help") {
15
+ usage
16
+ exit(0)
17
+ }
18
+ opt.parse! argv
19
+ }
20
+ end
21
+
22
+ def usage
23
+ puts usage_text = <<-"USAGE"
24
+ Cameleon - HTTP mock server framework.
25
+
26
+ Usage:
27
+ cameleon [option] command [args]
28
+
29
+ Commands:
30
+ new: create new dummy application
31
+ server: launch server
32
+ generate path: generate scaffold for path
33
+
34
+ Options:
35
+ -v: show version
36
+ USAGE
37
+ end
38
+
39
+ def run
40
+ aliases = {
41
+ 's' => 'server',
42
+ 'g' => 'generate'
43
+ }
44
+
45
+ parse_options ARGV
46
+
47
+ command = ARGV.shift
48
+ command = aliases[command] || command
49
+ case command
50
+ when 'server'
51
+ require 'cameleon/cli/server'
52
+ when 'new'
53
+ require 'cameleon/cli/new'
54
+ when 'generate'
55
+ require 'cameleon/cli/generate'
56
+ when 'gallery'
57
+ require 'cameleon/cli/gallery'
58
+ when 'help'
59
+ usage
60
+ else
61
+ puts "unknown command: #{command}."
62
+ puts "'cameleon help' for usage."
63
+ end
64
+ end
65
+
66
+ run
@@ -0,0 +1,99 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'hashie'
3
+ require 'json'
4
+ require 'nokogiri'
5
+
6
+ class Cameleon
7
+ class Renderer
8
+ class << self
9
+ def run_switch(base_path, req, switch_path)
10
+ switch_src = File.read switch_path
11
+ Renderer.new(base_path, req).__eval_switch(switch_src)
12
+ end
13
+
14
+ def render_file(base_path, req, filename = nil)
15
+ catch(:read) {
16
+ Renderer.new(base_path, req).render(filename)
17
+ }
18
+ end
19
+ end
20
+
21
+ def initialize(base_path, req)
22
+ @base_path = base_path
23
+ @status_code = 200
24
+ @headers = {
25
+ "Content-Type" => "text/plain"
26
+ }
27
+ @req = req
28
+ @params = Hashie::Mash.new req.params
29
+ req.body.rewind
30
+ @body = req.body.read
31
+ @method = req.env["REQUEST_METHOD"]
32
+ end
33
+
34
+ def __eval_switch(switch_src)
35
+ catch(:read) {
36
+ eval switch_src
37
+ render find_default_file
38
+ }
39
+ end
40
+
41
+ def params
42
+ @params
43
+ end
44
+
45
+ def json_body
46
+ @json_body || @json_body = Hashie::Mash.new(JSON.parse(@body))
47
+ end
48
+
49
+ def xml_body
50
+ @xml_body || @xml_body = Nokogiri::XML::Document.parse(@body)
51
+ end
52
+
53
+ def build_response
54
+ [@status_code, @headers, [@body]]
55
+ end
56
+
57
+ def set_header(name, value)
58
+ @headers[name] = value
59
+ end
60
+
61
+ def status_code(code)
62
+ @status_code = code
63
+ end
64
+
65
+ def on(*http_methods, &block)
66
+ if http_methods.map { |m| m.to_s.upcase }.include? @method
67
+ yield
68
+ end
69
+ end
70
+
71
+ def get(&block)
72
+ on(:get, &block)
73
+ end
74
+
75
+ def put(&block)
76
+ on(:put, &block)
77
+ end
78
+
79
+ def post(&block)
80
+ on(:post, &block)
81
+ end
82
+
83
+ def delete(&block)
84
+ on(:delete, &block)
85
+ end
86
+
87
+ def render(filename = nil)
88
+ filename = find_default_file unless filename
89
+ src = File.read File.join(@base_path, filename)
90
+ erb = Erubis::Eruby.new src
91
+ @body = erb.result(binding)
92
+ throw :read, self
93
+ end
94
+
95
+ def find_default_file
96
+ Dir.entries(@base_path).find { |f| f =~ /^default/ }
97
+ end
98
+ end
99
+ end
data/lib/cameleon.rb ADDED
@@ -0,0 +1,45 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'cameleon/app'
4
+ require 'hashie'
5
+ require 'yaml'
6
+
7
+ class Cameleon
8
+ @@imported = {}
9
+ @@config = nil
10
+
11
+ class << self
12
+ def root
13
+ File.join File.dirname(__FILE__), "../"
14
+ end
15
+
16
+ def import(file)
17
+ raise "file not found" unless File.exists? file
18
+ crnt_timestamp = File::stat(file).mtime
19
+ if @@imported.include?(file)
20
+ prev_timestamp = @@imported[file]
21
+ if (crnt_timestamp > prev_timestamp)
22
+ @@imported[file] = crnt_timestamp
23
+ load(file)
24
+ return true
25
+ else
26
+ return false
27
+ end
28
+ else
29
+ @@imported[file] = crnt_timestamp
30
+ load(file)
31
+ return true
32
+ end
33
+ end # import
34
+
35
+ def config
36
+ @config ||= begin
37
+ path = "./cameleon.yml"
38
+ unless File.exist? path
39
+ return nil
40
+ end
41
+ Hashie::Mash.new YAML.load(File.read(path))
42
+ end
43
+ end # config
44
+ end # class methods
45
+ end
@@ -0,0 +1,2 @@
1
+ You can use ERuby(Erubis) syntax in response file.
2
+ time: <%= DateTime.now %>
@@ -0,0 +1,15 @@
1
+ # set HTTP header
2
+ set_header "Content-Type", "application/json"
3
+
4
+ # you can access POST body as json by 'json_body'
5
+ case json_body.query
6
+ when "foo"
7
+ # curl -XPOST http://localhost:9292/gallery/json -d"{\"query\":\"foo\"}"
8
+ render "foo.json"
9
+ when "bar"
10
+ # curl -XPOST http://localhost:9292/gallery/json -d"{\"query\":\"bar\"}"
11
+ render "bar.json"
12
+ end
13
+
14
+ # if nothing to match, use 404 HTTP Status Code and render default.json.
15
+ status_code 404
@@ -0,0 +1 @@
1
+ {"result": "bar.json"}
@@ -0,0 +1 @@
1
+ {"result": "404 not found (default.json)"}
@@ -0,0 +1 @@
1
+ {"result": "foo.json"}
@@ -0,0 +1,10 @@
1
+ # you can access URL parameters by 'params'
2
+ case params[:key]
3
+ when "foo"
4
+ # curl http://localhost:9292/gallery/params?key=foo
5
+ render "foo.txt"
6
+ when "bar"
7
+ # You can also use POST or PUT. See 'rest' more about hadling HTTP methods.
8
+ # curl -XPOST http://localhost:9292/gallery/params -d"key=bar"
9
+ render "bar.txt"
10
+ end
@@ -0,0 +1 @@
1
+ bar.txt
@@ -0,0 +1 @@
1
+ This is default.txt.
@@ -0,0 +1 @@
1
+ foo.txt
@@ -0,0 +1,16 @@
1
+ # 'on' method handles HTTP Methods.
2
+ on(:get) {
3
+ # curl -XGET "http://localhost:9292/gallery/rest"
4
+ render "get.txt"
5
+ }
6
+ on(:put, :post) {
7
+ # curl -XPUT "http://localhost:9292/gallery/rest" -d=""
8
+ render "put_or_post.txt"
9
+ }
10
+
11
+ # or simply 'get', 'put', 'post' and 'delete' methods are available for same purpose.
12
+ # this is same as on(:delete) {}
13
+ delete {
14
+ # curl -XDELETE "http://localhost:9292/gallery/rest"
15
+ render "delete.txt"
16
+ }
@@ -0,0 +1 @@
1
+ delete.txt
@@ -0,0 +1 @@
1
+ get.txt
@@ -0,0 +1 @@
1
+ put_or_post.txt
@@ -0,0 +1 @@
1
+ This is default.txt.
@@ -0,0 +1,18 @@
1
+ # set HTTP header
2
+ set_header "Content-Type", "application/xml"
3
+
4
+ # you can access HTTP body as XML document by 'xml_body'.
5
+ # xml_body is Nokogiri::XML::Document object.
6
+ # See Nokogiri website for more info.
7
+ # http://nokogiri.org/
8
+ case xml_body.xpath("/root/query").first.text
9
+ when "foo"
10
+ # curl -XPOST http://localhost:9292/gallery/xml -d"<root><query>foo</query></root>"
11
+ render "foo.xml"
12
+ when "bar"
13
+ # curl -XPOST http://localhost:9292/gallery/xml -d"<root><query>bar</query></root>"
14
+ render "bar.xml"
15
+ end
16
+
17
+ # if nothing to match, use 404 HTTP Status Code and render default.xml.
18
+ status_code 404
@@ -0,0 +1 @@
1
+ <result>bar.xml</result>
@@ -0,0 +1 @@
1
+ <result>404 not found (dafault.xml)</result>
@@ -0,0 +1 @@
1
+ <result>foo.xml</result>
@@ -0,0 +1,5 @@
1
+ status_code 200
2
+ set_header "Content-Type", "text/plain"
3
+
4
+ # You can omit below if you use default file.
5
+ # render "default"
@@ -0,0 +1 @@
1
+ edit me: <%= target_file_path %>
@@ -0,0 +1 @@
1
+ port: 9292
@@ -0,0 +1,8 @@
1
+ # set HTTP status code (default: 200)
2
+ status_code 200
3
+
4
+ # set HTTP Header
5
+ set_header "content-type", "text/plain"
6
+
7
+ # select response file
8
+ render "default"
@@ -0,0 +1,3 @@
1
+ Hey, I am cameleon!
2
+ Edit response folder to change response whatever you want.
3
+ see README.md more detail.
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+ require 'shoulda'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'cameleon'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,4 @@
1
+ require 'helper'
2
+
3
+ class TestCameleon < Test::Unit::TestCase
4
+ end
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cameleon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - daixque
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-11 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: erubis
16
+ requirement: &2156026340 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *2156026340
25
+ - !ruby/object:Gem::Dependency
26
+ name: rack
27
+ requirement: &2156019320 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *2156019320
36
+ - !ruby/object:Gem::Dependency
37
+ name: hashie
38
+ requirement: &2156012980 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *2156012980
47
+ - !ruby/object:Gem::Dependency
48
+ name: json
49
+ requirement: &2156005480 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *2156005480
58
+ - !ruby/object:Gem::Dependency
59
+ name: nokogiri
60
+ requirement: &2156000260 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *2156000260
69
+ - !ruby/object:Gem::Dependency
70
+ name: shoulda
71
+ requirement: &2155995580 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *2155995580
80
+ - !ruby/object:Gem::Dependency
81
+ name: bundler
82
+ requirement: &2155991700 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ~>
86
+ - !ruby/object:Gem::Version
87
+ version: 1.0.0
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *2155991700
91
+ - !ruby/object:Gem::Dependency
92
+ name: jeweler
93
+ requirement: &2155982160 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ~>
97
+ - !ruby/object:Gem::Version
98
+ version: 1.6.4
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *2155982160
102
+ - !ruby/object:Gem::Dependency
103
+ name: rcov
104
+ requirement: &2155978480 !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: *2155978480
113
+ description: Cameleon is HTTP mock server framework based on Rack. You can easily
114
+ create HTTP server for mockup or stub of external system for your application.
115
+ email: daixque@gmail.com
116
+ executables:
117
+ - cameleon
118
+ extensions: []
119
+ extra_rdoc_files:
120
+ - LICENSE.txt
121
+ - README.md
122
+ files:
123
+ - .document
124
+ - Gemfile
125
+ - LICENSE.txt
126
+ - README.md
127
+ - Rakefile
128
+ - VERSION
129
+ - bin/cameleon
130
+ - cameleon.gemspec
131
+ - lib/cameleon.rb
132
+ - lib/cameleon/action.rb
133
+ - lib/cameleon/app.rb
134
+ - lib/cameleon/cli.rb
135
+ - lib/cameleon/cli/gallery.rb
136
+ - lib/cameleon/cli/generate.rb
137
+ - lib/cameleon/cli/new.rb
138
+ - lib/cameleon/cli/server.rb
139
+ - lib/cameleon/renderer.rb
140
+ - template/gallery/response/gallery/erb/default.txt
141
+ - template/gallery/response/gallery/json/_switch.rb
142
+ - template/gallery/response/gallery/json/bar.json
143
+ - template/gallery/response/gallery/json/default.json
144
+ - template/gallery/response/gallery/json/foo.json
145
+ - template/gallery/response/gallery/params/_switch.rb
146
+ - template/gallery/response/gallery/params/bar.txt
147
+ - template/gallery/response/gallery/params/default.txt
148
+ - template/gallery/response/gallery/params/foo.txt
149
+ - template/gallery/response/gallery/rest/_switch.rb
150
+ - template/gallery/response/gallery/rest/delete.txt
151
+ - template/gallery/response/gallery/rest/get.txt
152
+ - template/gallery/response/gallery/rest/put_or_post.txt
153
+ - template/gallery/response/gallery/simple/default.txt
154
+ - template/gallery/response/gallery/xml/_switch.rb
155
+ - template/gallery/response/gallery/xml/bar.xml
156
+ - template/gallery/response/gallery/xml/default.xml
157
+ - template/gallery/response/gallery/xml/foo.xml
158
+ - template/generate/_switch.rb
159
+ - template/generate/default
160
+ - template/new/cameleon.yml
161
+ - template/new/response/_root/_switch.rb
162
+ - template/new/response/_root/default
163
+ - test/helper.rb
164
+ - test/test_cameleon.rb
165
+ homepage: http://github.com/daixque/cameleon
166
+ licenses:
167
+ - MIT
168
+ post_install_message:
169
+ rdoc_options: []
170
+ require_paths:
171
+ - lib
172
+ required_ruby_version: !ruby/object:Gem::Requirement
173
+ none: false
174
+ requirements:
175
+ - - ! '>='
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ segments:
179
+ - 0
180
+ hash: -2425352503709104828
181
+ required_rubygems_version: !ruby/object:Gem::Requirement
182
+ none: false
183
+ requirements:
184
+ - - ! '>='
185
+ - !ruby/object:Gem::Version
186
+ version: '0'
187
+ requirements: []
188
+ rubyforge_project:
189
+ rubygems_version: 1.8.6
190
+ signing_key:
191
+ specification_version: 3
192
+ summary: Cameleon is HTTP mock server framework.
193
+ test_files: []