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/fcgi.rb,
lib/spiderfw/http/adapters/rack.rb,
lib/spiderfw/http/adapters/thin.rb,
lib/spiderfw/http/adapters/mongrel.rb,
lib/spiderfw/http/adapters/webrick.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 collapse

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
METHODS =
[
    :GET, :POST, :PUT, :DELETE, :HEAD, :TRACE, :CONNECT,
    :PROPFIND, :PROPPATCH, :MKCOL, :COPY, :MOVE, :LOCK, :UNLOCK
]

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

.normalize_params(parms, name, val = nil) ⇒ Object

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



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# File 'lib/spiderfw/http/http.rb', line 214

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

.params_to_hash(value, prefix = nil) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/spiderfw/http/http.rb', line 186

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

.parse_multipart(request, boundary, content_length) ⇒ Object

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)


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
309
310
311
312
313
# File 'lib/spiderfw/http/http.rb', line 245

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)}(#{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?
            #se sono con ruby >= 1.9 ricavo l'encoding
            body = UploadedFile.new(filename, content_type, (buf.respond_to?(:encoding) ? buf.encoding.to_s : nil) )
        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

.parse_query(qs, d = '&') ⇒ Object

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



178
179
180
181
182
183
# File 'lib/spiderfw/http/http.rb', line 178

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

.status_messagesObject



136
137
138
# File 'lib/spiderfw/http/http.rb', line 136

def self.status_messages
    StatusCodes.status_messages
end

.urldecode(s) ⇒ Object

Parameter

s<String>

String to URL unescape.

returns

String

The unescaped string.

– from Merb



160
161
162
163
164
# File 'lib/spiderfw/http/http.rb', line 160

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

.urlencode(s) ⇒ Object

Parameters

s<String>

String to URL escape.

returns

String

The escaped string.

– from Merb



147
148
149
150
151
# File 'lib/spiderfw/http/http.rb', line 147

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