# File lib/protocols/httpclient.rb, line 98
 98:   def send_request args
 99:     args[:verb] ||= args[:method] # Support :method as an alternative to :verb.
100:     args[:verb] ||= :get # IS THIS A GOOD IDEA, to default to GET if nothing was specified?
101: 
102:     verb = args[:verb].to_s.upcase
103:     unless ["GET", "POST", "PUT", "DELETE", "HEAD"].include?(verb)
104:       set_deferred_status :failed, {:status => 0} # TODO, not signalling the error type
105:       return # NOTE THE EARLY RETURN, we're not sending any data.
106:     end
107: 
108:     request = args[:request] || "/"
109:     unless request[0,1] == "/"
110:       request = "/" + request
111:     end
112: 
113:     qs = args[:query_string] || ""
114:     if qs.length > 0 and qs[0,1] != '?'
115:       qs = "?" + qs
116:     end
117: 
118:     version = args[:version] || "1.1"
119: 
120:     # Allow an override for the host header if it's not the connect-string.
121:     host = args[:host_header] || args[:host] || "_"
122:     # For now, ALWAYS tuck in the port string, although we may want to omit it if it's the default.
123:     port = args[:port]
124: 
125:     # POST items.
126:     postcontenttype = args[:contenttype] || "application/octet-stream"
127:     postcontent = args[:content] || ""
128:     raise "oversized content in HTTP POST" if postcontent.length > MaxPostContentLength
129: 
130:     # ESSENTIAL for the request's line-endings to be CRLF, not LF. Some servers misbehave otherwise.
131:     # TODO: We ASSUME the caller wants to send a 1.1 request. May not be a good assumption.
132:     req = [
133:       "#{verb} #{request}#{qs} HTTP/#{version}",
134:       "Host: #{host}:#{port}",
135:       "User-agent: Ruby EventMachine",
136:     ]
137: 
138:     if verb == "POST" || verb == "PUT"
139:       req << "Content-type: #{postcontenttype}"
140:       req << "Content-length: #{postcontent.length}"
141:     end
142: 
143:     # TODO, this cookie handler assumes it's getting a single, semicolon-delimited string.
144:     # Eventually we will want to deal intelligently with arrays and hashes.
145:     if args[:cookie]
146:       req << "Cookie: #{args[:cookie]}"
147:     end
148: 
149:     # Basic-auth stanza contributed by Matt Murphy.
150:     if args[:basic_auth]
151:       basic_auth_string = ["#{args[:basic_auth][:username]}:#{args[:basic_auth][:password]}"].pack('m').strip.gsub(/\n/,'')
152:       req << "Authorization: Basic #{basic_auth_string}"
153:     end 
154: 
155:     req << ""
156:     reqstring = req.map {|l| "#{l}\r\n"}.join
157:     send_data reqstring
158: 
159:     if verb == "POST" || verb == "PUT"
160:       send_data postcontent
161:     end
162:   end