This changes redirect_back_with_inputs to use an internal request instead of redirecting back. The main advantage from doing this is you do not need to store the submitted parameters in the flash, which avoids overflowing the session (CookieTooLarge errors) and avoids JSON::GeneratorError if the submitted inputs contain invalid UTF-8. The internal requests use the rack API to Clover, so they appear to Clover to be new GET requests from the server, for the referring page. We rotate the flash before the internal request, matching the previous redirect behavior. This changes some requests that result in error pages to use 400 responses instead of 200 responses. The 200 responses are not accurate, since the request was a failure and not a success, they were an artifact of the redirect implementation. Other than this behavior improvement, there are no changes to the specs, except for one new spec for a corner case (bad Referer header value). Note that redirects are still used inside of internal requests if the original request is a GET request. This is done to prevent internal request loops, but the issue we are trying to avoid is not a significant issue for GET requests, so it seems fine to limit it to non-GET requests. For invalid or missing referer values, this redirects back to the root, with no setting of old values. The old values wouldn't be helpful for a root request anyway. We discard the flash after making the internal request, so the flash message does not show up on the next page request. The `flash["referrer"] = referrer` code is used to handle the following case: * User goes to path X * User submits form to path Y * Results in error, redisplaying form shown on path X, but browser referer is now Y and not X * User resubmit form * Which has the same or other error, and we want to redisplay form shown on path X, not on path Y We may want to consider changing redirect_back_with_inputs to a different name, now that the standard implementation does an internal request. But that can be done later.
34 lines
881 B
Ruby
34 lines
881 B
Ruby
# frozen_string_literal: true
|
|
|
|
class Clover < Roda
|
|
def csrf_tag(*)
|
|
render("components/form/hidden", locals: {name: csrf_field, value: csrf_token(*)})
|
|
end
|
|
|
|
def redirect_back_with_inputs
|
|
referrer = flash["referrer"] || env["HTTP_REFERER"]
|
|
uri = begin
|
|
Kernel.URI(referrer)
|
|
rescue URI::InvalidURIError, ArgumentError
|
|
nil
|
|
end
|
|
|
|
request.redirect "/" unless uri
|
|
|
|
flash["old"] = request.params
|
|
|
|
if uri && env["REQUEST_METHOD"] != "GET"
|
|
# Force flash rotation, so flash works correctly for internal redirects
|
|
_roda_after_40__flash(nil)
|
|
|
|
rack_response = Clover.call(env.merge("REQUEST_METHOD" => "GET", "PATH_INFO" => uri.path))
|
|
flash.discard
|
|
flash["referrer"] = referrer
|
|
rack_response[0] = response.status || 400
|
|
request.halt rack_response
|
|
else
|
|
request.redirect referrer
|
|
end
|
|
end
|
|
end
|