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