Permalink
Browse files

First real version of the JsonRPC gem

  • Loading branch information...
1 parent 2b30b8a commit b885ca588deed6e70dffb5b05bd5aea1638ed53c @dbussink committed Dec 19, 2008
Showing with 537 additions and 0 deletions.
  1. +7 −0 .gitignore
  2. +20 −0 LICENSE
  3. +5 −0 README
  4. +49 −0 Rakefile
  5. +32 −0 lib/jsonrpc.rb
  6. +6 −0 lib/jsonrpc/exceptions.rb
  7. +11 −0 lib/jsonrpc/version.rb
  8. +94 −0 spec/jsonrpc_spec.rb
  9. +2 −0 tasks/clobber.rake
  10. +68 −0 tasks/gem.rake
  11. +40 −0 tasks/git.rake
  12. +22 −0 tasks/metrics.rake
  13. +29 −0 tasks/rdoc.rake
  14. +89 −0 tasks/rubyforge.rake
  15. +63 −0 tasks/spec.rake
View
@@ -0,0 +1,7 @@
+*.log
+log/*
+doc
+cov
+pkg
+.DS_Store
+coverage/*
View
20 LICENSE
@@ -0,0 +1,20 @@
+JsonRPC, Copyright (c) 2008 Dirkjan Bussink
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
5 README
@@ -0,0 +1,5 @@
+Extremely simple Ruby JSON RPC Client
+
+This plugin lets you easily call methods over a JSON RPC interface. It
+currently implements the bare minimum, feel free to submit pull requests
+if you implement additional functionality.
View
@@ -0,0 +1,49 @@
+lib_dir = File.expand_path(File.join(File.dirname(__FILE__), "lib"))
+$:.unshift(lib_dir)
+$:.uniq!
+
+require 'rubygems'
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+require 'rake/packagetask'
+require 'rake/gempackagetask'
+require 'rake/contrib/rubyforgepublisher'
+require 'spec/rake/spectask'
+
+require File.join(File.dirname(__FILE__), 'lib/jsonrpc', 'version')
+
+PKG_DISPLAY_NAME = 'JsonRPC'
+PKG_NAME = PKG_DISPLAY_NAME.downcase
+PKG_VERSION = JsonRPC::VERSION::STRING
+PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
+
+RELEASE_NAME = "REL #{PKG_VERSION}"
+
+RUBY_FORGE_PROJECT = PKG_NAME
+RUBY_FORGE_USER = "dbussink"
+RUBY_FORGE_PATH = "/var/www/gforge-projects/#{RUBY_FORGE_PROJECT}"
+RUBY_FORGE_URL = "http://#{RUBY_FORGE_PROJECT}.rubyforge.org/"
+
+PKG_SUMMARY = "JSON RPC implementation"
+PKG_DESCRIPTION = <<-TEXT
+Very simple JSON RPC client implementation
+TEXT
+
+PKG_FILES = FileList[
+ "lib/**/*", "spec/**/*", "vendor/**/*",
+ "tasks/**/*", "website/**/*",
+ "[A-Z]*", "Rakefile"
+].exclude(/database\.yml/).exclude(/[_\.]git$/)
+
+RCOV_ENABLED = (RUBY_PLATFORM != "java" && RUBY_VERSION =~ /^1\.8/)
+if RCOV_ENABLED
+ task :default => "spec:verify"
+else
+ task :default => "spec"
+end
+
+WINDOWS = (RUBY_PLATFORM =~ /mswin|win32|mingw|bccwin|cygwin/) rescue false
+SUDO = WINDOWS ? '' : ('sudo' unless ENV['SUDOLESS'])
+
+Dir['tasks/**/*.rake'].each { |rake| load rake }
View
@@ -0,0 +1,32 @@
+gem 'addressable', '~>2.0.0'
+gem 'json'
+
+require 'net/http'
+require 'addressable/uri'
+require 'json'
+
+require File.expand_path(File.join(File.dirname(__FILE__), 'jsonrpc', 'version'))
+require File.expand_path(File.join(File.dirname(__FILE__), 'jsonrpc', 'exceptions'))
+
+module JsonRPC
+
+ class Client
+
+ def initialize(url)
+ @address = Addressable::URI.parse(url)
+ end
+
+ def request(method, params)
+ result = {}
+ Net::HTTP.start(@address.host, @address.port) do |connection|
+ result = JSON.parse(connection.post(@address.path, {:method => method.to_s, :params => params, :id => @id}.to_json).body)
+ end
+ if error = result["error"]
+ raise JsonRPCError, error["message"]
+ end
+ result
+ end
+
+ end
+
+end
@@ -0,0 +1,6 @@
+module JsonRPC
+
+ class JsonRPCError < StandardError
+ end
+
+end
View
@@ -0,0 +1,11 @@
+if !defined?(JsonRPC::VERSION)
+ module JsonRPC
+ module VERSION #:nodoc:
+ MAJOR = 1
+ MINOR = 0
+ TINY = 0
+
+ STRING = [MAJOR, MINOR, TINY].join('.')
+ end
+ end
+end
View
@@ -0,0 +1,94 @@
+require 'net/http'
+require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'jsonrpc'))
+
+# Mock around Net::HTTP so we don't need a real connection.
+# We just verify whether the correct data is posted and return
+# know test data
+
+class Net::HTTP < Net::Protocol
+ def connect
+ end
+end
+
+class Net::HTTPResponse
+ def body=(content)
+ @body = content
+ @read = true
+ end
+end
+
+class Net::HTTP < Net::Protocol
+
+ def self.raw_response_data
+ @raw_response_data
+ end
+
+ def self.raw_response_data=(data)
+ @raw_response_data = data
+ end
+
+ def self.raw_post_body=(body)
+ @raw_post_body = body
+ end
+
+ def self.raw_post_body
+ @raw_post_body
+ end
+
+ def self.raw_post_path=(path)
+ @raw_post_path = path
+ end
+
+ def self.raw_post_path
+ @raw_post_path
+ end
+
+ def post(path, body, headers = [])
+ res = Net::HTTPSuccess.new('1.2', '200', 'OK')
+ self.class.raw_post_path = path
+ self.class.raw_post_body = body
+ res.body = self.class.raw_response_data
+ res
+ end
+end
+
+describe JsonRPC::Client do
+
+ before do
+ @jsonrpc = JsonRPC::Client.new("http://localhost:4444/api")
+ end
+
+ it { @jsonrpc.should respond_to(:request) }
+
+ describe 'when it is successful' do
+
+ before do
+ @jsonrpc = JsonRPC::Client.new("http://localhost:4444/api")
+ Net::HTTP.raw_response_data = '{"result":200,"message":"what a great success!"}'
+ @result = @jsonrpc.request("test_method", {:param1 => "value1", :param2 => "value2" })
+ end
+
+ it 'should receive the correct call at the http level' do
+ Net::HTTP.raw_post_body.should == '{"params":{"param1":"value1","param2":"value2"},"method":"test_method","id":null}'
+ end
+
+ it 'should correctly parse the response from the server' do
+ @result.should == {"result" => 200, "message" => "what a great success!"}
+ end
+
+ end
+
+ describe 'when it is not successful' do
+
+ before do
+ @jsonrpc = JsonRPC::Client.new("http://localhost:4444/api")
+ Net::HTTP.raw_response_data = '{"result":null,"error":{"message":"something is wrong!"}}'
+ end
+
+ it 'should raise an exception when a call went wrong' do
+ lambda { @jsonrpc.request("test_method", {:param1 => "value1", :param2 => "value2" }) }.should raise_error(JsonRPC::JsonRPCError)
+ end
+
+ end
+
+end
View
@@ -0,0 +1,2 @@
+desc "Remove all build products"
+task "clobber"
View
@@ -0,0 +1,68 @@
+require "rake/gempackagetask"
+
+namespace :gem do
+ GEM_SPEC = Gem::Specification.new do |s|
+ s.name = PKG_NAME
+ s.version = PKG_VERSION
+ s.summary = PKG_SUMMARY
+ s.description = PKG_DESCRIPTION
+
+ s.files = PKG_FILES.to_a
+
+ s.has_rdoc = true
+ s.extra_rdoc_files = %w( README )
+ s.rdoc_options.concat ["--main", "README"]
+
+ if !s.respond_to?(:add_development_dependency)
+ puts "Cannot build Gem with this version of RubyGems."
+ exit(1)
+ end
+
+ s.add_development_dependency("rake", ">= 0.7.3")
+ s.add_development_dependency("rspec", ">= 1.0.8")
+ s.add_development_dependency("launchy", ">= 0.3.2")
+
+ s.require_path = "lib"
+
+ s.author = "Bob Aman"
+ s.email = "bob@sporkmonger.com"
+ s.homepage = RUBY_FORGE_URL
+ s.rubyforge_project = RUBY_FORGE_PROJECT
+ end
+
+ Rake::GemPackageTask.new(GEM_SPEC) do |p|
+ p.gem_spec = GEM_SPEC
+ p.need_tar = true
+ p.need_zip = true
+ end
+
+ desc "Show information about the gem"
+ task :debug do
+ puts GEM_SPEC.to_ruby
+ end
+
+ desc "Install the gem"
+ task :install => ["clobber", "gem:package"] do
+ sh "#{SUDO} gem install --local pkg/#{GEM_SPEC.full_name}"
+ end
+
+ desc "Uninstall the gem"
+ task :uninstall do
+ installed_list = Gem.source_index.find_name(PKG_NAME)
+ if installed_list &&
+ (installed_list.collect { |s| s.version.to_s}.include?(PKG_VERSION))
+ sh(
+ "#{SUDO} gem uninstall --version '#{PKG_VERSION}' " +
+ "--ignore-dependencies --executables #{PKG_NAME}"
+ )
+ end
+ end
+
+ desc "Reinstall the gem"
+ task :reinstall => [:uninstall, :install]
+end
+
+desc "Alias to gem:package"
+task "gem" => "gem:package"
+
+task "clobber" => ["gem:clobber_package"]
View
@@ -0,0 +1,40 @@
+namespace :git do
+ namespace :tag do
+ desc "List tags from the Git repository"
+ task :list do
+ tags = `git tag -l`
+ tags.gsub!("\r", "")
+ tags = tags.split("\n").sort {|a, b| b <=> a }
+ puts tags.join("\n")
+ end
+
+ desc "Create a new tag in the Git repository"
+ task :create do
+ changelog = File.open("CHANGELOG", "r") { |file| file.read }
+ puts "-" * 80
+ puts changelog
+ puts "-" * 80
+ puts
+
+ v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
+ abort "Versions don't match #{v} vs #{PKG_VERSION}" if v != PKG_VERSION
+
+ tag = "#{PKG_NAME}-#{PKG_VERSION}"
+ msg = "Release #{PKG_NAME}-#{PKG_VERSION}"
+
+ existing_tags = `git tag -l instrument-*`.split("\n")
+ if existing_tags.include?(tag)
+ warn("Tag already exists, deleting...")
+ unless system "git tag -d #{tag}"
+ abort "Tag deletion failed."
+ end
+ end
+ puts "Creating git tag '#{tag}'..."
+ unless system "git tag -a -m \"#{msg}\" #{tag}"
+ abort "Tag creation failed."
+ end
+ end
+ end
+end
+
+task "gem:release" => "git:tag:create"
View
@@ -0,0 +1,22 @@
+namespace :metrics do
+ task :lines do
+ lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
+ for file_name in FileList["lib/**/*.rb"]
+ f = File.open(file_name)
+ while line = f.gets
+ lines += 1
+ next if line =~ /^\s*$/
+ next if line =~ /^\s*#/
+ codelines += 1
+ end
+ puts "L: #{sprintf("%4d", lines)}, " +
+ "LOC #{sprintf("%4d", codelines)} | #{file_name}"
+ total_lines += lines
+ total_codelines += codelines
+
+ lines, codelines = 0, 0
+ end
+
+ puts "Total: Lines #{total_lines}, LOC #{total_codelines}"
+ end
+end
View
@@ -0,0 +1,29 @@
+require "rake/rdoctask"
+
+namespace :doc do
+ desc "Generate RDoc documentation"
+ Rake::RDocTask.new do |rdoc|
+ rdoc.rdoc_dir = "doc"
+ rdoc.title = "#{PKG_NAME}-#{PKG_VERSION} Documentation"
+ rdoc.options << "--line-numbers" << "--inline-source" <<
+ "--accessor" << "cattr_accessor=object" << "--charset" << "utf-8"
+ rdoc.template = "#{ENV["template"]}.rb" if ENV["template"]
+ rdoc.rdoc_files.include("README", "CHANGELOG", "LICENSE")
+ rdoc.rdoc_files.include("lib/**/*.rb")
+ end
+
+ desc "Generate ri locally for testing"
+ task :ri do
+ sh "rdoc --ri -o ri ."
+ end
+
+ desc "Remove ri products"
+ task :clobber_ri do
+ rm_r "ri" rescue nil
+ end
+end
+
+desc "Alias to doc:rdoc"
+task "doc" => "doc:rdoc"
+
+task "clobber" => ["doc:clobber_rdoc", "doc:clobber_ri"]
Oops, something went wrong.

0 comments on commit b885ca5

Please sign in to comment.