./lib/lux/response/lib/file.rb in lux-fw-0.5.37 vs ./lib/lux/response/lib/file.rb in lux-fw-0.6.2

- old
+ new

@@ -1,81 +1,103 @@ # frozen_string_literal: true -class Lux::Response::File - MIMME_TYPES = { - txt: 'text/plain', - html: 'text/html', - gif: 'image/gif', - jpg: 'image/jpeg', - jpeg: 'image/jpeg', - png: 'image/png', - ico: 'image/png', # image/x-icon - css: 'text/css', - map: 'application/json', - js: 'application/javascript', - gz: 'application/x-gzip', - zip: 'application/x-gzip', - svg: 'image/svg+xml', - mp3: 'application/mp3', - woff: 'application/x-font-woff', - woff2: 'application/x-font-woff', - ttf: 'application/font-ttf', - eot: 'application/vnd.ms-fontobject', - otf: 'application/font-otf', - doc: 'application/msword' - } +module Lux + class Response + class File + class << self + def deliver_from_current + path = './public' + Lux.current.request.path + ext = path.split('.').last + return unless ext.length > 1 && ext.length < 5 + rack_file = new file: path, inline: true + rack_file.send if rack_file.is_static_file? + end - ### - # all parametars are optional - # :name - file name - # :cache - client cache in seconds - # :content_type - string type - # :inline - sets disposition to inline if true - # :disposition - inline or attachment - # :content - raw file data - def initialize file, in_opts={} - opts = in_opts.to_opts :name, :cache, :content_type, :inline, :disposition, :content - opts.disposition ||= opts.inline.class == TrueClass ? 'inline' : 'attachment' - opts.cache = true if opts.cache.nil? + def type name + MIMME_TYPES[name.to_sym] + end + end - file = 'public/%s' % file unless file[0, 1] == '/' + ### - @ext = file.include?('.') ? file.split('.').last.to_sym : nil - @file = file - @opts = opts - end + MIMME_TYPES = { + css: 'text/css', + doc: 'application/msword', + eot: 'application/vnd.ms-fontobject', + gif: 'image/gif', + gz: 'application/x-gzip', + html: 'text/html', + ico: 'image/png', # image/x-icon + jpeg: 'image/jpeg', + jpg: 'image/jpeg', + js: 'text/javascript', + json: 'application/json', + map: 'application/json', + mp3: 'application/mp3', + otf: 'application/font-otf', + png: 'image/png', + svg: 'image/svg+xml', + text: 'text/plain', + ttf: 'application/font-ttf', + txt: 'text/plain', + webp: 'image/webp', + woff: 'application/x-font-woff', + woff2: 'application/x-font-woff', + xml: 'application/xml', + zip: 'application/x-gzip' + } - define_method(:request) { Lux.current.request } - define_method(:response) { Lux.current.response } + OPTS = Struct.new 'LuxResponseFileOpts', :name, :file, :content_type, :inline, :disposition, :content, :ext, :path - def is_static_file? - return false unless @ext - File.exist?(@file) - end + ### + # all parametars are optional + # :name - file name + # :content_type - string type + # :inline - sets disposition to inline if true + # :disposition - inline or attachment + # :content - raw file data + def initialize in_opts = {} + opts = OPTS.new **in_opts + opts.disposition ||= opts.inline.class == TrueClass ? 'inline' : 'attachment' + opts.file = Pathname.new(opts.file) unless opts.file.class == Pathname + opts.path = opts.file.to_s + opts.ext = opts.path.include?('.') ? opts.path.split('.').last.to_sym : nil - def send - file = File.exist?(@file) ? @file : Lux.root.join("public#{@file}").to_s + @opts = opts + end - raise Lux::Error.not_found('Static file not found') unless File.exists?(file) + define_method(:request) { Lux.current.request } + define_method(:response) { Lux.current.response } - response.content_type(@opts.content_type || MIMME_TYPES[@ext || '_'] || 'application/octet-stream') + def is_static_file? + return false unless @opts.ext + @opts.file.exist? + end - file_mtime = File.mtime(file).utc.to_s - key = Crypt.sha1(file + (@opts.content || file_mtime.to_s)) + def etag key + response.headers['etag'] = '"%s"' % key + response.body('not-modified', status: 304) if request.env['HTTP_IF_NONE_MATCH'] == key + end - if @opts.disposition == 'attachment' - @opts.name ||= @file.split('/').last - response.headers['content-disposition'] = 'attachment; filename=%s' % @opts.name - end + def send + @opts.name ||= @opts.path.split('/').last + if @opts.disposition == 'attachment' + response.headers['content-disposition'] = 'attachment; filename=%s' % @opts.name + end - response.headers['cache-control'] = 'max-age=%d, public' % (@opts.cache ? 31536000 : 0) - response.headers['etag'] = '"%s"' % key - response.headers['last-modified'] = file_mtime + response.content_type(@opts.content_type || MIMME_TYPES[@opts.ext || '_'] || 'application/octet-stream') + response.headers['access-control-allow-origin'] ||= '*' - # IF etags match, returnfrom cache - if request.env['HTTP_IF_NONE_MATCH'] == key - response.body('not-modified', 304) - else - response.body @opts.content || File.read(file) + if @opts.content + etag Crypt.sha1 @opts.content + response.body @opts.content + else + raise Lux::Error.not_found('File not found') unless @opts.file.exist? + file_mtime = @opts.file.mtime.utc.to_s + response.headers['last-modified'] = file_mtime + etag Crypt.sha1(@opts.path + (@opts.content || file_mtime.to_s)) + response.body @opts.file.read + end + end end end -end \ No newline at end of file +end