Skip to content

Instantly share code, notes, and snippets.

@jimfoltz
Last active February 26, 2024 02:18
Show Gist options
  • Star 51 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save jimfoltz/ee791c1bdd30ce137bc23cce826096da to your computer and use it in GitHub Desktop.
Save jimfoltz/ee791c1bdd30ce137bc23cce826096da to your computer and use it in GitHub Desktop.
A local server for TiddlyWiki5 that allows saving wiki.
require 'webrick'
require 'fileutils'
if ARGV.length != 0
root = ARGV.first.gsub('\\', '/')
else
root = '.'
end
BACKUP_DIR = 'bak'
module WEBrick
module HTTPServlet
class FileHandler
alias do_PUT do_GET
end
class DefaultFileHandler
def do_PUT(req, res)
file = "#{@config[:DocumentRoot]}#{req.path}"
res.body = ''
unless Dir.exists? BACKUP_DIR
Dir.mkdir BACKUP_DIR
end
FileUtils.cp(file, "#{BACKUP_DIR}/#{File.basename(file, '.html')}.#{Time.now.to_i.to_s}.html")
File.open(file, "w+") {|f| f.puts(req.body)}
end
def do_OPTIONS(req, res)
res['Allow'] = "GET,HEAD,OPTIONS,PUT"
res['dav'] = 'anything' # TW looks for a 'dav' header, and ignores any value
end
end
end
end
server = WEBrick::HTTPServer.new({:Port => 8000, :DocumentRoot => root, :BindAddress => "127.0.0.1"})
trap "INT" do
puts "Shutting down..."
server.shutdown
end
server.start
@brianemery
Copy link

brianemery commented Aug 14, 2021

Hi Jim, I suggest adding some code to specify the bind address. If I am not mistaken, this will prevent webbrick from accepting connections from remote hosts (a portscan with nmap suggests this is true), and exposing your file system to the internet:

server = WEBrick::HTTPServer.new({:Port => 8000, :DocumentRoot => root, :BindAddress => "127.0.0.1"})

I've also added some notes on how to run this (See link).
Otherwise, thanks for this -Brian

https://github.com/brianemery/tw5_server/blob/main/tw5-server.rb

@jimfoltz
Copy link
Author

Hi Brian - good idea, thanks.

(Your link isn't working.)

@jimfoltz
Copy link
Author

Should also maybe limit the backups in some sort of rotation, or every X number of saves, or something.

@brianemery
Copy link

Ok, I think the link is fixed now -Brian

@korikori
Copy link

Hi Jim and Brian, since this isn't a repository and I can't open pull requests - just wanted to let you know that I've fixed a trailing slash bug (that may only affect my use case), and I've reformatted and expanded on the setup instructions at https://github.com/korikori/tw5_server.

@jimfoltz
Copy link
Author

@korikori - Cool, thanks. This is something I wrote, used for a minute (until I started using Timini), and haven't thought about since.

If you want, make a pull request at the TiddlyWiki repo to have the official docs point to your repo - I'll endorse it.

@korikori
Copy link

Thanks @jimfoltz, I really don't think it's necessary to make any further changes to the TiddlyWiki page - I believe that the discussion here is sufficient for anyone else who may need more information on how to run this behind NGINX as proxy.

@DestyNova
Copy link

DestyNova commented Mar 22, 2022

Should also maybe limit the backups in some sort of rotation, or every X number of saves, or something.

Hi @jimfoltz -- I've made a fork with a small modification to rotate between a fixed number of backups (defined by the BACKUP_VERSIONS constant). There's probably a much better way to do it but my Ruby is really weak. 😅
Thanks for making this BTW, really useful.

@chryoung
Copy link

chryoung commented Apr 7, 2022

Thank you for making this simple server script. I've modified it a little bit so it accepts the options for binding address and port.

tiddlywiki_server.rb

@ScottJWhite
Copy link

Works!

By the way for anyone else that wants to run this in a docker container. I had to change the BindAddress to get this to be accessible outside the contianer.

Change to:

:BindAddress => "0.0.0.0"}

@huataihuang
Copy link

Dir.exists? was deprecated in Ruby 2.1.0 and has been removed in the Ruby 3.2.0

https://www.reddit.com/r/ruby/comments/1196wti/psa_and_a_little_rant_fileexists_direxists/

suggest change:

            unless Dir.exist? BACKUP_DIR
               Dir.mkdir BACKUP_DIR
            end

@ClimaxUke
Copy link

Hello,
I've noticed this error. Any ideas?
Thanks in advance.

[2024-01-11 19:27:50] ERROR NoMethodError: undefined method `exists?' for Dir:Class
        tw5-server.rb:22:in `do_PUT'
        /usr/lib/ruby/gems/3.2.0/gems/webrick-1.8.1/lib/webrick/httpservlet/abstract.rb:105:in `service'
        /usr/lib/ruby/gems/3.2.0/gems/webrick-1.8.1/lib/webrick/httpservlet/filehandler.rb:315:in `exec_handler'
        /usr/lib/ruby/gems/3.2.0/gems/webrick-1.8.1/lib/webrick/httpservlet/filehandler.rb:246:in `do_GET'
        /usr/lib/ruby/gems/3.2.0/gems/webrick-1.8.1/lib/webrick/httpservlet/abstract.rb:105:in `service'
        /usr/lib/ruby/gems/3.2.0/gems/webrick-1.8.1/lib/webrick/httpservlet/filehandler.rb:242:in `service'
        /usr/lib/ruby/gems/3.2.0/gems/webrick-1.8.1/lib/webrick/httpserver.rb:140:in `service'
        /usr/lib/ruby/gems/3.2.0/gems/webrick-1.8.1/lib/webrick/httpserver.rb:96:in `run'
        /usr/lib/ruby/gems/3.2.0/gems/webrick-1.8.1/lib/webrick/server.rb:310:in `block in start_thread'

with

 ruby --version
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux-musl]

@jimfoltz
Copy link
Author

jimfoltz commented Jan 12, 2024

@ClimaxUke

Use Dir.exist? instead.

@huataihuang - thank you for the suggestion and fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment