diff --git a/.gitignore b/.gitignore index 4524de687..38b3ca7e5 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ public/stylesheets/sessions.css public/stylesheets/ui.css public/stylesheets/mobile.css public/diaspora +public/well-known/host-meta spec/fixtures/users.yaml # Uploded files and local files diff --git a/config.ru b/config.ru index 9cdc2591c..d01927cad 100644 --- a/config.ru +++ b/config.ru @@ -5,8 +5,13 @@ # This file is used by Rack-based servers to start the application. require ::File.expand_path('../config/environment', __FILE__) -#use Rack::FiberPool require ::File.expand_path('../lib/chrome_frame', __FILE__) +require 'lib/host-meta' +#use Rack::FiberPool + +map "/.well-known" do + run HostMeta::File.new( "public/well-known") +end map AppConfig[:pod_uri].path do use Rack::ChromeFrame, :minimum => 8 diff --git a/lib/host-meta.rb b/lib/host-meta.rb new file mode 100644 index 000000000..d3c387ad2 --- /dev/null +++ b/lib/host-meta.rb @@ -0,0 +1,83 @@ +require 'time' +require 'rack/utils' +require 'rack/mime' + +module HostMeta + + # + # Serve just a 'host-meta' request from a static file. + # + class File + attr_accessor :root + attr_accessor :path + + alias :to_path :path + + def initialize(root) + @root = root + end + + def call(env) + dup._call(env) + end + + F = ::File + + def _call(env) + @path_info = Rack::Utils.unescape(env["PATH_INFO"]) + @path = F.join(@root, @path_info) + + available = begin + @path_info == "/host-meta" && F.file?(@path) && F.readable?(@path) + rescue SystemCallError + false + end + + if available + serving(env) + else + fail(404, "File not found: #{@path_info}") + end + end + + def serving(env) + # NOTE: + # We check via File::size? whether this file provides size info + # via stat (e.g. /proc files often don't), otherwise we have to + # figure it out by reading the whole file into memory. + @size = F.size?(@path) || Rack::Utils.bytesize(F.read(@path)) + response = [ + 200, + { + "Last-Modified" => F.mtime(@path).httpdate, + "Content-Type" => 'application/xml+xrd; charset=utf-8' + }, + self + ] + response[1]["Content-Length"] = @size.to_s + response + end + + def each + F.open(@path) do |file| + yield file.read( @size) + end + end + + private + + def fail(status, body) + body += "\n" + [ + status, + { + "Content-Type" => "text/plain", + "Content-Length" => body.size.to_s, + "X-Cascade" => "pass" + }, + [body] + ] + end + + end +end diff --git a/script/server b/script/server index 5fea4a2cf..1a00d5f38 100755 --- a/script/server +++ b/script/server @@ -136,6 +136,15 @@ if [ ! -e public/source.tar.gz ]; then exit 65 fi +# create static public/well-known/host-meta if required +if [[ -w public && + (! -e public/well-known/host-meta || + public/well-known/host-meta -ot config/app_config.yml) ]] +then + bundle exec erb -r config/environment.rb app/views/publics/host_meta.erb \ + 2>/dev/null >public/well-known/host-meta +fi + # Precache jammit assets if [[ -w public && ! -e 'public/stylesheets/application.css' ]]; then if [ "$INIT_PUBLIC" != 'no' ]; then