From 40b0b927d7ed7370fbc7dba3aa0fd92c132aad8f Mon Sep 17 00:00:00 2001 From: Simon Baird Date: Sat, 24 Apr 2021 15:15:18 -0400 Subject: [PATCH] Support uploads using the put saver TiddlyWiki's upload.js saver is old and deprecated so let's see if we can switch to using the put saver. Includes: - A bogus WebDAV header to convince TiddlyWiki that the put saver is usable - A new controller method and route for the "put" saves - Clear the url from $:/UploadURL when serving a site to make sure TW doesn't try to use the upload saver There's a related PR for TiddlyWiki that exposes the error messages to the user, see https://github.com/Jermolene/TiddlyWiki5/pull/6589 Issue: #148 --- .../app/controllers/tiddlywiki_controller.rb | 31 +++++++++++++++++-- rails/app/models/site.rb | 3 +- rails/config/routes.rb | 3 +- rails/lib/th_file.rb | 19 +++++++----- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/rails/app/controllers/tiddlywiki_controller.rb b/rails/app/controllers/tiddlywiki_controller.rb index 3facc96af..44e3efcde 100644 --- a/rails/app/controllers/tiddlywiki_controller.rb +++ b/rails/app/controllers/tiddlywiki_controller.rb @@ -7,7 +7,7 @@ class TiddlywikiController < ApplicationController before_action :find_site # TiddlyWiki can't provide the token for saving so we need to skip it - skip_before_action :verify_authenticity_token, only: :save + skip_before_action :verify_authenticity_token, only: [:upload_save, :put_save] # Rails wants a token for options requests, which TiddlyWiki similarly can't provide skip_before_action :verify_authenticity_token, @@ -20,6 +20,9 @@ class TiddlywikiController < ApplicationController def serve return site_not_available unless site_visible? + # Convince TiddlyWiki it can use the put saver + dummy_webdav_header if request.options? && @site.enable_put_saver? + etag_header # Avoid site download for head or options requests @@ -92,7 +95,8 @@ def download download_html_content(@site.download_content, @site.name) end - def save + # Using the "upload" saver + def upload_save begin if site_saveable? @site.file_upload(params[:userfile]) @@ -108,6 +112,24 @@ def save end end + # Using the "put" saver + def put_save + begin + if site_saveable? + @site.file_upload(request.body) + @site.increment_save_count + head 204 + else + err_message = "If this is your site please log in at #{main_site_url} and try again." + render status: 403, plain: err_message + end + rescue => e + # Todo: Should probably give a generic "Save failed!" message, and log the real problem + err_message = "#{e.class.name} #{e.message}" + render status: 500, plain: err_message + end + end + private def update_view_count_and_access_timestamp @@ -200,4 +222,9 @@ def cors_headers response.set_header 'Access-Control-Allow-Headers', 'X-Requested-With' end + # TiddlyWiki just checks if the header exists so the value doesn't matter + def dummy_webdav_header + response.set_header 'dav', "Dummy WebDAV header to enable TiddlyWiki's PUT saver" + end + end diff --git a/rails/app/models/site.rb b/rails/app/models/site.rb index 3805efd38..3a36467d1 100644 --- a/rails/app/models/site.rb +++ b/rails/app/models/site.rb @@ -56,7 +56,8 @@ def looks_valid? end def html_content(signed_in_user: nil) - th_file.apply_tiddlyhost_mods(name, signed_in_user: signed_in_user).to_html + th_file.apply_tiddlyhost_mods(name, + signed_in_user: signed_in_user, enable_put_saver: enable_put_saver).to_html end def json_data(opts={}) diff --git a/rails/config/routes.rb b/rails/config/routes.rb index 013b0fb0e..fd03b1fe6 100644 --- a/rails/config/routes.rb +++ b/rails/config/routes.rb @@ -29,7 +29,8 @@ get '/favicon.ico', to: 'tiddlywiki#favicon' get '/download', to: 'tiddlywiki#download' - post '/', to: 'tiddlywiki#save' + post '/', to: 'tiddlywiki#upload_save' + put '/', to: 'tiddlywiki#put_save' end # diff --git a/rails/lib/th_file.rb b/rails/lib/th_file.rb index 4f246e4a4..180b63bde 100644 --- a/rails/lib/th_file.rb +++ b/rails/lib/th_file.rb @@ -38,17 +38,22 @@ def self.from_empty(empty_type) from_file(empty_path(empty_type)) end - def apply_tiddlyhost_mods(site_name, for_download: false, signed_in_user: nil) + def apply_tiddlyhost_mods(site_name, for_download: false, enable_put_saver: false, signed_in_user: nil) if is_tw5? - upload_url = if !for_download - # The url for uploads is the same as the site url - Settings.subdomain_site_url(site_name) - else - # Clear $:/UploadURL so the save button in the downloaded file will not try - # to use upload.js. It should use another save method, probably download to file. + upload_url = if for_download || enable_put_saver + # Clear $:/UploadURL for downloads so the save button in the downloaded + # file will not try to use upload.js. It should use another save + # method, probably download to file. + # # Todo: Consider if we should do that also when signed_in_user is nil. + # + # Clear $:/UploadURL when using the put saver otherwise TW will + # prioritize the upload saver "" + else + # The url for uploads is the same as the site url + Settings.subdomain_site_url(site_name) end if !for_download && signed_in_user