Class: Protocol::Rack::Rewindable

Inherits:
HTTP::Middleware
  • Object
show all
Defined in:
lib/protocol/rack/rewindable.rb

Overview

Content-type driven input buffering, specific to the needs of ‘rack`. This middleware ensures that request bodies for certain content types can be read multiple times, which is required by Rack’s specification.

Constant Summary collapse

BUFFERED_MEDIA_TYPES =

Media types that require buffering. These types typically contain form data or file uploads that may need to be read multiple times by Rack applications.

%r{
  application/x-www-form-urlencoded|
  multipart/form-data|
  multipart/related|
  multipart/mixed
}x
POST =

The HTTP POST method.

"POST"

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ Rewindable

Initialize the rewindable middleware.



31
32
33
# File 'lib/protocol/rack/rewindable.rb', line 31

def initialize(app)
  super(app)
end

Instance Method Details

#call(request) ⇒ Object

Wrap the request body in a rewindable buffer if required. If the request needs a rewindable body, wraps it in a HTTP::Body::Rewindable.



70
71
72
73
74
75
76
# File 'lib/protocol/rack/rewindable.rb', line 70

def call(request)
  if body = request.body and needs_rewind?(request)
    request.body = Protocol::HTTP::Body::Rewindable.new(body)
  end
  
  return super
end

#make_environment(request) ⇒ Object

Create a Rack environment from the request. Delegates to the wrapped middleware.



61
62
63
# File 'lib/protocol/rack/rewindable.rb', line 61

def make_environment(request)
  @delegate.make_environment(request)
end

#needs_rewind?(request) ⇒ Boolean

Determine whether the request needs a rewindable body. A request needs a rewindable body if:

  • It’s a POST request with no content type (legacy behavior)

  • It has a content type that matches BUFFERED_MEDIA_TYPES



42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/protocol/rack/rewindable.rb', line 42

def needs_rewind?(request)
  content_type = request.headers["content-type"]
  
  if request.method == POST and content_type.nil?
    return true
  end
  
  if BUFFERED_MEDIA_TYPES =~ content_type
    return true
  end
  
  return false
end