Skip to content
Snippets Groups Projects
Commit 535f5755 authored by cleemy desu wayo's avatar cleemy desu wayo
Browse files

Modify: add new builtin data source "web-001" (experimental)

This commit adds simple web server functionality.

It is more for one-liners.

If the ring method is defined in outvoke.conf.rb and port 8080
is free, then if you start Outoke as follows and then access
lodalhost:8080 via HTTP, you will hear a sound each time you
access.

  ./outvoke.rb -e 'hookweb{ring}'

It may be more convenient to do it as follows:

  ./outvoke.rb -e 'hookweb{ring; "ok"}'

The following example displays the request headers in an
easy-to-read format.

  ./outvoke.rb -e 'hookweb{ _1.req.header.to_yaml }'

You can change the port by doing the following outside the
block passed to the hook.

$outvoke["web-001"].port = 8081

You can also put the above line in outvoke.conf.rb.

The data source “web-001” uses the following features recently
added to Outvoke:

  - post_procs (20f8d9c1)
  - attachment (d558e477)
  - msgid (0c1a0563)
  - new instance variable "ds" (835cc873)
  - new instance variable "outvoke" (bf184875)
  - OutvokeDataSource#generate_context (698e59bc)

This commit is also related to 1c328546 which changed to use
Object#to_yaml instead of Marshal.#dump. Because both
WEBrick::HTTPRequest objects and WEBrick::HTTPResponse objects
cause errors when Marshal.#dump.
parent b209dfd5
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/env ruby
#
# ==========================================================================
# Outvoke -- version 0.0.99.20241125.1
# Outvoke -- version 0.0.99.20241127
#
# written by cleemy desu wayo / Licensed under CC0 1.0
#
......@@ -14,6 +14,7 @@
require 'time'
require 'yaml'
require 'json'
class Outvoke
attr_accessor :version, :ds, :hooks, :hooks_first_time, :wait, :nodup_list,
......@@ -25,7 +26,7 @@ class Outvoke
@version = Struct.new(:branch, :body).new(
'0.1',
'0.0.99.20241125.1'
'0.0.99.20241127'
)
@ds = Hash.new
......@@ -226,7 +227,7 @@ class Outvoke
# execute
if hook['proc']
tmp_context = OutvokeProcExecContext.new(self, ds, event)
tmp_context = ds.generate_context(event)
hook_result = tmp_context.instance_exec(event, &hook['proc'])
else
hook_result_for_post_process = event.body
......@@ -300,6 +301,10 @@ module OutvokeDSL
hook("every-sec", event_cond, &block)
end
def hookweb(event_cond = true, &block)
hook("web-001", event_cond, &block)
end
def hookvr(event_cond = true, &block)
hook(/^vr/, event_cond, &block)
end
......@@ -441,6 +446,10 @@ class OutvokeDataSource
def first_time_log_check
raise NotImplementedError
end
def generate_context(event)
OutvokeProcExecContext.new(@outvoke, self, event)
end
end
#
......@@ -586,6 +595,166 @@ class OutvokeDataSourceLoopback < OutvokeDataSource
end
end
#
# TODO: experimental and incomplete implementation
#
# (specifications are subject to sudden change without notice)
#
StructDSWebStatus = Struct.new(:now, :last_time, :ds_label)
StructDSWebEvent = Struct.new(:status, :msgid, :time, :body, :attachment, :m, :is_quiet_mode,
:req, :get, :post, :res)
class OutvokeDataSourceWeb < OutvokeDataSource
attr_accessor :port, :document_root, :mount_proc_dir, :timeout
attr_reader :first_res_list
def initialize(outvoke, label)
super
@status = StructDSWebStatus.new
@status.last_time = Time.now.floor
@websrv = nil
@port = 8080
@document_root = nil
@mount_proc_dir = "/"
@timeout = 5
@first_res_list = Hash.new
@mutex_first_res = Mutex.new
@post_procs = []
@post_procs << ->(e, hook_result) {
register_first_res(e.msgid, hook_result)
}
end
# TODO
def enabled=(x)
@is_enabled = !!x
end
def websrv_start
require 'uri'
require 'webrick'
websrv = WEBrick::HTTPServer.new({:Port => @port,
:DocumentRoot => @document_root})
if @mount_proc_dir
websrv.mount_proc @mount_proc_dir do |req, res|
req.query # TODO
msgid = self << { "body" => req.path.to_s.dup, "attachment" => [req, res] }
res_found = false
loop_start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
loop do
break if loop_start_time + @timeout < Process.clock_gettime(Process::CLOCK_MONOTONIC)
# TODO (delete from @first_res_list when done)
tmp_res = nil
@mutex_first_res.synchronize do
tmp_res = @first_res_list[msgid]
end
if tmp_res
if res == tmp_res
# nop
elsif tmp_res.is_a?(WEBrick::HTTPResponse) # maybe hookcc
res.body = tmp_res.body
tmp_res.header.each do |key, value|
res.header[key] = value
end
else
res.body = tmp_res.to_s
res.body += "\n" if res.body[-1] != "\n"
end
res_found = true
break
end
end
unless res_found
res.status = 500
res.body = "error\n"
end
end
end
Thread.start { websrv.start }
end
def each_event
@log_lines.each do |line|
event = StructDSWebEvent.new
event.time = Time.now
event.msgid = line["msgid"]
event.body = line["body"].to_s
event.attachment = line["attachment"]
event.req = line["attachment"][0]
event.res = line["attachment"][1]
if event.req.request_method == "GET"
event.get = event.req.query
event.post = Hash.new
elsif event.req.request_method == "POST"
event.get = Hash[URI::decode_www_form(event.req.request_uri.query)]
event.post = event.req.query
end
event.status = @status
event.status.now = event.time
event.status.ds_label = @label
yield event
@status.last_time = event.time
end
self
end
def before_each_event
@log_lines = []
@mutex_lo.synchronize do
@log_lines = @lo_data
@lo_data = []
end
end
def after_each_event
nil
end
def first_time_log_check(ds, event)
nil
end
def register_first_res(msgid, res)
return if res.nil?
@mutex_first_res.synchronize do
if @first_res_list[msgid].nil?
@first_res_list[msgid] = res
end
end
end
def generate_context(event)
context = OutvokeProcExecContext.new(@outvoke, self, event)
context.extend(Module.new do
def res(hook_result)
@ds.register_first_res(@event.msgid, hook_result)
end
end)
end
end
StructDSVrchatStatus = Struct.new(:now, :logfile, :file_size,
:last_joined_time, :elapsed, :count, :lineno)
StructDSVrchatEvent = Struct.new(:status, :msgid, :raw, :time, :type, :body, :m, :is_quiet_mode)
......@@ -829,6 +998,10 @@ if $0 == __FILE__
$outvoke.ds[_1] = OutvokeDataSourceEverySec.new($outvoke, _1)
end
'web-001'.then do
$outvoke.ds[_1] = OutvokeDataSourceWeb.new($outvoke, _1)
end
'vrchat-001'.then do
vrchat_log_dir = "#{Dir.home}/.steam/debian-installation/steamapps/compatdata/438100/pfx/drive_c/users/steamuser/AppData/LocalLow/VRChat/VRChat"
$outvoke.ds[_1] = OutvokeDataSourceVrchat.new($outvoke, _1)
......@@ -860,6 +1033,13 @@ if $0 == __FILE__
end
end
'web-001'.then do
if $outvoke[_1].enabled?
log_puts "# =========================== websrv start ==========================="
$outvoke[_1].websrv_start
end
end
log_puts '# ----'
log_puts ''
......
# for Outvoke 0.1 (version 0.0.99.20241127 or later)
# written by cleemy desu wayo / Licensed under CC0 1.0
# initial release of this sample: 2024-11-27
# --------
#
# a sample of data source "web-001"
#
using OutvokeDSL
$outvoke.wait = 0.1
#
# a tiny example
# try $ wget http://localhost:8080/test1 -q -S -O -
#
hook "web-001", /^\/test1$/ do
"hello this is test1"
end
#
# e.res is an WEBrick::HTTPResponse object
# try $ wget http://localhost:8080/test2 -q -S -O -
#
hook "web-001", /^\/test2$/ do |e|
e.res["Content-Type"] = "text/html; charset=UTF-8"
e.res.body = "hello this is test2\n"
e.res
end
#
# 307 Temporary Redirect
# try $ wget http://localhost:8080/test3 -q -S -O -
#
hook "web-001", /^\/test3$/ do |e|
begin
e.res.status = 307
e.res.set_redirect WEBrick::HTTPStatus::TemporaryRedirect, "/test2"
rescue => err
puts "err: #{err}"
end
e.res
end
# for Outvoke 0.1 (version 0.0.99.20241127 or later)
# written by cleemy desu wayo / Licensed under CC0 1.0
# initial release of this sample: 2024-11-27
# --------
#
# a sample of data source "web-001"
#
using OutvokeDSL
$outvoke.wait = 0.1
#
# show request headers 1
# try $ wget http://localhost:8080/test1 -q -S -O -
#
hook "web-001", /^\/test1$/ do |e|
JSON.pretty_generate(e.req.header)
end
#
# show request headers 2
# try $ wget http://localhost:8080/test2 -q -S -O -
#
hook "web-001", /^\/test2$/ do |e|
e.req.header.to_json
end
#
# show request headers 3
# try $ wget http://localhost:8080/test3 -q -S -O -
#
hook "web-001", /^\/test3$/ do |e|
e.req.header.to_yaml
end
#
# treating request parameters 1
# try $ wget "http://localhost:8080/test4?num=100&name=john" -q -S -O -
#
hook "web-001", /^\/test4$/ do |e|
JSON.pretty_generate(e.get)
end
#
# treating request parameters 2
# try $ wget "http://localhost:8080/test5?num=200" -q -S -O -
#
hook "web-001", /^\/test5$/ do |e|
if e.get["num"].to_i > 100
"ok"
else
"under 100"
end
end
#
# treating request parameters 3
# try $ wget "http://localhost:8080/test6?num=200" -q -S -O -
#
# if i is 100 or less, it will return 500 Internal Server Error
#
hook "web-001", ->(e) { e.body == "/test6" && e.get["num"].to_i > 100 } do
"ok!"
end
# for Outvoke 0.1 (version 0.0.99.20241127 or later)
# written by cleemy desu wayo / Licensed under CC0 1.0
# initial release of this sample: 2024-11-27
# --------
#
# a sample of data source "web-001"
#
using OutvokeDSL
$outvoke.wait = 0.1
#
# try $ wget http://localhost:8080/test1 -q -S -O -
#
hookcc "web-001", /^\/test1$/ do
loputs "hookcc start -- (sleep 4)"
sleep 4
res "sleep 4 -- #{Time.now}" # this value probably will be ignored
loputs "hookcc end -- (sleep 4)"
end
hookcc "web-001", /^\/test1$/ do
loputs "hookcc start -- (sleep 2)"
sleep 2
res "sleep 2 -- #{Time.now}"
loputs "hookcc end -- (sleep 2)"
end
#
# try $ wget http://localhost:8080/test2 -q -S -O -
#
hookcc "web-001", /^\/test2$/ do |e|
loputs "hookcc start -- (/test2)"
sleep 2
e.res["Content-Type"] = "text/html; charset=UTF-8"
e.res.body = "hello hookcc test2\n"
res e.res
loputs "hookcc end -- (/test2)"
end
hooklo
# for Outvoke 0.1 (version 0.0.99.20241127 or later)
# written by cleemy desu wayo / Licensed under CC0 1.0
# initial release of this sample: 2024-11-27
# --------
#
# a sample of data source "web-001"
#
# in this example, there may not be much point in using Outvoke.
#
using OutvokeDSL
#
# try visiting http://localhost:8081 in your browser
#
$outvoke["web-001"].then do
_1.port = 8081
_1.document_root = "./"
_1.mount_proc_dir = nil
_1.enabled = true
end
# for Outvoke 0.1 (version 0.0.99.20241127 or later)
# written by cleemy desu wayo / Licensed under CC0 1.0
# initial release of this sample: 2024-11-27
# --------
#
# a sample of data source "web-001"
#
# in this example, static page and dynamic page are mixed.
#
using OutvokeDSL
$outvoke.wait = 0.1
$outvoke["web-001"].then do
_1.port = 8081
_1.document_root = "./"
_1.mount_proc_dir = "/dynamic"
_1.enabled = true
end
#
# try $ wget "http://localhost:8081/dynamic?num=55" -q -S -O -
#
hookweb do |e|
e.get["num"].to_i * 2
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment