Module: Rack::Request::Helpers

Included in:
Rack::Request
Defined in:
lib/rack/request.rb

Constant Summary collapse

FORM_DATA_MEDIA_TYPES =

The set of form-data media-types. Requests that do not indicate one of the media types present in this list will not be eligible for form-data / param parsing.

[
  'application/x-www-form-urlencoded',
  'multipart/form-data'
]
PARSEABLE_DATA_MEDIA_TYPES =

The set of media-types. Requests that do not indicate one of the media types present in this list will not be eligible for param parsing like soap attachments or generic multiparts

[
  'multipart/related',
  'multipart/mixed'
]
DEFAULT_PORTS =

Default ports depending on scheme. Used to decide whether or not to include the port in a generated URI.

{ 'http' => 80, 'https' => 443, 'coffee' => 80 }
HTTP_X_FORWARDED_FOR =

The address of the client which connected to the proxy.

'HTTP_X_FORWARDED_FOR'
HTTP_X_FORWARDED_HOST =

The contents of the host/:authority header sent to the proxy.

'HTTP_X_FORWARDED_HOST'
HTTP_FORWARDED =
'HTTP_FORWARDED'
HTTP_X_FORWARDED_SCHEME =

The value of the scheme sent to the proxy.

'HTTP_X_FORWARDED_SCHEME'
HTTP_X_FORWARDED_PROTO =

The protocol used to connect to the proxy.

'HTTP_X_FORWARDED_PROTO'
HTTP_X_FORWARDED_PORT =

The port used to connect to the proxy.

'HTTP_X_FORWARDED_PORT'
HTTP_X_FORWARDED_SSL =

Another way for specifying https scheme was used.

'HTTP_X_FORWARDED_SSL'

Instance Method Summary collapse

Instance Method Details

#accept_encodingObject

[View source]

607
608
609
# File 'lib/rack/request.rb', line 607

def accept_encoding
  parse_http_accept_header(get_header("HTTP_ACCEPT_ENCODING"))
end

#accept_languageObject

[View source]

611
612
613
# File 'lib/rack/request.rb', line 611

def accept_language
  parse_http_accept_header(get_header("HTTP_ACCEPT_LANGUAGE"))
end

#authorityObject

The authority of the incoming request as defined by RFC3976. tools.ietf.org/html/rfc3986#section-3.2

In HTTP/1, this is the ‘host` header. In HTTP/2, this is the `:authority` pseudo-header.

[View source]

266
267
268
# File 'lib/rack/request.rb', line 266

def authority
  forwarded_authority || host_authority || server_authority
end

#base_urlObject

[View source]

590
591
592
# File 'lib/rack/request.rb', line 590

def base_url
  "#{scheme}://#{host_with_port}"
end

#bodyObject

[View source]

190
# File 'lib/rack/request.rb', line 190

def body;            get_header(RACK_INPUT)                         end

#content_charsetObject

The character set of the request body if a “charset” media type parameter was given, or nil if no “charset” was specified. Note that, per RFC2616, text/* media types that specify no explicit charset are to be considered ISO-8859-1.

[View source]

458
459
460
# File 'lib/rack/request.rb', line 458

def content_charset
  media_type_params['charset']
end

#content_lengthObject

[View source]

199
# File 'lib/rack/request.rb', line 199

def content_length;  get_header('CONTENT_LENGTH')                   end

#content_typeObject

[View source]

308
309
310
311
# File 'lib/rack/request.rb', line 308

def content_type
  content_type = get_header('CONTENT_TYPE')
  content_type.nil? || content_type.empty? ? nil : content_type
end

#cookiesObject

[View source]

293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/rack/request.rb', line 293

def cookies
  hash = fetch_header(RACK_REQUEST_COOKIE_HASH) do |key|
    set_header(key, {})
  end

  string = get_header(HTTP_COOKIE)

  unless string == get_header(RACK_REQUEST_COOKIE_STRING)
    hash.replace Utils.parse_cookies_header(string)
    set_header(RACK_REQUEST_COOKIE_STRING, string)
  end

  hash
end

#delete?Boolean

Checks the HTTP request method (or verb) to see if it was of type DELETE

Returns:

  • (Boolean)
[View source]

220
# File 'lib/rack/request.rb', line 220

def delete?;  request_method == DELETE  end

#delete_param(k) ⇒ Object

Destructively delete a parameter, whether it’s in GET or POST. Returns the value of the deleted parameter.

If the parameter is in both GET and POST, the POST value takes precedence since that’s how #params works.

env['rack.input'] is not touched.

[View source]

585
586
587
588
# File 'lib/rack/request.rb', line 585

def delete_param(k)
  post_value, get_value = self.POST.delete(k), self.GET.delete(k)
  post_value || get_value
end

#form_data?Boolean

Determine whether the request body contains form-data by checking the request content-type for one of the media-types: “application/x-www-form-urlencoded” or “multipart/form-data”. The list of form-data media types can be modified through the FORM_DATA_MEDIA_TYPES array.

A request body is also assumed to contain form-data when no content-type header is provided and the request_method is POST.

Returns:

  • (Boolean)
[View source]

470
471
472
473
474
475
# File 'lib/rack/request.rb', line 470

def form_data?
  type = media_type
  meth = get_header(RACK_METHODOVERRIDE_ORIGINAL_METHOD) || get_header(REQUEST_METHOD)

  (meth == POST && type.nil?) || FORM_DATA_MEDIA_TYPES.include?(type)
end

#forwarded_authorityObject

[View source]

393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/rack/request.rb', line 393

def forwarded_authority
  forwarded_priority.each do |type|
    case type
    when :forwarded
      if forwarded = get_http_forwarded(:host)
        return forwarded.last
      end
    when :x_forwarded
      if value = get_header(HTTP_X_FORWARDED_HOST)
        return wrap_ipv6(split_header(value).last)
      end
    end
  end

  nil
end

#forwarded_forObject

[View source]

353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/rack/request.rb', line 353

def forwarded_for
  forwarded_priority.each do |type|
    case type
    when :forwarded
      if forwarded_for = get_http_forwarded(:for)
        return(forwarded_for.map! do |authority|
          split_authority(authority)[1]
        end)
      end
    when :x_forwarded
      if value = get_header(HTTP_X_FORWARDED_FOR)
        return(split_header(value).map do |authority|
          split_authority(wrap_ipv6(authority))[1]
        end)
      end
    end
  end

  nil
end

#forwarded_portObject

[View source]

374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
# File 'lib/rack/request.rb', line 374

def forwarded_port
  forwarded_priority.each do |type|
    case type
    when :forwarded
      if forwarded = get_http_forwarded(:for)
        return(forwarded.map do |authority|
          split_authority(authority)[2]
        end.compact)
      end
    when :x_forwarded
      if value = get_header(HTTP_X_FORWARDED_PORT)
        return split_header(value).map(&:to_i)
      end
    end
  end

  nil
end

#fullpathObject

[View source]

603
604
605
# File 'lib/rack/request.rb', line 603

def fullpath
  query_string.empty? ? path : "#{path}?#{query_string}"
end

#GETObject

Returns the data received in the query string.

[View source]

484
485
486
487
488
489
490
491
492
493
494
495
496
497
# File 'lib/rack/request.rb', line 484

def GET
  rr_query_string = get_header(RACK_REQUEST_QUERY_STRING)
  query_string = self.query_string
  if rr_query_string == query_string
    get_header(RACK_REQUEST_QUERY_HASH)
  else
    if rr_query_string
      warn "query string used for GET parsing different from current query string. Starting in Rack 3.2, Rack will used the cached GET value instead of parsing the current query string.", uplevel: 1
    end
    query_hash = parse_query(query_string, '&')
    set_header(RACK_REQUEST_QUERY_STRING, query_string)
    set_header(RACK_REQUEST_QUERY_HASH, query_hash)
  end
end

#get?Boolean

Checks the HTTP request method (or verb) to see if it was of type GET

Returns:

  • (Boolean)
[View source]

223
# File 'lib/rack/request.rb', line 223

def get?;     request_method == GET     end

#head?Boolean

Checks the HTTP request method (or verb) to see if it was of type HEAD

Returns:

  • (Boolean)
[View source]

226
# File 'lib/rack/request.rb', line 226

def head?;    request_method == HEAD    end

#hostObject

Returns a formatted host, suitable for being used in a URI.

[View source]

333
334
335
# File 'lib/rack/request.rb', line 333

def host
  split_authority(self.authority)[0]
end

#host_authorityObject

The ‘HTTP_HOST` header.

