Validate HTTP response length while receiving (#6891)
to_s method of HTTP::Response keeps blocking while it receives the whole content, no matter how it is big. This means it may waste time to receive unacceptably large files. It may also consume memory and disk in the process. This solves the inefficency by checking response length while receiving.
This commit is contained in:
committed by
Eugen Rochko
parent
18965cb0e6
commit
40e5d2303b
@ -55,7 +55,6 @@ class Account < ApplicationRecord
|
||||
include AccountHeader
|
||||
include AccountInteractions
|
||||
include Attachmentable
|
||||
include Remotable
|
||||
include Paginable
|
||||
|
||||
enum protocol: [:ostatus, :activitypub]
|
||||
|
||||
@ -2,4 +2,5 @@
|
||||
|
||||
class ApplicationRecord < ActiveRecord::Base
|
||||
self.abstract_class = true
|
||||
include Remotable
|
||||
end
|
||||
|
||||
@ -4,6 +4,7 @@ module AccountAvatar
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze
|
||||
LIMIT = 2.megabytes
|
||||
|
||||
class_methods do
|
||||
def avatar_styles(file)
|
||||
@ -19,7 +20,8 @@ module AccountAvatar
|
||||
# Avatar upload
|
||||
has_attached_file :avatar, styles: ->(f) { avatar_styles(f) }, convert_options: { all: '-strip' }, processors: [:lazy_thumbnail]
|
||||
validates_attachment_content_type :avatar, content_type: IMAGE_MIME_TYPES
|
||||
validates_attachment_size :avatar, less_than: 2.megabytes
|
||||
validates_attachment_size :avatar, less_than: LIMIT
|
||||
remotable_attachment :avatar, LIMIT
|
||||
end
|
||||
|
||||
def avatar_original_url
|
||||
|
||||
@ -4,6 +4,7 @@ module AccountHeader
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze
|
||||
LIMIT = 2.megabytes
|
||||
|
||||
class_methods do
|
||||
def header_styles(file)
|
||||
@ -19,7 +20,8 @@ module AccountHeader
|
||||
# Header upload
|
||||
has_attached_file :header, styles: ->(f) { header_styles(f) }, convert_options: { all: '-strip' }, processors: [:lazy_thumbnail]
|
||||
validates_attachment_content_type :header, content_type: IMAGE_MIME_TYPES
|
||||
validates_attachment_size :header, less_than: 2.megabytes
|
||||
validates_attachment_size :header, less_than: LIMIT
|
||||
remotable_attachment :header, LIMIT
|
||||
end
|
||||
|
||||
def header_original_url
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
module Remotable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
attachment_definitions.each_key do |attachment_name|
|
||||
class_methods do
|
||||
def remotable_attachment(attachment_name, limit)
|
||||
attribute_name = "#{attachment_name}_remote_url".to_sym
|
||||
method_name = "#{attribute_name}=".to_sym
|
||||
alt_method_name = "reset_#{attachment_name}!".to_sym
|
||||
@ -33,7 +33,7 @@ module Remotable
|
||||
File.extname(filename)
|
||||
end
|
||||
|
||||
send("#{attachment_name}=", StringIO.new(response.to_s))
|
||||
send("#{attachment_name}=", StringIO.new(response.body_with_limit(limit)))
|
||||
send("#{attachment_name}_file_name=", basename + extname)
|
||||
|
||||
self[attribute_name] = url if has_attribute?(attribute_name)
|
||||
|
||||
@ -19,6 +19,8 @@
|
||||
#
|
||||
|
||||
class CustomEmoji < ApplicationRecord
|
||||
LIMIT = 50.kilobytes
|
||||
|
||||
SHORTCODE_RE_FRAGMENT = '[a-zA-Z0-9_]{2,}'
|
||||
|
||||
SCAN_RE = /(?<=[^[:alnum:]:]|\n|^)
|
||||
@ -29,14 +31,14 @@ class CustomEmoji < ApplicationRecord
|
||||
|
||||
has_attached_file :image, styles: { static: { format: 'png', convert_options: '-coalesce -strip' } }
|
||||
|
||||
validates_attachment :image, content_type: { content_type: 'image/png' }, presence: true, size: { in: 0..50.kilobytes }
|
||||
validates_attachment :image, content_type: { content_type: 'image/png' }, presence: true, size: { less_than: LIMIT }
|
||||
validates :shortcode, uniqueness: { scope: :domain }, format: { with: /\A#{SHORTCODE_RE_FRAGMENT}\z/ }, length: { minimum: 2 }
|
||||
|
||||
scope :local, -> { where(domain: nil) }
|
||||
scope :remote, -> { where.not(domain: nil) }
|
||||
scope :alphabetic, -> { order(domain: :asc, shortcode: :asc) }
|
||||
|
||||
include Remotable
|
||||
remotable_attachment :image, LIMIT
|
||||
|
||||
def local?
|
||||
domain.nil?
|
||||
|
||||
@ -56,6 +56,8 @@ class MediaAttachment < ApplicationRecord
|
||||
},
|
||||
}.freeze
|
||||
|
||||
LIMIT = 8.megabytes
|
||||
|
||||
belongs_to :account, inverse_of: :media_attachments, optional: true
|
||||
belongs_to :status, inverse_of: :media_attachments, optional: true
|
||||
|
||||
@ -64,10 +66,9 @@ class MediaAttachment < ApplicationRecord
|
||||
processors: ->(f) { file_processors f },
|
||||
convert_options: { all: '-quality 90 -strip' }
|
||||
|
||||
include Remotable
|
||||
|
||||
validates_attachment_content_type :file, content_type: IMAGE_MIME_TYPES + VIDEO_MIME_TYPES
|
||||
validates_attachment_size :file, less_than: 8.megabytes
|
||||
validates_attachment_size :file, less_than: LIMIT
|
||||
remotable_attachment :file, LIMIT
|
||||
|
||||
validates :account, presence: true
|
||||
validates :description, length: { maximum: 420 }, if: :local?
|
||||
|
||||
@ -26,6 +26,7 @@
|
||||
|
||||
class PreviewCard < ApplicationRecord
|
||||
IMAGE_MIME_TYPES = ['image/jpeg', 'image/png', 'image/gif'].freeze
|
||||
LIMIT = 1.megabytes
|
||||
|
||||
self.inheritance_column = false
|
||||
|
||||
@ -36,11 +37,11 @@ class PreviewCard < ApplicationRecord
|
||||
has_attached_file :image, styles: { original: { geometry: '400x400>', file_geometry_parser: FastGeometryParser } }, convert_options: { all: '-quality 80 -strip' }
|
||||
|
||||
include Attachmentable
|
||||
include Remotable
|
||||
|
||||
validates :url, presence: true, uniqueness: true
|
||||
validates_attachment_content_type :image, content_type: IMAGE_MIME_TYPES
|
||||
validates_attachment_size :image, less_than: 1.megabytes
|
||||
validates_attachment_size :image, less_than: LIMIT
|
||||
remotable_attachment :image, LIMIT
|
||||
|
||||
before_save :extract_dimensions, if: :link?
|
||||
|
||||
|
||||
Reference in New Issue
Block a user