migrate to athena for web routing
This commit is contained in:
parent
7e2dbd2917
commit
543a959829
|
@ -1,5 +1,9 @@
|
|||
version: 2.0
|
||||
shards:
|
||||
athena-routing:
|
||||
git: https://github.com/athena-framework/routing.git
|
||||
version: 0.1.6
|
||||
|
||||
db:
|
||||
git: https://github.com/crystal-lang/crystal-db.git
|
||||
version: 0.11.0
|
||||
|
|
|
@ -23,6 +23,9 @@ dependencies:
|
|||
branch: master
|
||||
http-session:
|
||||
github: straight-shoota/http-session
|
||||
athena-routing:
|
||||
github: athena-framework/routing
|
||||
version: ~> 0.1.0
|
||||
|
||||
crystal: 1.6.2
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ require "colorize"
|
|||
require "option_parser"
|
||||
require "migrate"
|
||||
|
||||
require "./server"
|
||||
require "./enums"
|
||||
require "./lib/hash"
|
||||
require "./lib/format"
|
||||
|
@ -64,7 +65,10 @@ module CrystalGauntlet
|
|||
DATA_FOLDER = Path.new("data")
|
||||
|
||||
@@endpoints = Hash(String, (HTTP::Server::Context -> String)).new
|
||||
@@template_endpoints = Hash(String, (HTTP::Server::Context -> Nil)).new
|
||||
@@template_endpoints = Hash(
|
||||
NamedTuple(name: String, path: String, methods: Enumerable(String)),
|
||||
Proc(HTTP::Server::Context, Hash(String, String?), Nil)
|
||||
).new
|
||||
|
||||
@@up_at = nil
|
||||
|
||||
|
@ -132,90 +136,6 @@ module CrystalGauntlet
|
|||
end
|
||||
end
|
||||
|
||||
class GDHandler
|
||||
include HTTP::Handler
|
||||
|
||||
def call(context : HTTP::Server::Context)
|
||||
# expunge trailing slashes
|
||||
path = context.request.path.chomp("/")
|
||||
|
||||
path = path.sub(config_get("general.append_path").as(String | Nil) || "", "")
|
||||
|
||||
body = context.request.body
|
||||
|
||||
if CrystalGauntlet.endpoints.has_key?(path) && context.request.method == "POST" && body
|
||||
func = CrystalGauntlet.endpoints[path]
|
||||
begin
|
||||
value = func.call(context)
|
||||
rescue err
|
||||
LOG.error { "error while handling #{path.colorize(:white)}:" }
|
||||
LOG.error { err.to_s }
|
||||
is_relevant = true
|
||||
err.backtrace.each do |str|
|
||||
# this is a hack. Oh well
|
||||
if str.starts_with?("src/crystal-gauntlet.cr") || (!is_relevant)
|
||||
is_relevant = false
|
||||
else
|
||||
LOG.error {" #{str}"}
|
||||
end
|
||||
end
|
||||
context.response.content_type = "text/plain"
|
||||
context.response.respond_with_status(500, "-1")
|
||||
else
|
||||
max_size = 2048
|
||||
|
||||
value_displayed = value
|
||||
if value.size > max_size
|
||||
value_displayed = value[0..max_size] + ("…".colorize(:dark_gray).to_s)
|
||||
end
|
||||
LOG.debug { "-> ".colorize(:green).to_s + value_displayed }
|
||||
|
||||
context.response.content_type = "text/plain"
|
||||
# to let endpoints manually write to IO
|
||||
if value != ""
|
||||
context.response.print value
|
||||
end
|
||||
end
|
||||
else
|
||||
call_next(context)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class TemplateHandler
|
||||
include HTTP::Handler
|
||||
|
||||
def call(context : HTTP::Server::Context)
|
||||
# expunge trailing slashes
|
||||
path = context.request.path.chomp("/")
|
||||
|
||||
body = context.request.body
|
||||
|
||||
if CrystalGauntlet.template_endpoints.has_key?(path)
|
||||
func = CrystalGauntlet.template_endpoints[path]
|
||||
begin
|
||||
func.call(context)
|
||||
rescue err
|
||||
LOG.error { "error while handling #{path.colorize(:white)}:" }
|
||||
LOG.error { err.to_s }
|
||||
is_relevant = true
|
||||
err.backtrace.each do |str|
|
||||
# this is a hack. Oh well
|
||||
if str.starts_with?("src/crystal-gauntlet.cr") || (!is_relevant)
|
||||
is_relevant = false
|
||||
else
|
||||
LOG.error {" #{str}"}
|
||||
end
|
||||
end
|
||||
context.response.content_type = "text/html"
|
||||
context.response.respond_with_status(500, "Internal server error occurred, sorry about that")
|
||||
end
|
||||
else
|
||||
call_next(context)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.run()
|
||||
Log.setup_from_env(backend: Log::IOBackend.new(formatter: CrystalGauntletFormat))
|
||||
|
||||
|
@ -294,31 +214,7 @@ module CrystalGauntlet
|
|||
Dir.mkdir_p(DATA_FOLDER / v)
|
||||
}
|
||||
|
||||
server = HTTP::Server.new([
|
||||
HTTP::LogHandler.new,
|
||||
HTTP::StaticFileHandler.new("public/", fallthrough: true, directory_listing: false),
|
||||
HTTP::StaticFileHandler.new((DATA_FOLDER / "songs").to_s, fallthrough: true, directory_listing: false),
|
||||
CrystalGauntlet::GDHandler.new,
|
||||
CrystalGauntlet::TemplateHandler.new
|
||||
])
|
||||
|
||||
listen_on = URI.parse(ENV["LISTEN_ON"]? || "http://localhost:8080").normalize
|
||||
|
||||
case listen_on.scheme
|
||||
when "http"
|
||||
server.bind_tcp(listen_on.hostname.not_nil!, listen_on.port.not_nil!)
|
||||
when "unix"
|
||||
server.bind_unix(listen_on.to_s.sub("unix://",""))
|
||||
end
|
||||
|
||||
check_server_length(false)
|
||||
|
||||
Reupload.init()
|
||||
Ranks.init()
|
||||
|
||||
@@up_at = Time.utc
|
||||
LOG.notice { "Listening on #{listen_on.to_s.colorize(:white)}" }
|
||||
server.listen
|
||||
Server.run()
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
require "athena-routing"
|
||||
|
||||
module CrystalGauntlet::Server
|
||||
class GDHandler
|
||||
include HTTP::Handler
|
||||
|
||||
def call(context : HTTP::Server::Context)
|
||||
# expunge trailing slashes
|
||||
path = context.request.path.chomp("/")
|
||||
|
||||
path = path.sub(config_get("general.append_path").as(String | Nil) || "", "")
|
||||
|
||||
body = context.request.body
|
||||
|
||||
if CrystalGauntlet.endpoints.has_key?(path) && context.request.method == "POST" && body
|
||||
func = CrystalGauntlet.endpoints[path]
|
||||
begin
|
||||
value = func.call(context)
|
||||
rescue err
|
||||
LOG.error { "error while handling #{path.colorize(:white)}:" }
|
||||
LOG.error { err.to_s }
|
||||
is_relevant = true
|
||||
err.backtrace.each do |str|
|
||||
# this is a hack. Oh well
|
||||
if str.starts_with?("src/crystal-gauntlet.cr") || (!is_relevant)
|
||||
is_relevant = false
|
||||
else
|
||||
LOG.error {" #{str}"}
|
||||
end
|
||||
end
|
||||
context.response.content_type = "text/plain"
|
||||
context.response.respond_with_status(500, "-1")
|
||||
else
|
||||
max_size = 2048
|
||||
|
||||
value_displayed = value
|
||||
if value.size > max_size
|
||||
value_displayed = value[0..max_size] + ("…".colorize(:dark_gray).to_s)
|
||||
end
|
||||
LOG.debug { "-> ".colorize(:green).to_s + value_displayed }
|
||||
|
||||
context.response.content_type = "text/plain"
|
||||
# to let endpoints manually write to IO
|
||||
if value != ""
|
||||
context.response.print value
|
||||
end
|
||||
end
|
||||
else
|
||||
call_next(context)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.run()
|
||||
template_handler = ART::RoutingHandler.new
|
||||
|
||||
CrystalGauntlet.template_endpoints.each do |key, handler|
|
||||
template_handler.add(
|
||||
key[:name],
|
||||
ART::Route.new(
|
||||
key[:path],
|
||||
methods: key[:methods]
|
||||
)
|
||||
) { |ctx, params| handler.call(ctx, params) }
|
||||
end
|
||||
|
||||
server = HTTP::Server.new([
|
||||
HTTP::LogHandler.new,
|
||||
HTTP::StaticFileHandler.new("public/", fallthrough: true, directory_listing: false),
|
||||
HTTP::StaticFileHandler.new((DATA_FOLDER / "songs").to_s, fallthrough: true, directory_listing: false),
|
||||
GDHandler.new,
|
||||
template_handler.compile
|
||||
])
|
||||
|
||||
listen_on = URI.parse(ENV["LISTEN_ON"]? || "http://localhost:8080").normalize
|
||||
|
||||
case listen_on.scheme
|
||||
when "http"
|
||||
server.bind_tcp(listen_on.hostname.not_nil!, listen_on.port.not_nil!)
|
||||
when "unix"
|
||||
server.bind_unix(listen_on.to_s.sub("unix://",""))
|
||||
end
|
||||
|
||||
check_server_length(false)
|
||||
|
||||
Reupload.init()
|
||||
Ranks.init()
|
||||
|
||||
@@up_at = Time.utc
|
||||
LOG.notice { "Listening on #{listen_on.to_s.colorize(:white)}" }
|
||||
server.listen
|
||||
end
|
||||
end
|
|
@ -1,11 +1,19 @@
|
|||
include CrystalGauntlet
|
||||
|
||||
CrystalGauntlet.template_endpoints["/#{config_get("general.append_path").as(String | Nil) || ""}accounts/accountManagement.php"] = ->(context : HTTP::Server::Context) {
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "account_management_redirect",
|
||||
path: "/#{config_get("general.append_path").as(String | Nil) || ""}accounts/accountManagement.php",
|
||||
methods: ["get"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
context.response.headers.add("Location", "/accounts/")
|
||||
context.response.status = HTTP::Status::MOVED_PERMANENTLY
|
||||
}
|
||||
|
||||
CrystalGauntlet.template_endpoints["/accounts"] = ->(context : HTTP::Server::Context) {
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "account_management",
|
||||
path: "/accounts",
|
||||
methods: ["get"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
context.response.content_type = "text/html"
|
||||
|
||||
account_id = nil
|
||||
|
|
|
@ -2,7 +2,12 @@ require "uri"
|
|||
|
||||
include CrystalGauntlet
|
||||
|
||||
CrystalGauntlet.template_endpoints["/accounts/settings"] = ->(context : HTTP::Server::Context) {
|
||||
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "account_settings",
|
||||
path: "/accounts/settings",
|
||||
methods: ["get", "post"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
context.response.content_type = "text/html"
|
||||
|
||||
account_id = nil
|
||||
|
|
|
@ -3,7 +3,11 @@ require "compress/gzip"
|
|||
|
||||
include CrystalGauntlet
|
||||
|
||||
CrystalGauntlet.template_endpoints["/tools/create_session"] = ->(context : HTTP::Server::Context) {
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "create_session",
|
||||
path: "/tools/create_session",
|
||||
methods: ["get", "post"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
disabled = !config_get("sessions.allow").as(Bool | Nil)
|
||||
result = nil
|
||||
body = context.request.body
|
||||
|
|
|
@ -2,12 +2,21 @@ require "ecr"
|
|||
|
||||
include CrystalGauntlet
|
||||
|
||||
CrystalGauntlet.template_endpoints["/tools"] = ->(context : HTTP::Server::Context) {
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "tools_redirect",
|
||||
path: "/tools",
|
||||
methods: ["get"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
context.response.headers.add("Location", "/")
|
||||
context.response.status = HTTP::Status::TEMPORARY_REDIRECT
|
||||
}
|
||||
|
||||
CrystalGauntlet.template_endpoints[""] = ->(context : HTTP::Server::Context) {
|
||||
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "index",
|
||||
path: "/",
|
||||
methods: ["get"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
context.response.content_type = "text/html"
|
||||
ECR.embed("./public/template/index.ecr", context.response)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,11 @@ include CrystalGauntlet
|
|||
|
||||
levels_per_page = 10
|
||||
|
||||
CrystalGauntlet.template_endpoints["/tools/levels"] = ->(context : HTTP::Server::Context) {
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "list_levels",
|
||||
path: "/tools/levels",
|
||||
methods: ["get"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
context.response.content_type = "text/html"
|
||||
page = (context.request.query_params["page"]? || "0").to_i? || 0
|
||||
total_levels = DATABASE.scalar("select count(*) from levels").as(Int64)
|
||||
|
|
|
@ -3,7 +3,11 @@ require "http-session"
|
|||
|
||||
include CrystalGauntlet
|
||||
|
||||
CrystalGauntlet.template_endpoints["/login"] = ->(context : HTTP::Server::Context) {
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "login",
|
||||
path: "/login",
|
||||
methods: ["get", "post"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
if session = CrystalGauntlet.sessions.get(context)
|
||||
logged_in = true
|
||||
account_id = session.account_id
|
||||
|
|
|
@ -3,12 +3,11 @@ require "http-session"
|
|||
|
||||
include CrystalGauntlet
|
||||
|
||||
CrystalGauntlet.template_endpoints["/accounts/logout"] = ->(context : HTTP::Server::Context) {
|
||||
if context.request.method != "POST"
|
||||
context.response.respond_with_status 405
|
||||
return
|
||||
end
|
||||
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "logout",
|
||||
path: "/accounts/logout",
|
||||
methods: ["post"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
CrystalGauntlet.sessions.delete(context)
|
||||
|
||||
context.response.headers.add("Location", "/")
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
include CrystalGauntlet
|
||||
|
||||
CrystalGauntlet.template_endpoints["/accounts/notifications"] = ->(context : HTTP::Server::Context) {
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "account_notifications",
|
||||
path: "/accounts/notifications",
|
||||
methods: ["get"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
context.response.content_type = "text/html"
|
||||
|
||||
account_id = nil
|
||||
|
|
|
@ -3,7 +3,11 @@ require "xml"
|
|||
|
||||
include CrystalGauntlet
|
||||
|
||||
CrystalGauntlet.template_endpoints["/tools/reupload"] = ->(context : HTTP::Server::Context) {
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "reupload",
|
||||
path: "/tools/reupload",
|
||||
methods: ["get", "post"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
context.response.content_type = "text/html"
|
||||
|
||||
disabled = !(config_get("reuploads.allowed").as?(Bool))
|
||||
|
|
|
@ -2,7 +2,11 @@ require "ecr"
|
|||
|
||||
include CrystalGauntlet
|
||||
|
||||
CrystalGauntlet.template_endpoints["/tools/song_search"] = ->(context : HTTP::Server::Context) {
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "song_search",
|
||||
path: "/tools/song_search",
|
||||
methods: ["get", "post"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
context.response.content_type = "text/html"
|
||||
|
||||
error = nil
|
||||
|
|
|
@ -17,7 +17,11 @@ def get_next_song_id() : Int32
|
|||
end
|
||||
end
|
||||
|
||||
CrystalGauntlet.template_endpoints["/tools/song_upload"] = ->(context : HTTP::Server::Context) {
|
||||
CrystalGauntlet.template_endpoints[{
|
||||
name: "song_upload",
|
||||
path: "/tools/song_upload",
|
||||
methods: ["get", "post"]
|
||||
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
|
||||
context.response.content_type = "text/html"
|
||||
|
||||
disabled = !(config_get("songs.allow_custom_songs").as?(Bool))
|
||||
|
|
Loading…
Reference in New Issue