cryx-g5k 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,47 @@
1
+ module G5K
2
+ module Parsing
3
+ class UnsupportedFormat < StandardError; end
4
+ class Parser
5
+ @@parsers = []
6
+ def self.add(*parsers)
7
+ parsers.each{ |parser|
8
+ parser.dependencies
9
+ @@parsers << parser
10
+ }
11
+ self
12
+ end
13
+ def self.select(parser_format)
14
+ raise UnsupportedFormat, "The format cannot be nil." if parser_format.nil?
15
+ parsers = @@parsers.select{|parser| parser.supported_formats.include?(parser_format.to_sym)}
16
+ if parsers.empty?
17
+ raise UnsupportedFormat, "No parser found for '#{parser_format}' format."
18
+ else
19
+ parsers.first
20
+ end
21
+ end
22
+ def self.available_parsers; @@parsers; end
23
+ end
24
+
25
+ class JSONParser
26
+ def self.dependencies
27
+ require 'json'
28
+ end
29
+ def self.supported_formats
30
+ [:json]
31
+ end
32
+ def self.dump(object, options = {:format => :pretty})
33
+ case options[:format]
34
+ when :pretty
35
+ JSON.pretty_generate object
36
+ else
37
+ object.to_json
38
+ end
39
+ end
40
+ def self.load(object)
41
+ JSON.parse(object)
42
+ end
43
+ end
44
+
45
+ # Parser.add(JSONParser)
46
+ end
47
+ end
@@ -0,0 +1,7 @@
1
+ require File.dirname(__FILE__)+'/parsing/parser.rb'
2
+
3
+ module G5K
4
+ module Parsing
5
+ VERSION = 0.1
6
+ end
7
+ end
@@ -0,0 +1,46 @@
1
+ module G5K
2
+ module Rack
3
+ #
4
+ # A Rack middleware for automatically adding a <tt>format</tt> token at the end of the request path
5
+ # when there is none. It can detect formats passed in the HTTP_ACCEPT header to populate this token.
6
+ #
7
+ # e.g.:
8
+ # GET /some/resource HTTP/1.1
9
+ # Accept: application/json
10
+ # ->
11
+ # GET /some/resource.json HTTP/1.1
12
+ # Accept: application/json
13
+ #
14
+ # You can add custom types with this kind of function (taken from sinatra):
15
+ # def mime(ext, type)
16
+ # ext = ".#{ext}" unless ext.to_s[0] == ?.
17
+ # Rack::Mime::MIME_TYPES[ext.to_s] = type
18
+ # end
19
+ # and then:
20
+ # mime :json, 'application/json'
21
+ #
22
+ # Note: it does not take into account multiple media types in the Accept header.
23
+ # The first media type takes precedence over all the others.
24
+ #
25
+ # MIT-License - Cyril Rohr
26
+ #
27
+ class AcceptFormat
28
+ # Constants
29
+ DEFAULT_EXTENSION = ".html"
30
+
31
+ def initialize(app)
32
+ @app = app
33
+ end
34
+
35
+ def call(env)
36
+ req = Rack::Request.new(env)
37
+ unless req.path_info =~ /(.*)\.(.+)/
38
+ accept = env['HTTP_ACCEPT'].scan(/[^;,\s]*\/[^;,\s]*/)[0] rescue ""
39
+ extension = Rack::Mime::MIME_TYPES.invert[accept] || DEFAULT_EXTENSION
40
+ req.path_info = req.path_info+"#{extension}"
41
+ end
42
+ @app.call(env)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,43 @@
1
+ module G5K
2
+ module Rack
3
+
4
+ # A Rack middleware for providing JSON-P support.
5
+ #
6
+ # Full credit to Flinn Mueller (http://actsasflinn.com/) for this contribution.
7
+ #
8
+ class JSONP
9
+
10
+ def initialize(app)
11
+ @app = app
12
+ end
13
+
14
+ # Proxies the request to the application, stripping out the JSON-P callback
15
+ # method and padding the response with the appropriate callback format.
16
+ #
17
+ # Changes nothing if no <tt>callback</tt> param is specified.
18
+ #
19
+ def call(env)
20
+ status, headers, response = @app.call(env)
21
+ request = Rack::Request.new(env)
22
+ if request.params.include?('callback')
23
+ response = pad(request.params.delete('callback'), response)
24
+ headers['Content-Length'] = response.length.to_s
25
+ end
26
+ [status, headers, response]
27
+ end
28
+
29
+ # Pads the response with the appropriate callback format according to the
30
+ # JSON-P spec/requirements.
31
+ #
32
+ # The Rack response spec indicates that it should be enumerable. The method
33
+ # of combining all of the data into a single string makes sense since JSON
34
+ # is returned as a full string.
35
+ #
36
+ def pad(callback, response, body = "")
37
+ response.each{ |s| body << s }
38
+ "#{callback}(#{body})"
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,32 @@
1
+ module G5K
2
+ module Sinatra
3
+ module Helpers
4
+ def returning(thing = nil)
5
+ yield thing
6
+ thing
7
+ end
8
+
9
+ def provides *formats
10
+ if params[:format].nil? || !formats.include?(params[:format].to_sym)
11
+ throw :halt, [406, "The accepted types are: #{formats.join(", ")}"]
12
+ end
13
+ end
14
+
15
+ def formatted_error(http_status, options = {})
16
+ body = {:code => (options[:code] || http_status), :message => options[:message], :title => options[:title]}
17
+ format = options[:format] || params[:format] || "txt"
18
+ content_type format.to_sym, :charset => 'utf-8'
19
+ if (parser = Parser.select(format.to_sym))
20
+ body = parser.dump(body)
21
+ else
22
+ body.map!{|(k,v)| [k,v].join("=")}.join(";")
23
+ end
24
+ error(http_status, body)
25
+ end
26
+
27
+ def compute_etag(*differentiators)
28
+ Digest::SHA1.hexdigest(differentiators.join("."))
29
+ end
30
+ end
31
+ end
32
+ end
data/lib/g5k.rb ADDED
@@ -0,0 +1,5 @@
1
+ # Subdirs are not automatically loaded. Users must explicitly require them.
2
+
3
+ module G5K
4
+
5
+ end
data/spec/g5k_spec.rb ADDED
@@ -0,0 +1,4 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+
3
+ describe "G5k" do
4
+ end
@@ -0,0 +1,44 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require File.dirname(__FILE__) + '/../lib/g5k/parsing'
3
+
4
+ include G5K::Parsing
5
+ describe "Parsing" do
6
+ before do
7
+ require 'rubygems'
8
+ end
9
+ it "should add the json parser" do
10
+ Parser.add(JSONParser).available_parsers.should include(JSONParser)
11
+ end
12
+ it "should return an error if a parser is not available for the required format" do
13
+ Parser.add(JSONParser)
14
+ lambda{Parser.select(:xml)}.should raise_error(UnsupportedFormat)
15
+ end
16
+ it "should raise an UnsupportedFormat if the given format is nil" do
17
+ lambda{Parser.select(nil)}.should raise_error(UnsupportedFormat)
18
+ end
19
+ it "should select the parser for the given format, if made available" do
20
+ Parser.add(JSONParser)
21
+ Parser.select(:json).should == JSONParser
22
+ end
23
+ end
24
+
25
+ describe JSONParser do
26
+ before do
27
+ require 'rubygems'
28
+ end
29
+ it "should successfully parse a json object" do
30
+ object = {'a' => 1, 'b' => {'c' => 2, 'd' => [3]}}
31
+ JSONParser.load(object.to_json).should == object
32
+ end
33
+ it "should pretty generate an object" do
34
+ object = {'a' => 1, 'b' => {'c' => 2, 'd' => [3]}}
35
+ JSON.should_receive(:pretty_generate).with(object)
36
+ JSONParser.dump(object, :format => :pretty)
37
+ end
38
+ it "should not pretty generate an object" do
39
+ object = {'a' => 1, 'b' => {'c' => 2, 'd' => [3]}}
40
+ JSON.should_not_receive(:pretty_generate).with(object)
41
+ object.should_receive(:to_json)
42
+ JSONParser.dump(object, :format => :raw)
43
+ end
44
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec'
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+
5
+ require File.dirname(__FILE__) + '/../lib/g5k'
6
+
7
+ Spec::Runner.configure do |config|
8
+
9
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cryx-g5k
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Cyril Rohr
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-02 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Collection of tools and libs for Grid5000 APIs.
17
+ email: cyril.rohr@irisa.fr
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - VERSION.yml
26
+ - lib/g5k
27
+ - lib/g5k/parsing
28
+ - lib/g5k/parsing/parser.rb
29
+ - lib/g5k/parsing.rb
30
+ - lib/g5k/rack
31
+ - lib/g5k/rack/accept_format.rb
32
+ - lib/g5k/rack/jsonp.rb
33
+ - lib/g5k/schema
34
+ - lib/g5k/sinatra
35
+ - lib/g5k/sinatra/helpers.rb
36
+ - lib/g5k.rb
37
+ - spec/g5k_spec.rb
38
+ - spec/parsing_spec.rb
39
+ - spec/spec_helper.rb
40
+ has_rdoc: true
41
+ homepage: http://github.com/cryx/g5k
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --inline-source
45
+ - --charset=UTF-8
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.2.0
64
+ signing_key:
65
+ specification_version: 2
66
+ summary: TODO
67
+ test_files: []
68
+