[View source]

318
319
320
# File 'lib/rack/request.rb', line 318

def host_authority
  get_header(HTTP_HOST)
end

#host_with_port(authority = self.authority) ⇒ Object

[View source]

322
323
324
325
326
327
328
329
330
# File 'lib/rack/request.rb', line 322

def host_with_port(authority = self.authority)
  host, _, port = split_authority(authority)

  if port == DEFAULT_PORTS[self.scheme]
    host
  else
    authority
  end
end

#hostnameObject

Returns an address suitable for being to resolve to an address. In the case of a domain name or IPv4 address, the result is the same as host. In the case of IPv6 or future address formats, the square brackets are removed.

[View source]

341
342
343
# File 'lib/rack/request.rb', line 341

def hostname
  split_authority(self.authority)[1]
end

#ipObject

[View source]

414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/rack/request.rb', line 414

def ip
  remote_addresses = split_header(get_header('REMOTE_ADDR'))
  external_addresses = reject_trusted_ip_addresses(remote_addresses)

  unless external_addresses.empty?
    return external_addresses.last
  end

  if (forwarded_for = self.forwarded_for) && !forwarded_for.empty?
    # The forwarded for addresses are ordered: client, proxy1, proxy2.
    # So we reject all the trusted addresses (proxy*) and return the
    # last client. Or if we trust everyone, we just return the first
    # address.
    return reject_trusted_ip_addresses(forwarded_for).last || forwarded_for.first
  end

  # If all the addresses are trusted, and we aren't forwarded, just return
  # the first remote address, which represents the source of the request.
  remote_addresses.first
end

#link?Boolean

Checks the HTTP request method (or verb) to see if it was of type LINK

Returns:

  • (Boolean)
[View source]

232
# File 'lib/rack/request.rb', line 232

def link?;    request_method == LINK    end

#loggerObject

[View source]

200
# File 'lib/rack/request.rb', line 200

def logger;          get_header(RACK_LOGGER)                        end

#media_typeObject

The media type (type/subtype) portion of the CONTENT_TYPE header without any media type parameters. e.g., when CONTENT_TYPE is “text/plain;charset=utf-8”, the media-type is “text/plain”.

For more information on the use of media types in HTTP, see: www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7

[View source]

441
442
443
# File 'lib/rack/request.rb', line 441

def media_type
  MediaType.type(content_type)
end

#media_type_paramsObject

The media type parameters provided in CONTENT_TYPE as a Hash, or an empty Hash if no CONTENT_TYPE or media-type parameters were provided. e.g., when the CONTENT_TYPE is “text/plain;charset=utf-8”, this method responds with the following Hash:

{ 'charset' => 'utf-8' }
[View source]

450
451
452
# File 'lib/rack/request.rb', line 450

def media_type_params
  MediaType.params(content_type)
end

#options?Boolean

Checks the HTTP request method (or verb) to see if it was of type OPTIONS

Returns:

  • (Boolean)
[View source]

229
# File 'lib/rack/request.rb', line 229

def options?; request_method == OPTIONS end

#paramsObject

The union of GET and POST data.

Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params.

[View source]

556
557
558
# File 'lib/rack/request.rb', line 556

def params
  self.GET.merge(self.POST)
end

#parseable_data?Boolean

Determine whether the request body contains data by checking the request media_type against registered parse-data media-types

Returns:

  • (Boolean)
[View source]

479
480
481
# File 'lib/rack/request.rb', line 479

def parseable_data?
  PARSEABLE_DATA_MEDIA_TYPES.include?(media_type)
end

#patch?Boolean

Checks the HTTP request method (or verb) to see if it was of type PATCH

