Class: Onesie

Inherits:
Object
  • Object
show all
Defined in:
lib/onesie.rb

Overview

For any request path that doesn’t match options[:path], immediately redirect to #{options[:path]}/#/#{request-path} after dropping the original request path in the session. For any request that comes in, matches options[:path], and has a request-path in the session, rewrite the request to match the path info in the session, remove the session copy, and allow the app to route/handle as normal.

Constant Summary collapse

VERSION =

Duh.

"1.0.0"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ Onesie

Create a new instance of this middleware. app (required) is the Rack application we’re wrapping. Valid options:

:except  # An Array of prefix strings or Regexps to ignore.
:log     # A lambda for logging, takes one message arg.
:only    # An array of prefix strings or Regexps to require.
:path    # The correct path for the one-page app. Default: "/"


26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/onesie.rb', line 26

def initialize app, options = {}
  @app    = app
  @except = Array(options[:except]).map { |e| regexpify e }
  @log    = options[:log]
  @only   = Array(options[:only]).map   { |o| regexpify o }
  @path   = options[:path] || "/"

  if FalseClass === @log
    @log = lambda { |m| }
  elsif !@log
    if defined? Rails
      @log = lambda { |m| Rails.logger.info "  [Onesie] #{m}" }
    else
      @log = lambda { |m| puts "[Onesie] #{m}" }
    end
  end
end

Instance Attribute Details

#exceptObject (readonly)

Returns the value of attribute except.



16
17
18
# File 'lib/onesie.rb', line 16

def except
  @except
end

#onlyObject (readonly)

Returns the value of attribute only.



16
17
18
# File 'lib/onesie.rb', line 16

def only
  @only
end

#pathObject (readonly)

Returns the value of attribute path.



16
17
18
# File 'lib/onesie.rb', line 16

def path
  @path
end

Instance Method Details

#call(env) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/onesie.rb', line 44

def call env
  request = Rack::Request.new env
  session = env["rack.session"]

  session.delete "onesie.path" if /onesie.clear/ =~ env["REQUEST_URI"]

  allowed = only.empty? || only.any? { |o| o =~ request.path_info }
  denied  = except.any? { |e| e =~ request.path_info }

  return @app.call env if request.xhr? || !allowed || denied

  if request.path_info == @path
    path = session.delete("onesie.path") || "/"
    old_path_info = request.path_info

    env["PATH_INFO"] = env["onesie.path"] = path
    env["REQUEST_URI"].sub!(/^#{old_path_info}/, path)

    @log.call "actual path is #{path}"
    return @app.call env
  end

  session["onesie.path"] = dest = request.path_info
  request.path_info = @path
  request.path_info << "/" unless "/" == request.path_info[-1, 1]

  dest = request.url + "##{dest}"
  @log.call "redirecting to #{dest}"

  [302, { "Location" => dest }, "Redirecting."]
end