diff options
-rw-r--r-- | Gemfile | 1 | ||||
-rw-r--r-- | config.ru | 10 | ||||
-rw-r--r-- | lib/poe/core.rb | 59 | ||||
-rw-r--r-- | lib/poe/snippet.rb | 22 | ||||
-rw-r--r-- | lib/poe/webapp.rb | 22 | ||||
-rw-r--r-- | poe-config.json | 5 |
6 files changed, 115 insertions, 4 deletions
@@ -1,3 +1,4 @@ source "https://rubygems.org" gem "msgpack", "~> 1.1" +gem "sinatra", "~> 2.0" @@ -1,10 +1,14 @@ -require "rack" require_relative "lib/poe/webapp" +require "rack" + +# Load configuration from ENV["POE_CONFIG"] or $(pwd)/poe.json +Poe::Config.load -use Rack::CommonLogger if Poe.debug? use Rack::ShowExceptions use Rack::Lint end -run Sinatra::Application +use Rack::CommonLogger + +run Poe::WebApp diff --git a/lib/poe/core.rb b/lib/poe/core.rb new file mode 100644 index 0000000..df15894 --- /dev/null +++ b/lib/poe/core.rb @@ -0,0 +1,59 @@ +require_relative "snippet" +require "json" + +module Poe + module_function + + def debug? + Poe::Config.fetch("debug", false) + end + + def datadir + Poe::Config.expand_path(Poe::Config.fetch("datadir")) + end + + def tmpdir + Poe::Config.expand_path(Poe::Config.fetch("tmpdir")) + end + + module Config + module_function + + def load(path = ENV["POE_CONFIG"]) + path or raise "config file for poe not given; set POE_CONFIG " \ + "environment variable to the path" + t = File.read(path) + @hash = JSON.parse(t) + @config_base_path = File.dirname(path) + end + + def expand_path(path) + check + File.expand_path(path, @config_base_path) + end + + def fetch(path, default = UNSPECIFIED) + check + path.split(".").inject(@hash) do |h, c| + h.fetch(c) or ( + if default == UNSPECIFIED + raise KeyError, "config key %s not found" % path + else + return default + end + ) + end + end + + def check + return if defined?(@hash) + raise "[BUG] config is not loaded yet" + end + + UNSPECIFIED = Object.new + end + + class PoeError < StandardError; end + class SnippetNotFound < PoeError; end + class OutputNotFound < PoeError; end +end diff --git a/lib/poe/snippet.rb b/lib/poe/snippet.rb new file mode 100644 index 0000000..18f1512 --- /dev/null +++ b/lib/poe/snippet.rb @@ -0,0 +1,22 @@ +require_relative "core" + +class Poe::Snippet + # FIXME + SID_PATTERN = /\A[0-9a-f]{32,64}\z/ + RID_PATTERN = /\A(?:0|[1-9]\d+)\z/ + + attr_reader :id + + def initialize(sid, *) + @id = sid + end + + class << self + def find(sid) + raise Poe::SnippetNotFound, "invalid sid format" if SID_PATTERN !~ sid + json = File.read(File.join(Poe.datadir, "snippets", sid, "metadata.json")) + hash = JSON.parse(json, symbolize_keys: true) + new(sid, **hash) + end + end +end diff --git a/lib/poe/webapp.rb b/lib/poe/webapp.rb index 2a55eaa..5e38b12 100644 --- a/lib/poe/webapp.rb +++ b/lib/poe/webapp.rb @@ -1,2 +1,22 @@ -require "sinatra" +require_relative "core" +require "sinatra/base" require "msgpack" + +class Poe::WebApp < Sinatra::Base + post "/api/snippet/new" do + content_type :json + s = Poe::Snippet.create(params[:snippet]) + Poe::Runner.enqueue(s) + s.to_json + end + + get "/api/snippet/:sid" do + content_type :json + Poe::Snippet.find(params[:sid]).to_json + end + + get "/api/snippet/:sid/:rid/stdout" do + content_type :text + Poe::Snippet.find(params[:sid]).result(params[:rid]).split_stdout + end +end diff --git a/poe-config.json b/poe-config.json new file mode 100644 index 0000000..231b449 --- /dev/null +++ b/poe-config.json @@ -0,0 +1,5 @@ +{ + "debug": true, + "tmpdir": "tmp", + "datadir": "data" +} |