Parent

Yajl::HttpStream

This module is for making HTTP requests to which the response bodies (and possibly requests in the near future) are streamed directly into Yajl.

Constants

ALLOWED_MIME_TYPES

The mime-type we expect the response to be. If it’s anything else, we can’t parse it and an InvalidContentType is raised.

Public Class Methods

delete(uri, opts = {}, &block) click to toggle source

Makes a basic HTTP DELETE request to the URI provided

    # File lib/yajl/http_stream.rb, line 70
70:     def self.delete(uri, opts = {}, &block)
71:       request("DELETE", uri, opts, &block)
72:     end
get(uri, opts = {}, &block) click to toggle source

Makes a basic HTTP GET request to the URI provided

    # File lib/yajl/http_stream.rb, line 31
31:     def self.get(uri, opts = {}, &block)
32:       request("GET", uri, opts, &block)
33:     end
post(uri, body, opts = {}, &block) click to toggle source

Makes a basic HTTP POST request to the URI provided

    # File lib/yajl/http_stream.rb, line 44
44:     def self.post(uri, body, opts = {}, &block)
45:       request("POST", uri, opts.merge({:body => body}), &block)
46:     end
put(uri, body, opts = {}, &block) click to toggle source

Makes a basic HTTP PUT request to the URI provided

    # File lib/yajl/http_stream.rb, line 57
57:     def self.put(uri, body, opts = {}, &block)
58:       request("PUT", uri, opts.merge({:body => body}), &block)
59:     end

Protected Class Methods

request(method, uri, opts = {}, &block) click to toggle source
     # File lib/yajl/http_stream.rb, line 89
 89:       def self.request(method, uri, opts = {}, &block)
 90:         if uri.is_a?(String)
 91:           uri = URI.parse(uri)
 92:         end
 93: 
 94:         default_headers = {
 95:           "User-Agent" => opts["User-Agent"] || "Yajl::HttpStream #{Yajl::VERSION}",
 96:           "Accept" => "*/*",
 97:           "Accept-Charset" => "utf-8"
 98:         }
 99: 
100:         if method == "POST" || method == "PUT"
101:           default_headers["Content-Type"] = opts["Content-Type"] || "application/x-www-form-urlencoded"
102:           body = opts.delete(:body)
103:           if body.is_a?(Hash)
104:             body = body.keys.collect {|param| "#{URI.escape(param.to_s)}=#{URI.escape(body[param].to_s)}"}.join('&')
105:           end
106:           default_headers["Content-Length"] = body.length
107:         end
108: 
109:         unless uri.userinfo.nil?
110:           default_headers["Authorization"] = "Basic #{[uri.userinfo].pack('m').strip!}\r\n"
111:         end
112: 
113:         encodings = []
114:         encodings << "bzip2" if defined?(Yajl::Bzip2)
115:         encodings << "gzip" if defined?(Yajl::Gzip)
116:         encodings << "deflate" if defined?(Yajl::Deflate)
117:         if encodings.any?
118:           default_headers["Accept-Encoding"] = "#{encodings.join(',')}\r\n"
119:         end
120: 
121:         headers = default_headers.merge(opts[:headers] || {})
122: 
123:         socket = opts.delete(:socket) || TCPSocket.new(uri.host, uri.port)
124:         request = "#{method} #{uri.path}#{uri.query ? "?"+uri.query : nil} HTTP/1.1\r\n"
125:         request << "Host: #{uri.host}\r\n"
126:         headers.each do |k, v|
127:           request << "#{k}: #{v}\r\n"
128:         end
129:         request << "\r\n"
130:         if method == "POST" || method == "PUT"
131:           request << body
132:         end
133:         socket.write(request)
134:         response_head = {}
135:         response_head[:headers] = {}
136: 
137:         socket.each_line do |line|
138:           if line == "\r\n" # end of the headers
139:             break
140:           else
141:             header = line.split(": ")
142:             if header.size == 1
143:               header = header[0].split(" ")
144:               response_head[:version] = header[0]
145:               response_head[:code] = header[1].to_i
146:               response_head[:msg] = header[2]
147:               # this is the response code line
148:             else
149:               response_head[:headers][header[0]] = header[1].strip
150:             end
151:           end
152:         end
153: 
154:         if (response_head[:code] != 200)
155:           raise HttpError.new("Code 200 expected got #{response_head[:code]}", response_head[:headers])
156:         end
157: 
158:         parser = Yajl::Parser.new(opts)
159:         parser.on_parse_complete = block if block_given?
160:         if response_head[:headers]["Transfer-Encoding"] == 'chunked'
161:           if block_given?
162:             chunkLeft = 0
163:             while !socket.eof? && (line = socket.gets)
164:               break if line.match /^0.*?\r\n/
165:               next if line == "\r\n"
166:               size = line.hex
167:               json = socket.read(size)
168:               next if json.nil?
169:               chunkLeft = size-json.size
170:               if chunkLeft == 0
171:                 parser << json
172:               else
173:                 # received only part of the chunk, grab the rest
174:                 parser << socket.read(chunkLeft)
175:               end
176:             end
177:           else
178:             raise Exception, "Chunked responses detected, but no block given to handle the chunks."
179:           end
180:         else
181:           content_type = response_head[:headers]["Content-Type"].split(';')
182:           content_type = content_type.first
183:           if ALLOWED_MIME_TYPES.include?(content_type)
184:             case response_head[:headers]["Content-Encoding"]
185:             when "gzip"
186:               return Yajl::Gzip::StreamReader.parse(socket, opts, &block)
187:             when "deflate"
188:               return Yajl::Deflate::StreamReader.parse(socket, opts.merge({:deflate_options => -Zlib::MAX_WBITS}), &block)
189:             when "bzip2"
190:               return Yajl::Bzip2::StreamReader.parse(socket, opts, &block)
191:             else
192:               return parser.parse(socket)
193:             end
194:           else
195:             raise InvalidContentType, "The response MIME type #{content_type}"
196:           end
197:         end
198:       ensure
199:         socket.close if !socket.nil? and !socket.closed?
200:       end