Returns:

  • (Boolean)
[View source]

235
# File 'lib/rack/request.rb', line 235

def patch?;   request_method == PATCH   end

#pathObject

[View source]

599
600
601
# File 'lib/rack/request.rb', line 599

def path
  script_name + path_info
end

#path_infoObject

[View source]

194
# File 'lib/rack/request.rb', line 194

def path_info;       get_header(PATH_INFO).to_s                     end

#path_info=(s) ⇒ Object

[View source]

195
# File 'lib/rack/request.rb', line 195

def path_info=(s);   set_header(PATH_INFO, s.to_s)                  end

#portObject

[View source]

345
346
347
348
349
350
351
# File 'lib/rack/request.rb', line 345

def port
  if authority = self.authority
    _, _, port = split_authority(authority)
  end

  port || forwarded_port&.last || DEFAULT_PORTS[scheme] || server_port
end

#POSTObject

Returns the data received in the request body.

This method support both application/x-www-form-urlencoded and multipart/form-data.

[View source]

503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
# File 'lib/rack/request.rb', line 503

def POST
  if error = get_header(RACK_REQUEST_FORM_ERROR)
    raise error.class, error.message, cause: error.cause
  end

  begin
    rack_input = get_header(RACK_INPUT)

    # If the form hash was already memoized:
    if form_hash = get_header(RACK_REQUEST_FORM_HASH)
      form_input = get_header(RACK_REQUEST_FORM_INPUT)
      # And it was memoized from the same input:
      if form_input.equal?(rack_input)
        return form_hash
      elsif form_input
        warn "input stream used for POST parsing different from current input stream. Starting in Rack 3.2, Rack will used the cached POST value instead of parsing the current input stream.", uplevel: 1
      end
    end

    # Otherwise, figure out how to parse the input:
    if rack_input.nil?
      set_header RACK_REQUEST_FORM_INPUT, nil
      set_header(RACK_REQUEST_FORM_HASH, {})
    elsif form_data? || parseable_data?
      if pairs = Rack::Multipart.parse_multipart(env, Rack::Multipart::ParamList)
        set_header RACK_REQUEST_FORM_PAIRS, pairs
        set_header RACK_REQUEST_FORM_HASH, expand_param_pairs(pairs)
      else
        form_vars = get_header(RACK_INPUT).read

        # Fix for Safari Ajax postings that always append \0
        # form_vars.sub!(/\0\z/, '') # performance replacement:
        form_vars.slice!(-1) if form_vars.end_with?("\0")

        set_header RACK_REQUEST_FORM_VARS, form_vars
        set_header RACK_REQUEST_FORM_HASH, parse_query(form_vars, '&')
      end

      set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
      get_header RACK_REQUEST_FORM_HASH
    else
      set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
      set_header(RACK_REQUEST_FORM_HASH, {})
    end
  rescue => error
    set_header(RACK_REQUEST_FORM_ERROR, error)
    raise
  end
end

#post?Boolean

Checks the HTTP request method (or verb) to see if it was of type POST

Returns:

  • (Boolean)
[View source]

238
# File 'lib/rack/request.rb', line 238

def post?;    request_method == POST    end

#put?Boolean

Checks the HTTP request method (or verb) to see if it was of type PUT

Returns:

  • (Boolean)
[View source]

241
# File 'lib/rack/request.rb', line 241

def put?;     request_method == PUT     end

#query_stringObject

[View source]

198
# File 'lib/rack/request.rb', line 198

def query_string;    get_header(QUERY_STRING).to_s                  end

#refererObject Also known as: referrer

the referer of the client

[View source]

204
# File 'lib/rack/request.rb', line 204

def referer;         get_header('HTTP_REFERER')                     end

#request_methodObject

[View source]

197
# File 'lib/rack/request.rb', line 197

def request_method;  get_header(REQUEST_METHOD)                     end

#schemeObject

[View source]

249
250
251
252
253
254
255
256
257
258
259
# File 'lib/rack/request.rb', line 249

