Skip to content

Instantly share code, notes, and snippets.

@fwolfst
Created September 20, 2023 10:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fwolfst/3aa45686b912bfcb3bea102aeb1bfda5 to your computer and use it in GitHub Desktop.
Save fwolfst/3aa45686b912bfcb3bea102aeb1bfda5 to your computer and use it in GitHub Desktop.
rails initializer for sprockets patch
# Avoid a funky bug in Sprockets
# https://github.com/rails/sprockets/issues/749
# made serving files likes /assets/logos/layout-logo-compact.svg
# impossible under certain circumstances.
class MonkeyPatch🐒ObsoleteCheck < StandardError
end
CURRENT_SPROCKETS_VERSION_WITHOUT_PATCH = "4.2.1"
if Sprockets::VERSION != CURRENT_SPROCKETS_VERSION_WITHOUT_PATCH
raise MonkeyPatch🐒ObsoleteCheck.new(
<<-MESSAGE
Sprockets was updated! (finally?)
Has https://github.com/rails/sprockets/pull/793/ been merged?'
-> If so, delete this file.
Offending spec is e.g.:
`rspec ./spec/dependsonyourprojcet.rb:5`
MESSAGE
)
end
# Patch from https://github.com/rails/sprockets/pull/793/
module Sprockets
# `Server` is a concern mixed into `Environment` and
# `CachedEnvironment` that provides a Rack compatible `call`
# interface and url generation helpers.
module Server
def call(env)
start_time = Time.now.to_f
time_elapsed = lambda { ((Time.now.to_f - start_time) * 1000).to_i }
unless ALLOWED_REQUEST_METHODS.include? env['REQUEST_METHOD']
return method_not_allowed_response
end
msg = "Served asset #{env['PATH_INFO']} -"
# Extract the path from everything after the leading slash
full_path = Rack::Utils.unescape(env['PATH_INFO'].to_s.sub(/^\//, ''))
path = full_path
return bad_request_response(env) unless path.valid_encoding?
return forbidden_response(env) if forbidden_request?(path)
asset = find_asset(path)
# Strip fingerprint
if asset.nil? && fingerprint = path_fingerprint(path)
path = path.sub("-#{fingerprint}", '')
return forbidden_response(env) if forbidden_request?(path)
asset = find_asset(path)
end
if fingerprint
if_match = asset&.etag
elsif env['HTTP_IF_MATCH']
if_match = env['HTTP_IF_MATCH'][/"(\w+)"$/, 1]
end
if env['HTTP_IF_NONE_MATCH']
if_none_match = env['HTTP_IF_NONE_MATCH'][/"(\w+)"$/, 1]
end
if asset.nil?
status = :not_found
elsif fingerprint && asset.etag != fingerprint
status = :not_found
elsif if_match && asset.etag != if_match
status = :precondition_failed
elsif if_none_match && asset.etag == if_none_match
status = :not_modified
else
status = :ok
end
case status
when :ok
logger.info "#{msg} 200 OK (#{time_elapsed.call}ms)"
ok_response(asset, env)
when :not_modified
logger.info "#{msg} 304 Not Modified (#{time_elapsed.call}ms)"
not_modified_response(env, if_none_match)
when :not_found
logger.info "#{msg} 404 Not Found (#{time_elapsed.call}ms)"
not_found_response(env)
when :precondition_failed
logger.info "#{msg} 412 Precondition Failed (#{time_elapsed.call}ms)"
precondition_failed_response(env)
end
rescue Exception => e
logger.error "Error compiling asset #{path}:"
logger.error "#{e.class.name}: #{e.message}"
case File.extname(path)
when ".js"
# Re-throw JavaScript asset exceptions to the browser
logger.info "#{msg} 500 Internal Server Error\n\n"
return javascript_exception_response(e)
when ".css"
# Display CSS asset exceptions in the browser
logger.info "#{msg} 500 Internal Server Error\n\n"
return css_exception_response(e)
else
raise
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment