class PreviewController < ApplicationController before_action :require_member! def title return render_bad_request('URL は必須です.') if params[:url].blank? render json: { title: Preview::ThumbnailFetcher.title(params[:url]) } rescue Preview::UrlSafety::UnsafeUrl => e render_bad_request(e.message) rescue Preview::HttpFetcher::FetchTimeout => e render_preview_error(e.message, :gateway_timeout) rescue Preview::HttpFetcher::ResponseTooLarge => e render_preview_error(e.message, :payload_too_large) rescue Preview::HttpFetcher::FetchFailed => e render_preview_error(e.message, :bad_gateway) end def thumbnail return render_bad_request('URL は必須です.') if params[:url].blank? image = MiniMagick::Image.read(Preview::ThumbnailFetcher.fetch(params[:url])) image.auto_orient image.resize '180x180>' image.format 'png' width, height = image.dimensions raise Preview::ThumbnailFetcher::GenerationFailed, 'サムネール画像の変換に失敗しました.' if width > 180 || height > 180 send_data image.to_blob, type: 'image/png', disposition: 'inline' rescue Preview::UrlSafety::UnsafeUrl => e render_bad_request(e.message) rescue Preview::HttpFetcher::FetchTimeout => e render_preview_error(e.message, :gateway_timeout) rescue Preview::HttpFetcher::ResponseTooLarge => e render_preview_error(e.message, :payload_too_large) rescue Preview::HttpFetcher::FetchFailed => e render_preview_error(e.message, :bad_gateway) rescue Preview::ThumbnailFetcher::GenerationFailed, MiniMagick::Error => e render_unprocessable_entity(e.message) end private def require_member! return head :unauthorized unless current_user return if current_user.gte_member? head :forbidden end def render_preview_error(message, status) render json: { type: status.to_s, message:, errors: { }, base_errors: [message] }, status: end end