def scheme
  if get_header(HTTPS) == 'on'
    'https'
  elsif get_header(HTTP_X_FORWARDED_SSL) == 'on'
    'https'
  elsif forwarded_scheme
    forwarded_scheme
  else
    get_header(RACK_URL_SCHEME)
  end
end

#script_nameObject

[View source]

191
# File 'lib/rack/request.rb', line 191

def script_name;     get_header(SCRIPT_NAME).to_s                   end

#script_name=(s) ⇒ Object

[View source]

192
# File 'lib/rack/request.rb', line 192

def script_name=(s); set_header(SCRIPT_NAME, s.to_s)                end

#server_authorityObject

The authority as defined by the ‘SERVER_NAME` and `SERVER_PORT` variables.

[View source]

272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/rack/request.rb', line 272

def server_authority
  host = self.server_name
  port = self.server_port

  if host
    if port
      "#{host}:#{port}"
    else
      host
    end
  end
end

#server_nameObject

[View source]

285
286
287
# File 'lib/rack/request.rb', line 285

def server_name
  get_header(SERVER_NAME)
end

#server_portObject

[View source]

289
290
291
# File 'lib/rack/request.rb', line 289

def server_port
  get_header(SERVER_PORT)
end

#sessionObject

[View source]

207
208
209
210
211
# File 'lib/rack/request.rb', line 207

def session
  fetch_header(RACK_SESSION) do |k|
    set_header RACK_SESSION, default_session
  end
end

#session_optionsObject

[View source]

213
214
215
216
217
# File 'lib/rack/request.rb', line 213

def session_options
  fetch_header(RACK_SESSION_OPTIONS) do |k|
    set_header RACK_SESSION_OPTIONS, {}
  end
end

#ssl?Boolean

Returns:

  • (Boolean)
[View source]

410
411
412
# File 'lib/rack/request.rb', line 410

def ssl?
  scheme == 'https' || scheme == 'wss'
end

#trace?Boolean

Checks the HTTP request method (or verb) to see if it was of type TRACE

Returns:

  • (Boolean)
[View source]

244
# File 'lib/rack/request.rb', line 244

def trace?;   request_method == TRACE   end

#trusted_proxy?(ip) ⇒ Boolean

Returns:

  • (Boolean)
[View source]

615
616
617
# File 'lib/rack/request.rb', line 615

def trusted_proxy?(ip)
  Rack::Request.ip_filter.call(ip)
end

#unlink?Boolean

Checks the HTTP request method (or verb) to see if it was of type UNLINK

Returns:

  • (Boolean)
[View source]

247
# File 'lib/rack/request.rb', line 247

def unlink?;  request_method == UNLINK  end

#update_param(k, v) ⇒ Object

Destructively update a parameter, whether it’s in GET and/or POST. Returns nil.

The parameter is updated wherever it was previous defined, so GET, POST, or both. If it wasn’t previously defined, it’s inserted into GET.

env['rack.input'] is not touched.

[View source]

565
566
567
568
569
570
571
572
573
574
575
576
577
578
# File 'lib/rack/request.rb', line 565

def update_param(k, v)
  found = false
  if self.GET.has_key?(k)
    found = true
    self.GET[k] = v
  end
  if self.POST.has_key?(k)
    found = true
    self.POST[k] = v
  end
  unless found
    self.GET[k] = v
  end
end

#urlObject

Tries to return a remake of the original request URL as a string.

[View source]

595
596
597
# File 'lib/rack/request.rb', line 595

def url
  base_url + fullpath
end

#user_agentObject

[View source]

201
# File 'lib/rack/request.rb', line 201

def user_agent;      get_header('HTTP_USER_AGENT')                  end

#values_at(*keys) ⇒ Object

like Hash#values_at

[View source]

620
621
622
623
624
# File 'lib/rack/request.rb', line 620

def values_at(*keys)
  warn("Request#values_at is deprecated and will be removed in a future version of Rack. Please use request.params.values_at instead", uplevel: 1)
  
  keys.map { |key| params[key] }
end

#xhr?Boolean

Returns:

  • (Boolean)
[View source]

313
314
315
# File 'lib/rack/request.rb', line 313

def xhr?
  get_header("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest"
end