From 006bc8235e57f04980e2f641fb2ddd91e0d57499 Mon Sep 17 00:00:00 2001 From: Nguyễn Gia Phong Date: Sat, 4 Mar 2023 19:58:06 +0900 Subject: Parse CLI arguments --- src/http.cr | 157 +++++++++++++++++++++++++++++------------------------------- 1 file changed, 76 insertions(+), 81 deletions(-) (limited to 'src/http.cr') diff --git a/src/http.cr b/src/http.cr index 63eee07..1179f73 100644 --- a/src/http.cr +++ b/src/http.cr @@ -33,96 +33,91 @@ def http_error(context, status, message = nil) context.response.respond_with_status status, message end -if ARGV.empty? - puts "usage: #{Path[PROGRAM_NAME].basename} config.ini" - exit 1 -end -cfg = INI.parse File.read ARGV[0] -opennic_host = URI.parse(cfg["opennic"]["remote"]).host +class Server + def initialize(cfg) + @opennic_host = URI.parse(cfg.opennic_remote).host + @db = Database.new cfg.db, cfg.opennic_remote, cfg.icann_remote + @opennic_page = Page.new cfg.opennic_local, cfg.opennic_remote, + cfg.api, @db + @opennic_page.write + @icann_page = Page.new cfg.icann_local, cfg.icann_remote, + cfg.api, @db + @icann_page.write -Dir.mkdir_p Path[cfg["general"]["db"]].parent -db = Database.new cfg["general"]["db"], - cfg["opennic"]["remote"], cfg["icann"]["remote"] + @server = HTTP::Server.new do |context| + # Manually crafted request + next http_error context, 405 if context.request.method != "POST" + content_length = context.request.content_length + next http_error context, 411 unless content_length + next http_error context, 413 if content_length > MAX_CONTENT_LENGTH -opennic_page = Page.new cfg["opennic"]["local"], cfg["opennic"]["remote"], - cfg["general"]["api"], db -opennic_page.write -icann_page = Page.new cfg["icann"]["local"], cfg["icann"]["remote"], - cfg["general"]["api"], db -icann_page.write + errors = {} of String => String + params = {} of String => String + invalid_param = false + body = context.request.body.try &.gets_to_end || "" + URI::Params.parse body do |key, value| + params[key] = value + case key + when "nick" + if value.size > MAX_NICK_LENGTH + next errors["nick"] = "Must be within ${MAX_NICK_LENGTH} characters" + end + if /^[0-9a-z]+$/ !~ value + next errors["nick"] = "Must be ASCII lowercase alphanumeric" + end + when "opennic" + uri = URI.parse value + next errors["opennic"] = "Must be absolute URL" unless uri.absolute? + if uri.scheme != "http" && uri.scheme != "https" + next errors["opennic"] = "Must be HTTP/S" + end + host = uri.host + unless OPENNIC_TLD.includes? Path[host].extension + next errors["opennic"] = "Must be under OpenNIC domain" + end if host + when "icann" + uri = URI.parse value + next errors["icann"] = "Must be absolute URL" unless uri.absolute? + next errors["icann"] = "Must be HTTPS" unless uri.scheme == "https" + host = uri.host # impractical to check for ICANN TLD + if OPENNIC_TLD.includes? Path[host].extension + next errors["icann"] = "Must not be under OpenNIC domain" + end if host + when "host" + else + break invalid_param = true + end + end -server = HTTP::Server.new do |context| - # Manually crafted request - next http_error context, 405 if context.request.method != "POST" - content_length = context.request.content_length - next http_error context, 411 unless content_length - next http_error context, 413 if content_length > MAX_CONTENT_LENGTH + # Manually crafted request + next http_error context, 400, "Invalid Parameter" if invalid_param + next http_error context, 400, "Missing Parameter" unless params.size == 4 - errors = {} of String => String - params = {} of String => String - invalid_param = false - body = context.request.body.try &.gets_to_end || "" - URI::Params.parse body do |key, value| - params[key] = value - case key - when "nick" - if value.size > MAX_NICK_LENGTH - next errors["nick"] = "Must be within ${MAX_NICK_LENGTH} characters" + others = @db.members.each_value.chain @db.applicants.each_value + others.each do |nick, opennic, icann| + errors["nick"] = "Must be unique" if nick == params["nick"] + errors["opennic"] = "Must be unique" if opennic == params["opennic"] + errors["icann"] = "Must be unique" if icann == params["icann"] end - if /^[0-9a-z]+$/ !~ value - next errors["nick"] = "Must be ASCII lowercase alphanumeric" + + if errors.empty? + @db.add_applicant params["nick"], params["opennic"], params["icann"] + # TODO: write feed + else + context.response.status_code = 400 unless errors.empty? end - when "opennic" - uri = URI.parse value - next errors["opennic"] = "Must be absolute URL" unless uri.absolute? - if uri.scheme != "http" && uri.scheme != "https" - next errors["opennic"] = "Must be HTTP/S" + context.response.content_type = "application/xhtml+xml" + if params["host"] == @opennic_host + context.response.print @opennic_page.build errors, params + else + context.response.print @icann_page.build errors, params end - host = uri.host - unless OPENNIC_TLD.includes? Path[host].extension - next errors["opennic"] = "Must be under OpenNIC domain" - end if host - when "icann" - uri = URI.parse value - next errors["icann"] = "Must be absolute URL" unless uri.absolute? - next errors["icann"] = "Must be HTTPS" unless uri.scheme == "https" - host = uri.host # impractical to check for ICANN TLD - if OPENNIC_TLD.includes? Path[host].extension - next errors["icann"] = "Must not be under OpenNIC domain" - end if host - when "host" - else - break invalid_param = true + # TODO: schedule dynamic check end end - # Manually crafted request - next http_error context, 400, "Invalid Parameter" if invalid_param - next http_error context, 400, "Missing Parameter" unless params.size == 4 - - others = db.members.each_value.chain db.applicants.each_value - others.each do |nick, opennic, icann| - errors["nick"] = "Must be unique" if nick == params["nick"] - errors["opennic"] = "Must be unique" if opennic == params["opennic"] - errors["icann"] = "Must be unique" if icann == params["icann"] - end - - if errors.empty? - db.add_applicant params["nick"], params["opennic"], params["icann"] - # TODO: write feed - else - context.response.status_code = 400 unless errors.empty? + def listen(port) + puts "Listening on http://#{@server.bind_tcp port}" + @server.listen end - context.response.content_type = "application/xhtml+xml" - if params["host"] == opennic_host - context.response.print opennic_page.build errors, params - else - context.response.print icann_page.build errors, params - end - # TODO: schedule dynamic check end - -# TODO: support Unix socket -address = server.bind_tcp cfg["general"]["port"].to_i -puts "Listening on http://#{address}" -server.listen -- cgit 1.4.1