cameleon 0.1.0

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.
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: []