lib/zold/node/front.rb in zold-0.16.2 vs lib/zold/node/front.rb in zold-0.16.3
- old
+ new
@@ -20,13 +20,14 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
STDOUT.sync = true
+require 'eventmachine'
+require 'thin'
require 'json'
require 'sinatra/base'
-require 'webrick'
require 'cachy'
require 'moneta'
require 'get_process_mem'
require 'diffy'
require 'usagewatch_ext'
@@ -54,11 +55,11 @@
set :bind, '0.0.0.0'
set :suppress_messages, true
set :start, Time.now
set :lock, false
set :show_exceptions, false
- set :server, :puma
+ set :server, :thin
set :log, nil? # to be injected at node.rb
set :trace, nil? # to be injected at node.rb
set :halt, '' # to be injected at node.rb
set :dump_errors, false # to be injected at node.rb
set :version, VERSION # to be injected at node.rb
@@ -80,23 +81,24 @@
set :node_alias, nil? # to be injected at node.rb
end
use Rack::Deflater
before do
+ @start = Time.now
if !settings.halt.empty? && params[:halt] && params[:halt] == settings.halt
settings.log.error('Halt signal received, shutting the front end down...')
Front.stop!
end
check_header(Http::NETWORK_HEADER) do |header|
if header != settings.network
- raise "Network name mismatch at #{request.url}, #{request.ip} is in '#{header}', \
-while #{settings.address} is in '#{settings.network}'"
+ error(400, "Network name mismatch at #{request.url}, #{request.ip} is in '#{header}', \
+while #{settings.address} is in '#{settings.network}'")
end
end
check_header(Http::PROTOCOL_HEADER) do |header|
if header != settings.protocol.to_s
- raise "Protocol mismatch, you are in '#{header}', we are in '#{settings.protocol}'"
+ error(400, "Protocol mismatch, you are in '#{header}', we are in '#{settings.protocol}'")
end
end
check_header(Http::SCORE_HEADER) do |header|
if settings.remotes.all.empty?
settings.log.debug("#{request.url}: we are in standalone mode, won't update remotes")
@@ -107,55 +109,61 @@
if settings.address == "#{s.host}:#{s.port}" && !settings.ignore_score_weakness
error(400, 'Self-requests are prohibited')
end
require_relative '../commands/remote'
cmd = Remote.new(remotes: settings.remotes, log: settings.log)
- cmd.run(['remote', 'add', s.host, s.port.to_s, "--network=#{settings.network}"])
+ begin
+ cmd.run(['remote', 'add', s.host, s.port.to_s, "--network=#{settings.network}"])
+ rescue StandardError => e
+ error(400, e.message)
+ end
end
- @start = Time.now
end
# @todo #357:30min Test that the headers are being set correctly.
# Currently there are no tests at all that would verify the headers.
after do
headers['Cache-Control'] = 'no-cache'
headers['X-Zold-Version'] = settings.version
headers[Http::PROTOCOL_HEADER] = settings.protocol.to_s
headers['Access-Control-Allow-Origin'] = '*'
headers[Http::SCORE_HEADER] = score.reduced(16).to_s
- headers['X-Zold-Thread'] = Thread.current.name.to_s
- headers['X-Zold-Milliseconds'] = ((Time.now - @start) * 1000).round.to_s
+ headers['X-Zold-Thread'] = Thread.current.object_id.to_s
+ unless @start.nil?
+ settings.log.info("Slow response to #{request.url} in #{Age.new(@start, limit: 1)}") if Time.now - @start > 1
+ headers['X-Zold-Milliseconds'] = ((Time.now - @start) * 1000).round.to_s
+ end
end
get '/robots.txt' do
- content_type 'text/plain'
+ content_type('text/plain')
'User-agent: *'
end
get '/version' do
- content_type 'text/plain'
+ content_type('text/plain')
settings.version
end
get '/pid' do
- content_type 'text/plain'
+ content_type('text/plain')
Process.pid.to_s
end
get '/score' do
- content_type 'text/plain'
+ content_type('text/plain')
score.to_s
end
get '/trace' do
- content_type 'text/plain'
+ content_type('text/plain')
settings.trace.to_s
end
get '/nohup_log' do
raise 'Run it with --nohup in order to see this log' if settings.nohup_log.nil?
- raise "Log not found at #{settings.nohup_log}" unless File.exist?(settings.nohup_log)
+ error(400, "Log not found at #{settings.nohup_log}") unless File.exist?(settings.nohup_log)
response.headers['Content-Type'] = 'text/plain'
response.headers['Content-Disposition'] = "attachment; filename='#{File.basename(settings.nohup_log)}'"
IO.read(settings.nohup_log)
end
@@ -168,11 +176,11 @@
redirect 'https://www.zold.io/images/logo-red.png'
end
end
get '/' do
- content_type 'application/json'
+ content_type('application/json')
JSON.pretty_generate(
version: settings.version,
alias: settings.node_alias,
network: settings.network,
protocol: settings.protocol,
@@ -193,22 +201,21 @@
home: 'https://www.zold.io'
)
end
get %r{/wallet/(?<id>[A-Fa-f0-9]{16})} do
- error 404 if settings.disable_fetch
+ error(404, 'FETCH is disabled with --disable-fetch') if settings.disable_fetch
id = Id.new(params[:id])
copy_of(id) do |wallet|
- error 404 unless wallet.exists?
- content_type 'application/json'
+ content_type('application/json')
JSON.pretty_generate(
version: settings.version,
alias: settings.node_alias,
protocol: settings.protocol,
id: wallet.id.to_s,
score: score.to_h,
- wallets: settings.wallets.all.count,
+ wallets: Cachy.cache(:a_wallets, expires_in: 5 * 60) { settings.wallets.all.count },
mtime: wallet.mtime.utc.iso8601,
size: File.size(wallet.path),
digest: wallet.digest,
copies: Copies.new(File.join(settings.copies, id)).all.count,
balance: wallet.balance.to_i,
@@ -216,15 +223,14 @@
)
end
end
get %r{/wallet/(?<id>[A-Fa-f0-9]{16}).json} do
- error 404 if settings.disable_fetch
+ error(404, 'FETCH is disabled with --disable-fetch') if settings.disable_fetch
id = Id.new(params[:id])
copy_of(id) do |wallet|
- error 404 unless wallet.exists?
- content_type 'application/json'
+ content_type('application/json')
JSON.pretty_generate(
version: settings.version,
alias: settings.node_alias,
protocol: settings.protocol,
id: wallet.id.to_s,
@@ -238,54 +244,49 @@
)
end
end
get %r{/wallet/(?<id>[A-Fa-f0-9]{16})/balance} do
- error 404 if settings.disable_fetch
+ error(404, 'FETCH is disabled with --disable-fetch') if settings.disable_fetch
id = Id.new(params[:id])
copy_of(id) do |wallet|
- error 404 unless wallet.exists?
content_type 'text/plain'
wallet.balance.to_i.to_s
end
end
get %r{/wallet/(?<id>[A-Fa-f0-9]{16})/key} do
- error 404 if settings.disable_fetch
+ error(404, 'FETCH is disabled with --disable-fetch') if settings.disable_fetch
id = Id.new(params[:id])
copy_of(id) do |wallet|
- error 404 unless wallet.exists?
content_type 'text/plain'
wallet.key.to_pub
end
end
get %r{/wallet/(?<id>[A-Fa-f0-9]{16})/mtime} do
- error 404 if settings.disable_fetch
+ error(404, 'FETCH is disabled with --disable-fetch') if settings.disable_fetch
id = Id.new(params[:id])
copy_of(id) do |wallet|
- error 404 unless wallet.exists?
content_type 'text/plain'
wallet.mtime.utc.iso8601.to_s
end
end
get %r{/wallet/(?<id>[A-Fa-f0-9]{16})/digest} do
- error 404 if settings.disable_fetch
+ error(404, 'FETCH is disabled with --disable-fetch') if settings.disable_fetch
id = Id.new(params[:id])
copy_of(id) do |wallet|
- error 404 unless wallet.exists?
content_type 'text/plain'
wallet.digest
end
end
get %r{/wallet/(?<id>[A-Fa-f0-9]{16})\.txt} do
- error 404 if settings.disable_fetch
+ error(404, 'FETCH is disabled with --disable-fetch') if settings.disable_fetch
id = Id.new(params[:id])
copy_of(id) do |wallet|
- error 404 unless wallet.exists?
content_type 'text/plain'
[
wallet.network,
wallet.protocol,
wallet.id.to_s,
@@ -302,24 +303,22 @@
].join("\n")
end
end
get %r{/wallet/(?<id>[A-Fa-f0-9]{16})\.bin} do
- error 404 if settings.disable_fetch
+ error(404, 'FETCH is disabled with --disable-fetch') if settings.disable_fetch
id = Id.new(params[:id])
copy_of(id) do |wallet|
- error 404 unless wallet.exists?
content_type 'text/plain'
IO.read(wallet.path)
end
end
get %r{/wallet/(?<id>[A-Fa-f0-9]{16})/copies} do
- error 404 if settings.disable_fetch
+ error(404, 'FETCH is disabled with --disable-fetch') if settings.disable_fetch
id = Id.new(params[:id])
- copy_of(id) do |wallet|
- error 404 unless wallet.exists?
+ copy_of(id) do
content_type 'text/plain'
copies = Copies.new(File.join(settings.copies, id))
copies.load.map do |c|
"#{c[:name]}: #{c[:host]}:#{c[:port]} #{c[:score]} #{c[:time].utc.iso8601}"
end.join("\n") +
@@ -331,28 +330,27 @@
end.join("\n")
end
end
get %r{/wallet/(?<id>[A-Fa-f0-9]{16})/copy/(?<name>[0-9]+)} do
- error 404 if settings.disable_fetch
+ error(404, 'FETCH is disabled with --disable-fetch') if settings.disable_fetch
id = Id.new(params[:id])
name = params[:name]
- copy_of(id) do |wallet|
- error 404 unless wallet.exists?
+ copy_of(id) do
copy = Copies.new(File.join(settings.copies, id)).all.find { |c| c[:name] == name }
error 404 if copy.nil?
content_type 'text/plain'
IO.read(copy[:path])
end
end
put %r{/wallet/(?<id>[A-Fa-f0-9]{16})/?} do
- error 404 if settings.disable_push
+ error(404, 'PUSH is disabled with --disable-push') if settings.disable_fetch
request.body.rewind
modified = settings.entrance.push(Id.new(params[:id]), request.body.read.to_s)
if modified.empty?
- status 304
+ status(304)
return
end
JSON.pretty_generate(
version: settings.version,
alias: settings.node_alias,
@@ -360,32 +358,32 @@
wallets: settings.wallets.all.count
)
end
get '/remotes' do
- content_type 'application/json'
+ content_type('application/json')
JSON.pretty_generate(
version: settings.version,
alias: settings.node_alias,
score: score.to_h,
all: settings.remotes.all,
mtime: settings.remotes.mtime.utc.iso8601
)
end
get '/farm' do
- content_type 'text/plain'
+ content_type('text/plain')
settings.farm.to_text
end
get '/metronome' do
- content_type 'text/plain'
+ content_type('text/plain')
settings.metronome.to_text
end
get '/threads' do
- content_type 'text/plain'
+ content_type('text/plain')
[
"Total threads: #{Thread.list.count}",
Thread.list.map do |t|
[
"#{t.name}: status=#{t.status}; alive=#{t.alive?}",
@@ -394,26 +392,28 @@
end
].flatten.join("\n\n")
end
not_found do
- status 404
- content_type 'text/plain'
+ status(404)
+ content_type('text/plain')
"Page not found: #{request.url}"
end
error 400 do
- status 400
- content_type 'text/plain'
+ status(400)
+ content_type('text/plain')
env['sinatra.error'] ? env['sinatra.error'].message : 'Invalid request'
end
error do
status 503
e = env['sinatra.error']
content_type 'text/plain'
headers['X-Zold-Error'] = e.message
+ headers['X-Zold-Path'] = request.url
+ settings.log.error(Backtrace.new(e).to_s)
Backtrace.new(e).to_s
end
private
@@ -431,14 +431,13 @@
end
def copy_of(id)
Tempfile.open([id.to_s, Wallet::EXT]) do |f|
settings.wallets.find(id) do |wallet|
- IO.write(f, IO.read(wallet.path)) if File.exist?(wallet.path)
+ error(404, "Wallet ##{id} doesn't exist on the node") unless wallet.exists?
+ IO.write(f, IO.read(wallet.path))
end
- path = f.path
- f.delete if File.size(f.path).zero?
- yield Wallet.new(path)
+ yield Wallet.new(f.path)
end
end
end
end