public
Fork of wycats/merb-core
Description: Merb Core: All you need. None you don't.
Homepage: http://www.merbivore.com
Clone URL: git://github.com/auser/merb-core.git
Add back support for streaming when using Mongrel or evented mongrel
ezmobius (author)
Wed Feb 13 18:06:57 -0800 2008
commit  8abb459d89ccb6061fa9dc59c380823619de1706
tree    e2308b970c53f0c54731eacc31683f0138fce10f
parent  a15b2e9aa1eb31f0a3fa7b2568f3ed25968e8433
...
1
2
3
4
 
 
 
5
6
7
...
34
35
36
 
37
38
39
 
 
 
40
41
42
...
44
45
46
47
 
 
48
49
50
51
52
53
 
 
54
55
56
...
61
62
63
64
 
 
65
66
67
...
77
78
79
 
80
81
82
...
111
112
113
114
115
 
116
117
 
118
119
120
...
122
123
124
125
 
126
127
128
...
140
141
142
 
143
144
145
...
1
2
3
 
4
5
6
7
8
9
...
36
37
38
39
40
 
 
41
42
43
44
45
46
...
48
49
50
 
51
52
53
54
55
56
 
 
57
58
59
60
61
...
66
67
68
 
69
70
71
72
73
...
83
84
85
86
87
88
89
...
118
119
120
 
 
121
122
 
123
124
125
126
...
128
129
130
 
131
132
133
134
...
146
147
148
149
150
151
152
0
@@ -1,7 +1,9 @@
0
 module Merb
0
   # Module that is mixed in to all implemented controllers.
0
   module ControllerMixin
0
-
0
+ def must_support_streaming!
0
+ raise(NotImplemented, "Current Rack adapter does not support streaming") unless request.env['rack.streaming']
0
+ end
0
     # Renders the block given as a parameter using chunked
0
     # encoding.
0
     #
0
@@ -34,9 +36,11 @@ module Merb
0
     # send chunks of data down to the server. The chunking will
0
     # terminate once the block returns.
0
     def render_chunked(&blk)
0
+ must_support_streaming!
0
       headers['Transfer-Encoding'] = 'chunked'
0
- Proc.new {
0
- response.send_status_no_connection_close(0)
0
+ Proc.new { |response|
0
+ @response = response
0
+ response.send_status_no_connection_close('')
0
         response.send_header
0
         blk.call
0
         response.write("0\r\n\r\n")
0
@@ -44,13 +48,14 @@ module Merb
0
     end
0
 
0
     # Writes a chunk from render_chunked to the response that
0
- # is sent back to the client.
0
+ # is sent back to the client. This can only be called within
0
+ # a render_chunked {} block
0
     #
0
     # ==== Parameters
0
     # data<String>:: a chunk of data to return
0
     def send_chunk(data)
0
- response.write('%x' % data.size + "\r\n")
0
- response.write(data + "\r\n")
0
+ @response.write('%x' % data.size + "\r\n")
0
+ @response.write(data + "\r\n")
0
     end
0
     
0
     # Returns a +Proc+ that Mongrel can call later, allowing
0
@@ -61,7 +66,8 @@ module Merb
0
     # A proc that should get called outside the mutex,
0
     # and which will return the value to render
0
     def render_deferred(&blk)
0
- Proc.new {
0
+ must_support_streaming!
0
+ Proc.new {|response|
0
         result = blk.call
0
         response.send_status(result.length)
0
         response.send_header
0
@@ -77,6 +83,7 @@ module Merb
0
     # blk<Proc>:: A proc that should get called once the string has
0
     # been returned
0
     def render_then_call(str, &blk)
0
+ must_support_streaming!
0
       Proc.new {
0
         response.send_status(str.length)
0
         response.send_header
0
@@ -111,10 +118,9 @@ module Merb
0
       headers.update(
0
         'Content-Type' => opts[:type].strip, # fixes a problem with extra '\r' with some browsers
0
         'Content-Disposition' => disposition,
0
- 'Content-Transfer-Encoding' => 'binary',
0
- 'X-SENDFILE' => file
0
+ 'Content-Transfer-Encoding' => 'binary'
0
       )
0
- return
0
+ File.open(file)
0
     end
0
     
0
     # Streams a file over HTTP.
0
@@ -122,7 +128,7 @@ module Merb
0
     # ==== Example
0
     # stream_file( { :filename => file_name,
0
     # :type => content_type,
0
- # :content_length => content_length }) do
0
+ # :content_length => content_length }) do |response|
0
     # AWS::S3::S3Object.stream(user.folder_name + "-" + user_file.unique_id, bucket_name) do |chunk|
0
     # response.write chunk
0
     # end
0
@@ -140,6 +146,7 @@ module Merb
0
     # :filename<String>:: An acceptable value for the filename= portion
0
     # of headers["Content-Disposition"]
0
     def stream_file(opts={}, &stream)
0
+ must_support_streaming!
0
       opts.update(Merb::Const::DEFAULT_SEND_FILE_OPTIONS.merge(opts))
0
       disposition = opts[:disposition].dup || 'attachment'
0
       disposition << %(; filename="#{opts[:filename]}")
...
1
2
 
3
4
5
...
8
9
10
11
 
12
13
14
...
1
 
2
3
4
5
...
8
9
10
 
11
12
13
14
0
@@ -1,5 +1,5 @@
0
 require 'mongrel'
0
-require 'rack/handler/mongrel'
0
+require 'merb-core/rack/handler/mongrel'
0
 module Merb
0
 
0
   module Rack
0
@@ -8,7 +8,7 @@ module Merb
0
       # start server on given host and port.
0
       def self.start(opts={})
0
         server = ::Mongrel::HttpServer.new(opts[:host], opts[:port])
0
- server.register('/', ::Rack::Handler::Mongrel.new(opts[:app]))
0
+ server.register('/', ::Merb::Rack::Handler::Mongrel.new(opts[:app]))
0
         server.run.join
0
       end
0
     end
...
11
12
13
14
 
15
16
17
18
19
20
 
 
 
21
22
23
24
25
 
26
27
28
...
11
12
13
 
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
0
@@ -11,18 +11,22 @@ module Merb
0
       def call(env)
0
         path = env['PATH_INFO'].chomp('/')
0
         cached_path = (path.empty? ? 'index' : path) + '.html'
0
-
0
+ Merb.logger.info "Request: #{path}"
0
         if file_exist?(path) # Serve the file if it's there
0
           serve_static(env)
0
         elsif file_exist?(cached_path) # Serve the page cache if it's there
0
           env['PATH_INFO'] = cached_path
0
           serve_static(env)
0
         else # No static file, let Merb handle it
0
+ if path =~ /favicon\.ico/
0
+ return [404, {"Content-Type"=>"text/html"}, "404 Not Founds."]
0
+ end
0
           begin
0
             controller = ::Merb::Dispatcher.handle(env)
0
           rescue Object => e
0
             return [500, {"Content-Type"=>"text/html"}, e.message + "<br/>" + e.backtrace.join("<br/>")]
0
           end
0
+ Merb.logger.info "\n\n"
0
           Merb.logger.flush
0
           [controller.status, controller.headers, controller.body]
0
         end

Comments

    No one has commented yet.