Class: Upr::JSON
Overview
JSON protocol based on Lighttpd’s mod_uploadprogress trac.lighttpd.net/trac/wiki/Docs:ModUploadProgress
Constant Summary collapse
- INT_MAX =
We use this in case length is nil when clients send chunked uploads
0x7fffffff
- SLEEP_CLASS =
defined?(Actor) ? Actor : Kernel
- RESPONSE_HEADERS =
our default response headers, we need to set no-transform to prevent deflaters from compressing our already-small small input and also to prevent buffering/corking of the response inside deflater buffers.
{ 'Content-Type' => 'application/json', 'Cache-Control' => 'no-cache, no-transform', }
Instance Attribute Summary collapse
-
#backend ⇒ Object
Returns the value of attribute backend.
-
#frequency ⇒ Object
Returns the value of attribute frequency.
-
#upload_id ⇒ Object
Returns the value of attribute upload_id.
Instance Method Summary collapse
- #_error_msg(msg) ⇒ Object
- #_json_object(options) ⇒ Object
- #_once ⇒ Object
- #_update_msg(status) ⇒ Object
-
#_wrap(env, uid) ⇒ Object
Rack interface reservced for future use with streaming AJAX.
-
#call(env) ⇒ Object
Rack interface reservced for future use with streaming AJAX.
-
#each {|_json_object(:state => 'starting') << eol| ... } ⇒ Object
Rack interface reservced for future use with streaming AJAX.
-
#initialize(options = {}) ⇒ JSON
constructor
A new instance of JSON.
- #rails_render_options ⇒ Object
Methods included from Params
Constructor Details
#initialize(options = {}) ⇒ JSON
Returns a new instance of JSON.
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/upr/json.rb', line 31 def initialize( = {}) super([:frequency] || 1, [:backend], [:upload_id]) # support :drb for compatibility with mongrel_upload_progress if [:drb] backend and raise ArgumentError, ":backend and :drb are incompatible" require 'drb' DRb.start_service self.backend = DRbObject.new(nil, [:drb]) elsif String === backend # allow people to use strings in case their backend gets # lazy-loaded (like an ActiveRecord model) self.backend = eval(backend) elsif backend.nil? raise ArgumentError, "backend MUST be specified" end # only for use with rails_proc upload_id.nil? and self.upload_id = [:env] end |
Instance Attribute Details
#backend ⇒ Object
Returns the value of attribute backend
13 14 15 |
# File 'lib/upr/json.rb', line 13 def backend @backend end |
#frequency ⇒ Object
Returns the value of attribute frequency
13 14 15 |
# File 'lib/upr/json.rb', line 13 def frequency @frequency end |
#upload_id ⇒ Object
Returns the value of attribute upload_id
13 14 15 |
# File 'lib/upr/json.rb', line 13 def upload_id @upload_id end |
Instance Method Details
#_error_msg(msg) ⇒ Object
126 127 128 |
# File 'lib/upr/json.rb', line 126 def _error_msg(msg) _json_object(:state => 'error', :status => 400, :message => msg) end |
#_json_object(options) ⇒ Object
130 131 132 133 |
# File 'lib/upr/json.rb', line 130 def _json_object() # $stderr.syswrite "#{options.inspect} #{$upr.inspect}\n" .to_json end |
#_once ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/upr/json.rb', line 63 def _once if status = backend.read(upload_id) if status.done? _json_object(:state => 'done') elsif status.seen == 0 _json_object(:state => 'starting') elsif status.error? _error_msg("upload failed") else _update_msg(status) end else timeout = Time.now + 2 until status = backend.read(upload_id) SLEEP_CLASS.sleep(0.1) return _error_msg("couldn't get status") if Time.now > timeout end _json_object(:state => 'starting') end end |
#_update_msg(status) ⇒ Object
135 136 137 138 139 140 |
# File 'lib/upr/json.rb', line 135 def _update_msg(status) raise "client error" if status.error? received = status.seen size = status.length || INT_MAX _json_object(:state => 'uploading', :size => size, :received => received) end |
#_wrap(env, uid) ⇒ Object
Rack interface reservced for future use with streaming AJAX
120 121 122 123 124 |
# File 'lib/upr/json.rb', line 120 def _wrap(env, uid) _self = dup _self.upload_id = uid [ 200, RESPONSE_HEADERS.dup, _self ] end |
#call(env) ⇒ Object
Rack interface reservced for future use with streaming AJAX
85 86 87 88 89 90 91 |
# File 'lib/upr/json.rb', line 85 def call(env) if uid = extract_upload_id(env) _wrap(env, uid) else [ 400, RESPONSE_HEADERS.dup, [ _error_msg("upload_id not given") ] ] end end |
#each {|_json_object(:state => 'starting') << eol| ... } ⇒ Object
Rack interface reservced for future use with streaming AJAX
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/upr/json.rb', line 94 def each(&block) sleeper = defined?(Actor) ? Actor : Kernel timeout = Time.now + 2 eol = ";\n" yield _json_object(:state => 'starting') << eol begin until status = backend.read(upload_id) sleeper.sleep(0.1) break if Time.now > timeout end if status begin yield _update_msg(status) << eol break if status.done? sleeper.sleep(frequency) end while status = backend.read(upload_id) yield _json_object(:state => 'done') << eol else yield _error_msg("couldn't get status") << eol end rescue => e yield _error_msg(e.) << eol end end |
#rails_render_options ⇒ Object
52 53 54 55 56 57 58 59 60 61 |
# File 'lib/upr/json.rb', line 52 def env = upload_id self.upload_id = extract_upload_id(env) text = if Rack::Request.new(env).GET.include?("long") Proc.new { |response,output| each { |line| output.write(line) } } else _once end { :content_type => 'application/json', :text => text } end |