Public Instance Methods

delete(uri, opts = {}, &block) click to toggle source

Makes a basic HTTP DELETE request to the URI provided allowing the user to terminate the connection

    # File lib/yajl/http_stream.rb, line 75
75:     def delete(uri, opts = {}, &block)
76:       initialize_socket(uri, opts)
77:       HttpStream::delete(uri, opts, &block)
78:     rescue IOError => e
79:       raise e unless @intentional_termination
80:     end
get(uri, opts = {}, &block) click to toggle source

Makes a basic HTTP GET request to the URI provided allowing the user to terminate the connection

    # File lib/yajl/http_stream.rb, line 36
36:     def get(uri, opts = {}, &block)
37:       initialize_socket(uri, opts)
38:       HttpStream::get(uri, opts, &block)
39:     rescue IOError => e
40:       raise e unless @intentional_termination
41:     end
post(uri, body, opts = {}, &block) click to toggle source

Makes a basic HTTP POST request to the URI provided allowing the user to terminate the connection

    # File lib/yajl/http_stream.rb, line 49
49:     def post(uri, body, opts = {}, &block)
50:       initialize_socket(uri, opts)
51:       HttpStream::post(uri, body, opts, &block)
52:     rescue IOError => e
53:       raise e unless @intentional_termination
54:     end
put(uri, body, opts = {}, &block) click to toggle source

Makes a basic HTTP PUT request to the URI provided allowing the user to terminate the connection

    # File lib/yajl/http_stream.rb, line 62
62:     def put(uri, body, opts = {}, &block)
63:       initialize_socket(uri, opts)
64:       HttpStream::put(uri, body, opts, &block)
65:     rescue IOError => e
66:       raise e unless @intentional_termination
67:     end
terminate() click to toggle source

Terminate a running HTTPStream instance

    # File lib/yajl/http_stream.rb, line 83
83:     def terminate
84:       @intentional_termination = true
85:       @socket.close
86:     end

Private Instance Methods

initialize_socket(uri, opts = {}) click to toggle source

Initialize socket and add it to the opts

     # File lib/yajl/http_stream.rb, line 204
204:     def initialize_socket(uri, opts = {})
205:       return if opts[:socket]
206: 
207:       @socket = TCPSocket.new(uri.host, uri.port)
208:       opts.merge!({:socket => @socket})
209:       @intentional_termination = false
210:     end

Disabled; run with --debug to generate this.

[Validate]

Generated with the Darkfish Rdoc Generator 1.1.6.