class Shrine::DerivationEndpoint

Attributes

options[R]
shrine_class[R]

Public Class Methods

new(shrine_class:, options: {}) click to toggle source
# File lib/shrine/plugins/derivation_endpoint.rb, line 354
def initialize(shrine_class:, options: {})
  @shrine_class = shrine_class
  @options      = options
end

Public Instance Methods

call(env) click to toggle source
# File lib/shrine/plugins/derivation_endpoint.rb, line 359
def call(env)
  request = Rack::Request.new(env)

  status, headers, body = catch(:halt) do
    error!(405, "Method not allowed") unless request.get? || request.head?

    handle_request(request)
  end

  headers = Rack::Headers[headers] if Rack.release >= "3"
  headers["Content-Length"] ||= body.respond_to?(:bytesize) ? body.bytesize.to_s :
                                                              body.map(&:bytesize).inject(0, :+).to_s

  [status, headers, body]
end
handle_request(request) click to toggle source

Verifies validity of the URL, then extracts parameters from it (such as derivation name, arguments and source file), and generates a derivation response.

Returns “403 Forbidden” if signature is invalid, or if the URL has expired.

Returns “404 Not Found” if derivation block is not defined, or if source file was not found on the storage.

# File lib/shrine/plugins/derivation_endpoint.rb, line 384
def handle_request(request)
  verify_signature!(request) if secret_key
  check_expiry!(request)

  name, *args, serialized_file = request.path_info.split("/")[1..-1]

  name          = name.to_sym
  uploaded_file = shrine_class::UploadedFile.urlsafe_load(serialized_file)

  # request params override statically configured options
  options = self.options.dup
  options[:type]        = request.params["type"]        if request.params["type"]
  options[:disposition] = request.params["disposition"] if request.params["disposition"]
  options[:filename]    = request.params["filename"]    if request.params["filename"]
  options[:version]     = request.params["version"]     if request.params["version"]
  options[:expires_in]  = expires_in(request)           if request.params["expires_at"]

  derivation = uploaded_file.derivation(name, *args, **options)

  begin
    status, headers, body = derivation.response(request.env)
  rescue Derivation::SourceNotFound
    error!(404, "Source file not found")
  rescue Derivation::NotFound
    error!(404, "Unknown derivation \"#{name}\"")
  end

  # tell clients to cache the derivation result if it was successful
  if status == 200 || status == 206
    headers["Cache-Control"] = derivation.option(:cache_control)
  end

  [status, headers, body]
end
inspect() click to toggle source
# File lib/shrine/plugins/derivation_endpoint.rb, line 419
def inspect
  "#<#{@shrine_class}::DerivationEndpoint>"
end
Also aliased as: to_s
to_s()
Alias for: inspect

Private Instance Methods

check_expiry!(request) click to toggle source

Return an error response if URL has expired.

# File lib/shrine/plugins/derivation_endpoint.rb, line 435
def check_expiry!(request)
  if request.params["expires_at"]
    error!(403, "Request has expired") if expires_in(request) <= 0
  end
end
derivation_options() click to toggle source
# File lib/shrine/plugins/derivation_endpoint.rb, line 456
def derivation_options
  shrine_class.derivation_options.merge(self.options)
end
error!(status, message) click to toggle source

Halts the request with the error message.

# File lib/shrine/plugins/derivation_endpoint.rb, line 448
def error!(status, message)
  throw :halt, [status, { "Content-Type" => "text/plain" }, [message]]
end
expires_in(request) click to toggle source
# File lib/shrine/plugins/derivation_endpoint.rb, line 441
def expires_in(request)
  expires_at = Integer(request.params["expires_at"])

  (Time.at(expires_at) - Time.now).to_i
end
secret_key() click to toggle source
# File lib/shrine/plugins/derivation_endpoint.rb, line 452
def secret_key
  derivation_options[:secret_key]
end
verify_signature!(request) click to toggle source

Return an error response if the signature is invalid.

# File lib/shrine/plugins/derivation_endpoint.rb, line 427
def verify_signature!(request)
  signer = UrlSigner.new(secret_key)
  signer.verify_url("#{request.path_info[1..-1]}?#{request.query_string}")
rescue UrlSigner::InvalidSignature => error
  error!(403, error.message.capitalize)
end