Module: Spider::HTTP

Includes:
StatusCodes
Defined in:
lib/spiderfw/http/http.rb,
lib/spiderfw/http/server.rb,
lib/spiderfw/http/adapters/cgi.rb,
lib/spiderfw/http/adapters/rack.rb,
lib/spiderfw/http/adapters/fcgi.rb,
lib/spiderfw/http/adapters/thin.rb,
lib/spiderfw/http/adapters/webrick.rb,
lib/spiderfw/http/adapters/mongrel.rb

Defined Under Namespace

Modules: StatusCodes Classes: CGIServer, FCGIServer, Mongrel, MongrelCGIServlet, MongrelIO, MongrelServlet, RackApplication, RackIO, RackRequest, Server, Spawner, Thin, WEBrick, WEBrickIO, WEBrickRequest, WEBrickServlet

Constant Summary

MULTIPART_REGEXP =

autoload :Rack, 'spiderfw/http/adapters/rack/rack'

/\Amultipart\/form-data.*boundary=\"?([^\";,]+)/n.freeze
NAME_REGEX =
/Content-Disposition:.* name="?([^\";]*)"?/ni.freeze
CONTENT_TYPE_REGEX =
/Content-Type: (.*)\r\n/ni.freeze
FILENAME_REGEX =
/Content-Disposition:.* filename="?([^\";]*)"?/ni.freeze
CRLF =
"\r\n".freeze
EOL =
CRLF

Constants included from StatusCodes

StatusCodes::ACCEPTED, StatusCodes::BAD_GATEWAY, StatusCodes::BAD_REQUEST, StatusCodes::BANDWIDTH_LIMIT_EXCEEDED, StatusCodes::CONFLICT, StatusCodes::CONTINUE, StatusCodes::CREATED, StatusCodes::EXPECTATION_FAILED, StatusCodes::FORBIDDEN, StatusCodes::FOUND, StatusCodes::GATEWAY_TIMEOUT, StatusCodes::GONE, StatusCodes::HTTP_VERSION_NOT_SUPPORTED, StatusCodes::INTERNAL_SERVER_ERROR, StatusCodes::LENGTH_REQUIRED, StatusCodes::METHOD_NOT_ALLOWED, StatusCodes::MOVED_PERMANENTLY, StatusCodes::MULTIPLE_CHOICES, StatusCodes::NON_AUTHORITATIVE, StatusCodes::NOT_ACCEPTABLE, StatusCodes::NOT_EXTENDED, StatusCodes::NOT_FOUND, StatusCodes::NOT_IMPLEMENTED, StatusCodes::NOT_MODIFIED, StatusCodes::NO_CONTENT, StatusCodes::OK, StatusCodes::PARTIAL_CONTENT, StatusCodes::PRECONDITION_FAILED, StatusCodes::PROXY_AUTHENTICATION_REQUIRED, StatusCodes::REQUESTED_RANGE_NOT_SATISFIABLE, StatusCodes::REQUEST_ENTITY_TOO_LARGE, StatusCodes::REQUEST_TIMEOUT, StatusCodes::REQUEST_URI_TOO_LONG, StatusCodes::RESET_CONTENT, StatusCodes::SEE_OTHER, StatusCodes::SERVICE_UNAVAILABLE, StatusCodes::SWITCHING_PROTOCOLS, StatusCodes::TEMPORARY_REDIRECT, StatusCodes::UNAUTHORIZED, StatusCodes::UNSUPPORTED_MEDIA_TYPE, StatusCodes::UPGRADE_REQUIRED, StatusCodes::USE_PROXY, StatusCodes::VARIANT_ALSO_NEGOTIATES, StatusCodes::WEBDAV_FAILED_DEPENDENCY, StatusCodes::WEBDAV_INSUFFICIENT_STORAGE, StatusCodes::WEBDAV_LOCKED, StatusCodes::WEBDAV_MULTI_STATUS, StatusCodes::WEBDAV_PROCESSING, StatusCodes::WEBDAV_UNPROCESSABLE_ENTITY

Class Method Summary (collapse)

Class Method Details

+ (Object) normalize_params(parms, name, val = nil)

Converts a query string snippet to a hash and adds it to existing parameters.

Parameters

parms<Hash>

Parameters to add the normalized parameters to.

name<String>

The key of the parameter to normalize.

val<String>

The value of the parameter.

Returns

Hash

Normalized parameters

-- from Merb



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/spiderfw/http/http.rb', line 209

def self.normalize_params(parms, name, val=nil)
  name =~ %r([\[\]]*([^\[\]]+)\]*)
  key = $1 || ''
  after = $' || ''

  if after == ""
    parms[key] = val
  elsif after == "[]"
    (parms[key] ||= []) << val
  elsif after =~ %r(^\[\])
    parms[key] ||= []
    parms[key] << normalize_params({}, after, val)
  else
    parms[key] ||= {}
    parms[key] = normalize_params(parms[key], after, val)
  end
  parms
