From 518de2fdecf9297399a23b0df7431eed25b9015a Mon Sep 17 00:00:00 2001 From: evazion Date: Sun, 15 Dec 2019 14:03:15 -0600 Subject: [PATCH] cloudflare: fix purging of cached urls. * Switch CloudflareService from HttpartyCache to Danbooru::Http. * Purge cached urls from Cloudflare when a post is replaced and the md5 doesn't change. This happens when a corrupted image is replaced or thumbnails are regenerated. Before we purged urls when a post was expunged, which was unneeded because those urls can expire naturally. It was also wrong because the subdomains were hardcoded, the urls used http:// instead of https://, and we didn't account for tagged urls. --- app/logical/cloudflare_service.rb | 50 +++++++++----------------- app/logical/danbooru/http.rb | 8 +++-- app/logical/upload_service/replacer.rb | 14 ++++++++ app/models/post.rb | 4 --- 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/app/logical/cloudflare_service.rb b/app/logical/cloudflare_service.rb index 75aa54487..6a1161502 100644 --- a/app/logical/cloudflare_service.rb +++ b/app/logical/cloudflare_service.rb @@ -1,48 +1,32 @@ -# donmai.us specific - class CloudflareService + attr_reader :api_token, :zone + + def initialize(api_token: Danbooru.config.cloudflare_api_token, zone: Danbooru.config.cloudflare_zone) + @api_token, @zone = api_token, zone + end + def enabled? api_token.present? && zone.present? end - def api_token - Danbooru.config.cloudflare_api_token - end - - def zone - Danbooru.config.cloudflare_zone - end - - def options - Danbooru.config.httparty_options.deep_merge(headers: { - "Authorization" => "Bearer #{api_token}", - "Content-Type" => "application/json", - "User-Agent" => "#{Danbooru.config.canonical_app_name}/#{Rails.application.config.x.git_hash}" - }) - end - def ips(expiry: 24.hours) - text, code = HttpartyCache.get("https://api.cloudflare.com/client/v4/ips", expiry: expiry) - return [] if code != 200 + response = Danbooru::Http.cache(expiry).get("https://api.cloudflare.com/client/v4/ips") + return [] if response.code != 200 - json = JSON.parse(text, symbolize_names: true) - ips = json[:result][:ipv4_cidrs] + json[:result][:ipv6_cidrs] + result = response.parse["result"] + ips = result["ipv4_cidrs"] + result["ipv6_cidrs"] ips.map { |ip| IPAddr.new(ip) } end - def delete(md5, ext) + def purge_cache(urls) return unless enabled? - url = "https://api.cloudflare.com/client/v4/zones/#{zone}/purge_cache" - files = ["#{md5}.#{ext}", "preview/#{md5}.jpg", "sample/sample-#{md5}.jpg"].map do |name| - ["danbooru", "safebooru", "raikou1", "raikou2", "raikou3", "raikou4"].map do |subdomain| - "http://#{subdomain}.donmai.us/data/#{name}" - end - end.flatten - body = { - "files" => files - }.to_json + cloudflare = Danbooru::Http.headers( + "Authorization" => "Bearer #{api_token}", + "Content-Type" => "application/json" + ) - HTTParty.delete(url, options.merge(body: body)) #, body: body) + url = "https://api.cloudflare.com/client/v4/zones/#{zone}/purge_cache" + cloudflare.delete(url, json: { files: urls }) end end diff --git a/app/logical/danbooru/http.rb b/app/logical/danbooru/http.rb index b69cf2f4b..45771626f 100644 --- a/app/logical/danbooru/http.rb +++ b/app/logical/danbooru/http.rb @@ -3,7 +3,7 @@ module Danbooru attr_accessor :cache, :http class << self - delegate :get, :post, :cache, :auth, :basic_auth, :headers, to: :new + delegate :get, :post, :delete, :cache, :auth, :basic_auth, :headers, to: :new end def get(url, **options) @@ -14,6 +14,10 @@ module Danbooru request(:post, url, **options) end + def delete(url, **options) + request(:delete, url, **options) + end + def cache(expiry) dup.tap { |o| o.cache = expiry.to_i } end @@ -41,7 +45,7 @@ module Danbooru end def cached_request(method, url, **options) - key = Cache.hash({ method: method, url: url, **options }.to_json) + key = Cache.hash({ method: method, url: url, headers: http.default_options.headers.to_h, **options }.to_json) cached_response = Cache.get(key, @cache) do response = raw_request(method, url, **options) diff --git a/app/logical/upload_service/replacer.rb b/app/logical/upload_service/replacer.rb index b831ac796..09ac16de3 100644 --- a/app/logical/upload_service/replacer.rb +++ b/app/logical/upload_service/replacer.rb @@ -123,6 +123,8 @@ class UploadService CurrentUser.as(User.system) do post.comments.create!(body: comment_replacement_message(post, replacement), do_not_bump_post: true) end + else + purge_cached_urls(post) end replacement.save! @@ -131,6 +133,18 @@ class UploadService post.update_iqdb_async end + def purge_cached_urls(post) + urls = [ + post.preview_file_url, + post.large_file_url, + post.file_url, + post.tagged_large_file_url, + post.tagged_file_url + ] + + CloudflareService.new.purge_cache(urls) + end + def rescale_notes(post) x_scale = post.image_width.to_f / post.image_width_was.to_f y_scale = post.image_height.to_f / post.image_height_was.to_f diff --git a/app/models/post.rb b/app/models/post.rb index 52bbb2dca..201bf3263 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -77,10 +77,6 @@ class Post < ApplicationRecord Danbooru.config.backup_storage_manager.delete_file(post_id, md5, file_ext, :original) Danbooru.config.backup_storage_manager.delete_file(post_id, md5, file_ext, :large) Danbooru.config.backup_storage_manager.delete_file(post_id, md5, file_ext, :preview) - - if Danbooru.config.cloudflare_key - CloudflareService.new.delete(md5, file_ext) - end end end