class NchanTools::Subscriber::LongPollClient::HTTPBundle

Attributes

done[RW]
last_message_time[RW]
parser[RW]
request_time[RW]
sock[RW]
stop_after_headers[RW]
time_requested[RW]

Public Class Methods

new(uri, opt={}) click to toggle source
Calls superclass method
# File lib/nchan_tools/pubsub.rb, line 727
      def initialize(uri, opt={})
        super
        @accept = opt[:accept] or "*/*"
        @rcvbuf=""
        @sndbuf=""
        @parser = Http::Parser.new
        @done = false
        extra_headers = (opt[:headers] or opt[:extra_headers] or {}).map{|k,v| "#{k}: #{v}\n"}.join ""
        host = uri.host.match "[^/]+$"
        request_uri = "#{uri.path}#{uri.query && "?#{uri.query}"}"
        @send_noid_str= <<-END.gsub(/^ {10}/, '')
          GET #{request_uri} HTTP/1.1
          Host: #{host}#{uri.default_port == uri.port ? "" : ":#{uri.port}"}
          #{extra_headers}Accept: #{@accept}
          User-Agent: #{opt[:useragent] || "HTTPBundle"}
          
        END
        
        @send_withid_fmt= <<-END.gsub(/^ {10}/, '')
          GET #{request_uri.gsub("%", "%%")} HTTP/1.1
          Host: #{host}#{uri.default_port == uri.port ? "" : ":#{uri.port}"}
          #{extra_headers}Accept: #{@accept}
          User-Agent: #{opt[:useragent] || "HTTPBundle"}
          If-Modified-Since: %s
          If-None-Match: %s
          
        END
        
        @send_withid_no_etag_fmt= <<-END.gsub(/^ {10}/, '')
          GET #{request_uri.gsub("%", "%%")} HTTP/1.1
          Host: #{host}#{uri.default_port == uri.port ? "" : ":#{uri.port}"}
          #{extra_headers}Accept: #{@accept}
          User-Agent: #{opt[:useragent] || "HTTPBundle"}
          If-Modified-Since: %s
          
        END
        
        @parser.on_headers_complete = proc do |h|
          if verbose 
            puts "< HTTP/1.1 #{@parser.status_code} [...]\r\n#{h.map {|k,v| "< #{k}: #{v}"}.join "\r\n"}"
          end
          @headers=h
          @last_modified = h['Last-Modified']
          @etag = h['Etag']
          @chunky = h['Transfer-Encoding']=='chunked'
          @gzipped = h['Content-Encoding']=='gzip'
          @code=@parser.status_code
          on_headers @parser.status_code, h
          if @stop_after_headers
            @bypass_parser = true
            :stop
          end
        end
        
        @parser.on_body = proc do |chunk|
          handle_chunk chunk
        end
        
        @parser.on_message_complete = proc do
          @chunky = nil
          @gzipped = nil
          on_response @parser.status_code, @parser.headers
        end
        
      end

Public Instance Methods

read() click to toggle source
# File lib/nchan_tools/pubsub.rb, line 833
def read
  @rcvbuf.clear
  begin
    sock.readpartial(1024*10000, @rcvbuf)
    while @rcvbuf.size > 0
      unless @bypass_parser
        offset = @parser << @rcvbuf
        if offset < @rcvbuf.size
          @rcvbuf = @rcvbuf[offset..-1]
        else
          @rcvbuf.clear
        end
      else
        handle_chunk @rcvbuf
        @rcvbuf.clear
      end
    end
  rescue HTTP::Parser::Error => e
    on_error "Invalid HTTP Respose - #{e}", e
  rescue EOFError => e
    on_error "Server closed connection...", e
  rescue => e 
    on_error "#{e.class}: #{e}", e
  end
  return false if @done || sock.closed?
end
reconnect?() click to toggle source
# File lib/nchan_tools/pubsub.rb, line 800
def reconnect?
  true
end
send_GET(msg_time=nil, msg_tag=nil) click to toggle source
# File lib/nchan_tools/pubsub.rb, line 804
def send_GET(msg_time=nil, msg_tag=nil)
  @last_modified = msg_time.to_s if msg_time
  @etag = msg_tag.to_s if msg_tag
  @sndbuf.clear 
  begin
    data = if @last_modified
      @etag ? sprintf(@send_withid_fmt, @last_modified, @etag) : sprintf(@send_withid_no_etag_fmt, @last_modified)
    else
      @send_noid_str
    end
  rescue Exception => e
    binding.pry
  end
  
  @sndbuf << data
  
  if @headers && @headers["Connection"]=="close" && [200, 201, 202, 304, 408].member?(@parser.status_code) && reconnect?
    sock.close
    open_socket
    @parser.reset!
  end
  
  @time_requested=Time.now.to_f
  if verbose
    puts "", data.gsub(/^.*$/, "> \\0")
  end
  sock << @sndbuf
end

Private Instance Methods

handle_chunk(chunk) click to toggle source
# File lib/nchan_tools/pubsub.rb, line 794
def handle_chunk(chunk)
  chunk = Zlib::GzipReader.new(StringIO.new(chunk)).read if @gzipped 
  on_chunk chunk
end