strelka 0.4.0 → 0.5.0.pre.393

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 58ca9bc4fbcc4953f0b9fb9b15407b726b0a9512
4
- data.tar.gz: 946729ae577f2cd5496b3a14542094abb35ec907
3
+ metadata.gz: 1d2cffaf505aa41496b0ce345534e70d6f4b45a0
4
+ data.tar.gz: c922b2aa4deafe3472b9be7d2d960237dc2e2b11
5
5
  SHA512:
6
- metadata.gz: 429cab795c50159c7fdad07e17ecf0da7dbf6d43ef6e5798752d942a371dd592292815393c89563a0f29da887943b576fc7580a3d7ac1b06c091bae56d66bd99
7
- data.tar.gz: 27c80311955501589a68d377e90c4c532f3acd3a074c648a4d5ea9eefc9246a6eb8669793c07583146bb9ef3cdd0e689440b8912dd37f82ac703f4a34d5a7b64
6
+ metadata.gz: 295a62542aae175dd4c70d425fc70f43d314412db557a01989aa63b015931cdf20cad5793fefd4e15a237f49d0f50a17c95b72b5905f321a260520ba4c13e06f
7
+ data.tar.gz: 590d6dfab3b2a652e916b9e78ad497440b5e5de314abbd12b5c289fd917d43a1c9e4b212ec55fdc2d030693ef312ea44d8ce0b530c140ee5c714241388a0ae0d
checksums.yaml.gz.sig CHANGED
@@ -1 +1 @@
1
- ���~&U�ϱ�ʺ��� ��ؿ�G��!$) e���'F��n���z_a���a�4��'��v@ھ��$��ev�\�a:��#'�����j+��*�A��jM�!�z1ע8xs��ѷILR���\ ~_'�/�m��1hr<i����S���pfj ��'Z���yu�����:ϟe���h�q ��@t�ԭc���y���hQ��gq���iv���t)��TK� �%~E ��勐>l�-e
1
+ Q�]O$SS������U��pMAxq�T6��b?g7, ���C�����:�;|vN��ϤY�-�DΚ˴����[h���ŝ�t��؎���D���æ�}�٧л��^[h�o���ަ�5鑉gU��ַӢ�O�AOe���2�N���8�����L�dB����2��Ry~�����1�с�L'%A��B�:�@00!Cu���4��YQb[J-��3g�r�+�<DUb��
data/Rakefile CHANGED
@@ -27,7 +27,7 @@ hoespec = Hoe.spec 'strelka' do
27
27
  self.dependency 'inversion', '~> 0.12'
28
28
  self.dependency 'loggability', '~> 0.5'
29
29
  self.dependency 'mongrel2', '~> 0.36'
30
- self.dependency 'pluggability', '~> 0.0'
30
+ self.dependency 'pluggability', '~> 0.2'
31
31
  self.dependency 'sysexits', '~> 1.1'
32
32
  self.dependency 'trollop', '~> 2.0'
33
33
  self.dependency 'uuidtools', '~> 2.1'
@@ -21,21 +21,7 @@ require 'strelka/httpresponse/negotiation'
21
21
  #
22
22
  # plugins :routing, :negotiation
23
23
  #
24
- # add_content_type :tnetstring, 'text/x-tnetstring' do |response|
25
- # tnetstr = nil
26
- # begin
27
- # response.body.rewind
28
- # tnetstr = TNetString.dump( response.body )
29
- # rescue => err
30
- # self.log.error "%p while transforming entity body to a TNetString: %s" %
31
- # [ err.class, err.message ]
32
- # return false
33
- # else
34
- # response.body = tnetstr
35
- # response.content_type = 'text/x-tnetstring'
36
- # return true
37
- # end
38
- # end
24
+ # add_content_type :tnetstring, 'text/x-tnetstring', TNetstring.method( :dump )
39
25
  #
40
26
  # end # class UserService
41
27
  #
@@ -50,31 +36,16 @@ module Strelka::App::Negotiation
50
36
  # Class methods to add to classes with content-negotiation.
51
37
  module ClassMethods # :nodoc:
52
38
 
53
- # Content-type tranform registry, keyed by name
54
- @content_type_transforms = {}
55
- attr_reader :content_type_transforms
56
-
57
- # Content-type transform names, keyed by mimetype
58
- @transform_names = {}
59
- attr_reader :transform_names
60
-
61
-
62
- ### Extension callback -- add instance variables to extending objects.
63
- def inherited( subclass )
64
- super
65
- subclass.instance_variable_set( :@content_type_transforms, @content_type_transforms.dup )
66
- subclass.instance_variable_set( :@transform_names, @transform_names.dup )
67
- end
68
-
69
-
70
39
  ### Define a new media-type associated with the specified +name+ and +mimetype+. Responses
71
- ### whose requests accept content of the given +mimetype+ will pass their response to the
72
- ### specified +transform_block+, which should re-write the response's entity body if it can
73
- ### transform it to its mimetype. If it successfully does so, it should return +true+, else
74
- ### the next-best mimetype's transform will be called, etc.
75
- def add_content_type( name, mimetype, &transform_block )
76
- self.transform_names[ mimetype ] = name
77
- self.content_type_transforms[ name ] = transform_block
40
+ ### whose requests accept content of the given +mimetype+ will #call the
41
+ ### specified +callback+ with the current response body, and should return the
42
+ ### transformed body. If the conversion failed, the callback can either raise an
43
+ ### exception or return +nil+, either of which will continue on to any remaining
44
+ ### transforms. If no +callback+ is given, the method's block will be used.
45
+ def add_content_type( name, mimetype, callback=nil ) # :yield: response.body
46
+ callback ||= Proc.new # Use the block
47
+ Strelka::HTTPResponse::Negotiation.mimetype_map[ name.to_sym ] = mimetype
48
+ Strelka::HTTPResponse::Negotiation.stringifiers[ mimetype ] = callback
78
49
  end
79
50
 
80
51
  end # module ClassMethods
@@ -8,6 +8,7 @@ require 'yajl'
8
8
 
9
9
  require 'strelka/constants'
10
10
  require 'strelka/exceptions'
11
+ require 'strelka/mixins'
11
12
  require 'strelka/httpresponse' unless defined?( Strelka::HTTPResponse )
12
13
 
13
14
 
@@ -23,11 +24,12 @@ require 'strelka/httpresponse' unless defined?( Strelka::HTTPResponse )
23
24
  # is acceptable according to its request's `Accept*` headers.
24
25
  #
25
26
  module Strelka::HTTPResponse::Negotiation
27
+ extend Strelka::MethodUtilities
26
28
  include Strelka::Constants
27
29
 
28
30
  # TODO: Perhaps replace this with something like this:
29
31
  # Mongrel2::Config::Mimetype.to_hash( :extension => :mimetype )
30
- BUILTIN_MIMETYPES = {
32
+ BUILTIN_MIMETYPE_MAP = {
31
33
  :html => 'text/html',
32
34
  :text => 'text/plain',
33
35
 
@@ -43,10 +45,10 @@ module Strelka::HTTPResponse::Negotiation
43
45
  :atom => 'application/atom+xml',
44
46
  }
45
47
 
46
- # A collection of stringifier callbacks, keyed by mimetype. If an object other
47
- # than a String is returned by a content callback, and an entry for the callback's
48
- # mimetype exists in this Hash, it will be #call()ed to stringify the object.
49
- STRINGIFIERS = {
48
+ # A collection of default stringifier callbacks, keyed by mimetype. If an entry
49
+ # for the content-negotiation callback's mimetype exists in this Hash, it will
50
+ # be #call()ed on the callback's return value to stringify the body.
51
+ BUILTIN_STRINGIFIERS = {
50
52
  'application/x-yaml' => YAML.method( :dump ),
51
53
  'application/json' => Yajl.method( :dump ),
52
54
  'text/plain' => Proc.new {|obj| obj.to_s },
@@ -62,6 +64,18 @@ module Strelka::HTTPResponse::Negotiation
62
64
  ]
63
65
 
64
66
 
67
+ ##
68
+ # The Hash of symbolic mediatypes of the form:
69
+ # { <name (Symbol)> => <mimetype> }
70
+ singleton_attr_reader :mimetype_map
71
+ @mimetype_map = BUILTIN_MIMETYPE_MAP.dup
72
+
73
+ ##
74
+ # The Hash of stringification callbacks, keyed by mimetype.
75
+ singleton_attr_reader :stringifiers
76
+ @stringifiers = BUILTIN_STRINGIFIERS.dup
77
+
78
+
65
79
  ### Add some instance variables for negotiation.
66
80
  def initialize( * )
67
81
  @mediatype_callbacks = {}
@@ -267,7 +281,11 @@ module Strelka::HTTPResponse::Negotiation
267
281
  ### to HTTP::OK.
268
282
  def for( *mediatypes, &callback )
269
283
  mediatypes.each do |mimetype|
270
- mimetype = BUILTIN_MIMETYPES[ mimetype ] if mimetype.is_a?( Symbol )
284
+ if mimetype.is_a?( Symbol )
285
+ mimetype = Strelka::HTTPResponse::Negotiation.mimetype_map[ mimetype ] or
286
+ raise "No known mimetype mapped to %p" % [ mimetype ]
287
+ end
288
+
271
289
  self.mediatype_callbacks[ mimetype ] = callback
272
290
  end
273
291
 
@@ -307,17 +325,19 @@ module Strelka::HTTPResponse::Negotiation
307
325
  ### until one returns a true-ish value, which becomes the new entity
308
326
  ### body. If the body object is not a String,
309
327
  def transform_content_type
328
+ self.log.debug "Applying content-type transforms (if any)"
310
329
  return if self.mediatype_callbacks.empty?
311
330
 
312
- self.log.debug "Applying content-type transforms (if any)"
331
+ self.log.debug " transform callbacks registered: %p" % [ self.mediatype_callbacks ]
313
332
  self.better_mediatypes.each do |mediatype|
314
333
  callbacks = self.mediatype_callbacks.find_all do |mimetype, _|
315
334
  mediatype =~ mimetype
316
335
  end
317
336
 
318
337
  if callbacks.empty?
319
- self.log.debug " no transforms for %s" % [ mediatype ]
338
+ self.log.debug " no transforms for %s" % [ mediatype ]
320
339
  else
340
+ self.log.debug " %d transform/s for %s" % [ callbacks.length, mediatype ]
321
341
  callbacks.each do |mimetype, callback|
322
342
  return if self.try_content_type_callback( mimetype, callback )
323
343
  end
@@ -334,9 +354,13 @@ module Strelka::HTTPResponse::Negotiation
334
354
 
335
355
  new_body = callback.call( mimetype ) or return false
336
356
 
337
- self.log.debug " successfully transformed: %p! Setting up response." % [ new_body ]
338
- new_body = STRINGIFIERS[ mimetype ].call( new_body ) if
339
- STRINGIFIERS.key?( mimetype ) && !new_body.is_a?( String )
357
+ self.log.debug " successfully transformed: %p! Setting up response." % [ new_body.class ]
358
+ stringifiers = Strelka::HTTPResponse::Negotiation.stringifiers
359
+ if stringifiers.key?( mimetype )
360
+ new_body = stringifiers[ mimetype ].call( new_body )
361
+ else
362
+ self.log.debug " no stringifier registered for %p" % [ mimetype ]
363
+ end
340
364
 
341
365
  self.body = new_body
342
366
  self.content_type = mimetype.dup # :TODO: Why is this frozen?
@@ -512,7 +536,7 @@ module Strelka::HTTPResponse::Negotiation
512
536
 
513
537
  # Don't close the FD when this IO goes out of scope
514
538
  oldbody = self.body
515
- oldbody.auto_close = false
539
+ oldbody.autoclose = false
516
540
 
517
541
  # Re-open the same file descriptor, but transcoding to the wanted encoding
518
542
  self.body = IO.for_fd( oldbody.fileno, internal_encoding: enc )
data/lib/strelka.rb CHANGED
@@ -24,7 +24,7 @@ module Strelka
24
24
  log_as :strelka
25
25
 
26
26
  # Library version constant
27
- VERSION = '0.4.0'
27
+ VERSION = '0.5.0'
28
28
 
29
29
  # Version-control revision constant
30
30
  REVISION = %q$Revision: 49ae27e4588e $
@@ -46,6 +46,19 @@ describe Strelka::App::Negotiation do
46
46
  def initialize( appid='conneg-test', sspec=TEST_SEND_SPEC, rspec=TEST_RECV_SPEC )
47
47
  super
48
48
  end
49
+
50
+ add_content_type :tnetstring, 'text/x-tnetstring', TNetstring.method(:dump)
51
+
52
+ def handle_request( req )
53
+ super do
54
+ res = req.response
55
+ res.for( :tnetstring ) {[ 'an', {'array' => 'of stuff'} ]}
56
+ res.for( :html ) do
57
+ "<html><head><title>Yep</title></head><body>Yeah!</body></html>"
58
+ end
59
+ res
60
+ end
61
+ end
49
62
  end
50
63
  end
51
64
 
@@ -54,18 +67,6 @@ describe Strelka::App::Negotiation do
54
67
  end
55
68
 
56
69
 
57
- it "has its config inherited by subclasses" do
58
- @app.add_content_type :text, 'text/plain' do
59
- "It's all text now, baby"
60
- end
61
- subclass = Class.new( @app )
62
-
63
- subclass.transform_names.should == @app.transform_names
64
- subclass.transform_names.should_not equal( @app.transform_names )
65
- subclass.content_type_transforms.should == @app.content_type_transforms
66
- subclass.content_type_transforms.should_not equal( @app.content_type_transforms )
67
- end
68
-
69
70
  it "gets requests that have been extended with content-negotiation" do
70
71
  req = @request_factory.get( '/service/user/estark' )
71
72
  @app.new.handle( req )
@@ -80,6 +81,13 @@ describe Strelka::App::Negotiation do
80
81
  should include( Strelka::HTTPResponse::Negotiation )
81
82
  end
82
83
 
84
+ it "adds custom content-type transforms to outgoing responses" do
85
+ req = @request_factory.get( '/service/user/astark', :accept => 'text/x-tnetstring' )
86
+ res = @app.new.handle( req )
87
+ res.content_type.should == 'text/x-tnetstring'
88
+ res.body.read.should == '28:2:an,19:5:array,8:of stuff,}]'
89
+ end
90
+
83
91
  end
84
92
 
85
93
 
@@ -63,11 +63,11 @@ describe Strelka::HTTPResponse::Negotiation do
63
63
  it "can provide blocks for bodies of several different mediatypes" do
64
64
  @req.headers.accept = 'application/x-yaml, application/json; q=0.7, text/xml; q=0.2'
65
65
 
66
- @res.for( 'application/json' ) { %{["a JSON dump"]} }
67
- @res.for( 'application/x-yaml' ) { "---\na: YAML dump\n\n" }
66
+ @res.for( 'application/json' ) { ["a JSON dump"] }
67
+ @res.for( 'application/x-yaml' ) { { 'a' => "YAML dump" } }
68
68
 
69
69
  @res.negotiated_body.rewind
70
- @res.negotiated_body.read.should == "---\na: YAML dump\n\n"
70
+ @res.negotiated_body.read.should == "---\na: YAML dump\n"
71
71
  @res.content_type.should == "application/x-yaml"
72
72
  @res.header_data.should =~ /accept(?!-)/i
73
73
  end
@@ -100,6 +100,12 @@ describe Strelka::HTTPResponse::Negotiation do
100
100
  @res.header_data.should =~ /accept(?!-)/i
101
101
  end
102
102
 
103
+ it "raises an exception if given a block for an unknown symbolic mediatype" do
104
+ expect {
105
+ @res.for( :yaquil ) {}
106
+ }.to raise_error( StandardError, /no known mimetype/i )
107
+ end
108
+
103
109
  end
104
110
 
105
111
 
@@ -132,7 +138,7 @@ describe Strelka::HTTPResponse::Negotiation do
132
138
  @res.body = File.open( __FILE__, 'r:iso-8859-5' )
133
139
  @res.content_type = 'text/plain'
134
140
 
135
- @res.negotiated_body.encoding.should == Encoding::KOI8_R
141
+ @res.negotiated_body.read.encoding.should == Encoding::KOI8_R
136
142
  @res.header_data.should =~ /accept-charset(?!-)/i
137
143
  end
138
144
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: strelka
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0.pre.393
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
@@ -30,7 +30,7 @@ cert_chain:
30
30
  6mKCwjpegytE0oifXfF8k75A9105cBnNiMZOe1tXiqYc/exCgWvbggurzDOcRkZu
31
31
  /YSusaiDXHKU2O3Akc3htA==
32
32
  -----END CERTIFICATE-----
33
- date: 2013-03-26 00:00:00.000000000 Z
33
+ date: 2013-05-02 00:00:00.000000000 Z
34
34
  dependencies:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: configurability
@@ -122,14 +122,14 @@ dependencies:
122
122
  requirements:
123
123
  - - ~>
124
124
  - !ruby/object:Gem::Version
125
- version: '0.0'
125
+ version: '0.2'
126
126
  type: :runtime
127
127
  prerelease: false
128
128
  version_requirements: !ruby/object:Gem::Requirement
129
129
  requirements:
130
130
  - - ~>
131
131
  - !ruby/object:Gem::Version
132
- version: '0.0'
132
+ version: '0.2'
133
133
  - !ruby/object:Gem::Dependency
134
134
  name: sysexits
135
135
  requirement: !ruby/object:Gem::Requirement
metadata.gz.sig CHANGED
Binary file