strelka 0.4.0 → 0.5.0.pre.393
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -1
- data/Rakefile +1 -1
- data/lib/strelka/app/negotiation.rb +10 -39
- data/lib/strelka/httpresponse/negotiation.rb +36 -12
- data/lib/strelka.rb +1 -1
- data/spec/strelka/app/negotiation_spec.rb +20 -12
- data/spec/strelka/httpresponse/negotiation_spec.rb +10 -4
- data.tar.gz.sig +0 -0
- metadata +4 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1d2cffaf505aa41496b0ce345534e70d6f4b45a0
|
4
|
+
data.tar.gz: c922b2aa4deafe3472b9be7d2d960237dc2e2b11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 295a62542aae175dd4c70d425fc70f43d314412db557a01989aa63b015931cdf20cad5793fefd4e15a237f49d0f50a17c95b72b5905f321a260520ba4c13e06f
|
7
|
+
data.tar.gz: 590d6dfab3b2a652e916b9e78ad497440b5e5de314abbd12b5c289fd917d43a1c9e4b212ec55fdc2d030693ef312ea44d8ce0b530c140ee5c714241388a0ae0d
|
checksums.yaml.gz.sig
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
Q�]O$S�S�������U��pMAx�q�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��YQ�b[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.
|
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'
|
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
|
72
|
-
### specified +
|
73
|
-
###
|
74
|
-
###
|
75
|
-
|
76
|
-
|
77
|
-
|
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
|
-
|
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
|
47
|
-
#
|
48
|
-
#
|
49
|
-
|
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
|
-
|
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 "
|
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 "
|
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
|
-
|
339
|
-
|
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.
|
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
@@ -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' ) {
|
67
|
-
@res.for( 'application/x-yaml' ) { "
|
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
|
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
|
+
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-
|
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.
|
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.
|
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
|