cuba-api 0.2.0 → 0.3.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.
data/README.md CHANGED
@@ -7,6 +7,11 @@ cuba-api
7
7
 
8
8
  these are just a handful for [cuba](https://github.com/soveran/cuba) to use cuba as API server.
9
9
 
10
+ security
11
+ --------
12
+
13
+ cuba-api installs the **safe_yaml** gem and will use it when you accept yaml input. installing **safe_yaml** is a bit invasiv, but better be on the safe side of things.
14
+
10
15
  cuba\_-api/config.rb
11
16
  ------------------
12
17
 
@@ -46,26 +46,15 @@ module CubaApi
46
46
  end
47
47
 
48
48
  def accept_content( obj, options = {} )
49
- script = env[ 'SCRIPT_NAME' ]
50
- if script =~ /\./
51
- extension = script.sub( /^.*\./, '' )
52
- mime = ClassMethods::MIMES[ extension.to_sym ] || []
53
- _accept( obj, mime.first )
54
- else
55
- _accept( obj, env[ 'HTTP_ACCEPT' ] )
56
- end
57
- end
58
-
59
- def _accept( obj, mime )
49
+ mime = env[ 'HTTP_ACCEPT' ]
60
50
  if self.class.mimes.key?( mime )
61
51
  res[ "Content-Type" ] = mime + "; charset=utf-8"
62
52
  obj.send self.class[ :mimes ][ mime ]
63
53
  else
64
- head 404
54
+ head :not_found
65
55
  nil
66
56
  end
67
57
  end
68
- private :_accept
69
58
 
70
59
  def self.included( base )
71
60
  base.append_aspect :accept_content
@@ -0,0 +1,19 @@
1
+ module CubaApi
2
+ class Ext2MimeRack
3
+ def initialize( app, *allowed)
4
+ @app = app
5
+ @allowed = allowed
6
+ end
7
+
8
+ def call(env)
9
+ ext = env[ 'PATH_INFO' ].sub( /.*\./, '' )
10
+ if ext && @allowed.member?( ext )
11
+ mime = Rack::Mime.mime_type( '.' + ext )
12
+ env[ 'PATH_INFO_ORIG' ] = env[ 'PATH_INFO' ].dup
13
+ env[ 'HTTP_ACCEPT' ] = mime
14
+ env[ 'PATH_INFO' ].sub!( /\..*/, '' )
15
+ end
16
+ status, headers, body = @app.call(env)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ module CubaApi
2
+ class Ext2MimeRack
3
+ def initialize( app, *allowed)
4
+ @app = app
5
+ @allowed = allowed
6
+ end
7
+
8
+ def call(env)
9
+ ext = env[ 'PATH_INFO' ].sub( /.*\./, '' )
10
+ if ext && @allowed.member?( ext )
11
+ mime = Rack::Mime.mime_type( '.' + ext )
12
+ env[ 'HTTP_ACCEPT' ] = mime
13
+ env[ 'PATH_INFO' ].sub!( /\..*/, '' )
14
+ end
15
+ status, headers, body = @app.call(env)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,50 @@
1
+ module CubaApi
2
+ class Reloader
3
+
4
+ def self.parse( basedir, baseconstant )
5
+ Dir[ File.join( basedir, '**', '*.rb' ) ].each do |f|
6
+ last_modified = File.mtime( f ).to_f
7
+ if ! File.directory?( f ) && last_modified > @max_last_modified.to_f
8
+ @max_last_modified = last_modified
9
+ yield f
10
+ end
11
+ end
12
+ end
13
+
14
+ def self.maybe_remove_constant( f, basedir, baseconstant )
15
+ c = baseconstant
16
+ cname = nil
17
+ f.sub( /#{basedir}/, '' ).split( /\/|\./ ).each do |name|
18
+ if name != 'rb'
19
+ ( c = c.const_get( cname ) ) rescue nil
20
+ cname = name.split('_').each { |a| a.capitalize! }.join.to_sym
21
+ end
22
+ end
23
+ c.send( :remove_const, cname ) rescue nil
24
+ end
25
+
26
+ def self.doit( basedir, baseconstant )
27
+ if @max_last_modified
28
+ parse( basedir, baseconstant ) do |f|
29
+ maybe_remove_constant( f, basedir, baseconstant )
30
+ puts "[CubaAPI::Reloader] #{f}: #{load f}"
31
+ end
32
+ else
33
+ parse( basedir, baseconstant ) {}
34
+ end
35
+ end
36
+ end
37
+
38
+ class ReloaderRack
39
+ def initialize( app, basedir, baseconstant)
40
+ @app = app
41
+ @basedir = basedir
42
+ @baseconstant = baseconstant
43
+ end
44
+
45
+ def call(env)
46
+ Reloader.doit( @basedir, @baseconstant )
47
+ status, headers, body = @app.call(env)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ module CubaApi
2
+ class Ext2MimeRack
3
+ def initialize( app, *allowed)
4
+ @app = app
5
+ @allowed = allowed
6
+ end
7
+
8
+ def call(env)
9
+ status, headers, body = @app.call(env)
10
+ end
11
+ end
12
+ end
@@ -7,7 +7,7 @@ module CubaApi
7
7
  obj = obj.errors
8
8
  elsif req.post?
9
9
  res.status = 201 # Created
10
- if obj.respond_to?( :id )
10
+ if obj.respond_to?( :id ) && ! res[ 'Location' ]
11
11
  res[ 'Location' ] = env[ 'SCRIPT_NAME' ].to_s+ "/#{obj.id}"
12
12
  end
13
13
  elsif req.delete?
@@ -0,0 +1,49 @@
1
+ module CubaApi
2
+ module Utils
3
+
4
+ def to_float( name, default = nil )
5
+ v = req[ name ]
6
+ if v
7
+ v.to_f
8
+ else
9
+ default
10
+ end
11
+ end
12
+
13
+ def to_int( name, default = nil )
14
+ v = req[ name ]
15
+ if v
16
+ v.to_i
17
+ else
18
+ default
19
+ end
20
+ end
21
+
22
+ def offset_n_limit( method, set )
23
+ count = set.count
24
+ offset = to_int( 'offset' ).to_i
25
+ limit = ( to_int( 'count' ) || count ) - 1 + offset
26
+ { method => set[ offset..limit ], :offset => offset, :total_count => count }
27
+ end
28
+
29
+ def last_modified( last )
30
+ res[ 'Last-Modified' ] = last.rfc2822
31
+ end
32
+
33
+ def modified_since
34
+ @modified_since ||=
35
+ if date = env[ 'HTTP_IF_MODIFIED_SINCE' ]
36
+ DateTime.parse( date )
37
+ end
38
+ end
39
+
40
+ def expires_in( minutes )
41
+ now = DateTime.now
42
+ res[ 'Expires' ] = ( now + minutes / 1440.0 ).rfc2822
43
+ end
44
+
45
+ def content_type( mime )
46
+ res[ 'Content-Type' ] = mime if mime
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,42 @@
1
+ module CubaApi
2
+ module Utils
3
+
4
+ def to_float( name, default = nil )
5
+ v = req[ name ]
6
+ if v
7
+ v.to_f
8
+ else
9
+ default
10
+ end
11
+ end
12
+
13
+ def to_int( name, default = nil )
14
+ v = req[ name ]
15
+ if v
16
+ v.to_i
17
+ else
18
+ default
19
+ end
20
+ end
21
+
22
+ def offset_n_limit( method, set )
23
+ count = set.count
24
+ offset = to_int( 'offset' ).to_i
25
+ limit = ( to_int( 'count' ) || count ) - 1 + offset
26
+ { method => set[ offset..limit ], :offset => offset, :total_count => count }
27
+ end
28
+
29
+ def last_modified( last )
30
+ res[ 'Last-Modified' ] = last.rfc2822
31
+ end
32
+
33
+ def expires_in( minutes )
34
+ now = DateTime.now
35
+ res[ 'Expires' ] = ( now + minutes / 1440.0 ).rfc2822
36
+ end
37
+
38
+ def content_type( mime )
39
+ header[ 'Content-Type' ] = mime
40
+ end
41
+ end
42
+ end
@@ -40,8 +40,9 @@ module CubaApi
40
40
  end
41
41
 
42
42
  def head( status )
43
- res.status = status
44
- res.write ''
43
+ res.status = Rack::Utils.status_code( status )
44
+ res.write Rack::Utils::HTTP_STATUS_CODES[ res.status ]
45
+ res['Content-Type' ] = 'text/plain'
45
46
  end
46
47
 
47
48
  def write( obj, options = {} )
data/spec/accept_spec.rb CHANGED
@@ -31,7 +31,7 @@ describe CubaApi::AcceptContent do
31
31
 
32
32
  _, _, resp = Cuba.call({"SCRIPT_NAME" => "/bla.yaml"})
33
33
  resp[ 0 ] = resp[ 0 ].sub(/.*!/, "---!").sub( /\n\n/, "\n")
34
- resp.join.must.eq "---!ruby/object:B {}\n"
34
+ resp.join.must.eq "Not Found"
35
35
 
36
36
  _, _, resp = Cuba.call({"HTTP_ACCEPT" => "application/x-yaml"})
37
37
  resp[ 0 ] = resp[ 0 ].sub(/.*!/, "---!").sub( /\n\n/, "\n")
@@ -53,11 +53,9 @@ describe CubaApi::AcceptContent do
53
53
  it 'gives preference to script extension' do
54
54
  skip("to_yaml add extra line with ...") if defined?( JRUBY_VERSION ) and (( JRUBY_VERSION =~ /^1.6./ ) == 0 ) and ( nil == (RUBY_VERSION =~ /^1.8/) )
55
55
 
56
- _, _, resp = Cuba.call({"SCRIPT_NAME" => "/bla.yaml", "HTTP_ACCEPT" => "application/xml"})
56
+ status, _, resp = Cuba.call({"SCRIPT_NAME" => "/bla.yaml", "HTTP_ACCEPT" => "application/xml"})
57
57
  resp[ 0 ] = resp[ 0 ].sub(/.*!/, "---!").sub( /\n\n/, "\n")
58
- resp.join.must.eq "---!ruby/object:B {}\n"
59
-
60
- status, _, _ = Cuba.call({"SCRIPT_NAME" => "/bla.xml", "HTTP_ACCEPT" => "application/x-yaml"})
58
+ resp.join.must.eq "Not Found"
61
59
  status.must.eq 404
62
60
  end
63
61
  end
data/spec/spec_helper.rb CHANGED
@@ -2,3 +2,20 @@ require 'cuba'
2
2
  ENV["MT_NO_EXPECTATIONS"] = "true"
3
3
 
4
4
  require 'mustard'
5
+
6
+ module Mustard
7
+ class Failure < MiniTest::Assertion
8
+ def initialize( *args )
9
+ super
10
+ begin
11
+ raise
12
+ rescue => e
13
+ @result = e.backtrace.detect { |l| nil == ( l =~ /lib\/mustard/ || l =~ /spec\/spec_helper.rb/ ) }
14
+ end
15
+ end
16
+
17
+ def backtrace
18
+ [@result]
19
+ end
20
+ end
21
+ end
metadata CHANGED
@@ -2,14 +2,14 @@
2
2
  name: cuba-api
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.0
5
+ version: 0.3.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Christian Meier
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-02 00:00:00.000000000 Z
12
+ date: 2013-02-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cuba
@@ -49,13 +49,13 @@ dependencies:
49
49
  requirements:
50
50
  - - "~>"
51
51
  - !ruby/object:Gem::Version
52
- version: '0.5'
52
+ version: '0.8'
53
53
  none: false
54
54
  requirement: !ruby/object:Gem::Requirement
55
55
  requirements:
56
56
  - - "~>"
57
57
  - !ruby/object:Gem::Version
58
- version: '0.5'
58
+ version: '0.8'
59
59
  none: false
60
60
  prerelease: false
61
61
  type: :runtime
@@ -166,8 +166,11 @@ files:
166
166
  - README.md
167
167
  - lib/cuba_api.rb
168
168
  - lib/cuba_api.rb~
169
+ - lib/cuba_api/reloader_rack.rb~
169
170
  - lib/cuba_api/input_filter.rb~
170
171
  - lib/cuba_api/write_aspects.rb~
172
+ - lib/cuba_api/ext2mime_rack.rb~
173
+ - lib/cuba_api/utils.rb
171
174
  - lib/cuba_api/guard.rb
172
175
  - lib/cuba_api/serializer.rb~
173
176
  - lib/cuba_api/accept_content.rb~
@@ -182,8 +185,11 @@ files:
182
185
  - lib/cuba_api/guard.rb~
183
186
  - lib/cuba_api/accept_content.rb
184
187
  - lib/cuba_api/config.rb~
188
+ - lib/cuba_api/utils.rb~
189
+ - lib/cuba_api/reloader_rack.rb
185
190
  - lib/cuba_api/serializer.rb
186
191
  - lib/cuba_api/response_status.rb
192
+ - lib/cuba_api/ext2mime_rack.rb
187
193
  - spec/serializer_spec.rb
188
194
  - spec/input_filter_spec.rb~
189
195
  - spec/config_spec.rb~