end

+ (Object) params_to_hash(value, prefix = nil)



181
182
183
184
185
186
187
188
189
190
191
192
193
194
# File 'lib/spiderfw/http/http.rb', line 181

def self.params_to_hash(value, prefix = nil)
    case value
    when Array
        value.map { |v|
            params_to_hash(v, "#{prefix}[]")
        }.inject({}){ |h, v| h.merge!(v) }
    when Hash
        value.map { |k, v|
            params_to_hash(v, prefix ? "#{prefix}[#{k}]" : k)
        }.inject({}){ |h, v| h.merge!(v) }
    else
        {prefix => value}
    end
end

+ (Object) parse_multipart(request, boundary, content_length)

Parameters

request<IO>

The raw request.

boundary<String>

The boundary string.

content_length<Fixnum>

The length of the content.

Raises

ControllerExceptions::MultiPartParseError

Failed to parse request.

Returns

Hash

The parsed request.

-- from Merb

Raises:

  • (ArgumentError)


240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/spiderfw/http/http.rb', line 240

def self.parse_multipart(request, boundary, content_length)
  boundary = "--#{boundary}"
  paramhsh = {}
  buf = ""
  input = request
  input.binmode if defined? input.binmode
  boundary_size = boundary.size + EOL.size
  bufsize = 16384
  content_length -= boundary_size
  status = input.read(boundary_size)
  raise ArgumentError, "bad content body:\n'#{status}' should == '#{boundary + EOL}'"  unless status == boundary + EOL
  rx = /(?:#{EOL})?#{Regexp.quote(boundary,'n')}(#{EOL}|--)/
  files = []
  loop {
    head = nil
    body = ''
    filename = content_type = name = nil
    read_size = 0
    until head && buf =~ rx
      i = buf.index("\r\n\r\n")
      if( i == nil && read_size == 0 && content_length == 0 )
        content_length = -1
        break
      end
      if !head && i
        head = buf.slice!(0, i+2) # First \r\n
        buf.slice!(0, 2)          # Second \r\n
        filename = head[FILENAME_REGEX, 1]
        content_type = head[CONTENT_TYPE_REGEX, 1]
        name = head[NAME_REGEX, 1]

        if filename && !filename.empty?
          body = UploadedFile.new(filename, content_type)
        end
        next
      end

      # Save the read body part.
      if head && (boundary_size+4 < buf.size)
        body << buf.slice!(0, buf.size - (boundary_size+4))
      end

      read_size = bufsize < content_length ? bufsize : content_length
      if( read_size > 0 )
        c = input.read(read_size)
        raise ArgumentError, "bad content body"  if c.nil? || c.empty?
        buf << c
        content_length -= c.size
      end
    end

    # Save the rest.
    if i = buf.index(rx)
      body << buf.slice!(0, i)
      buf.slice!(0, boundary_size+2)

      content_length = -1  if $1 == "--"
    end

    if filename && !filename.empty?
        body.rewind
        files << body
    end
    data = body
    paramhsh = normalize_params(paramhsh,name,data)
    break  if buf.empty? || content_length == -1
  }
  [paramhsh, files]
end

+ (Object) parse_query(qs, d = '&')

Parameters

qs<String>

The query string.

d<String>

The query string divider. Defaults to "&".

Returns

Mash

The parsed query string.

Examples

query_parse("bar=nik&post[body]=heya")
  # => { :bar => "nik", :post => { :body => "heya" } }

-- from Merb



173
174
175
176
177
178
# File 'lib/spiderfw/http/http.rb', line 173

def self.parse_query(qs, d = '&')
  return (qs||'').split(/[#{d}] */n).inject({}) { |h,p| 
    key, value = urldecode(p).split('=',2)
    normalize_params(h, key, value)
  }
end

+ (Object) status_messages



131
132
133
# File 'lib/spiderfw/http/http.rb', line 131

def self.status_messages
    StatusCodes.status_messages
end

+ (Object) urldecode(s)

Parameter

s<String>

String to URL unescape.

returns

String

The unescaped string.

-- from Merb



155
156
157
158
159
# File 'lib/spiderfw/http/http.rb', line 155

def self.urldecode(s)
  s.tr('+', ' ').gsub(/((?:%[0-9a-fA-F]{2})+)/n){
    [$1.delete('%')].pack('H*')
  }
end

+ (Object) urlencode(s)

Parameters

s<String>

String to URL escape.

returns

String

The escaped string.

-- from Merb



142
143
144
145
146
# File 'lib/spiderfw/http/http.rb', line 142

def self.urlencode(s)
   s.to_s.gsub(/([^a-zA-Z0-9_.-]+)/n) {
     '%'+$1.unpack('H2'*$1.size).join('%').upcase
   }.tr(' ', '+')
end