From 399e5a64612336f407a34e41a196ce16423fdf6f Mon Sep 17 00:00:00 2001 From: Superkooka Date: Wed, 7 Apr 2021 01:03:54 +0200 Subject: [PATCH] feat: configuration system --- config.json | 34 +++++++++-------- src/configuration.cr | 23 ++++++++++++ src/http/handler/handler.cr | 3 -- src/http/handler/proxy_handler.cr | 9 ++--- src/http/handler/static_handler.cr | 8 +++- src/main.cr | 60 +++++++++++------------------- 6 files changed, 73 insertions(+), 64 deletions(-) create mode 100644 src/configuration.cr diff --git a/config.json b/config.json index 291bcb3..344a684 100644 --- a/config.json +++ b/config.json @@ -1,18 +1,22 @@ { - "notaname.home": { - "handler": "static_serve", + "hostname": "192.168.50.50", + "port": 80, - "document_root": "/var/www/notaname/home" - }, - - "compteur.notaname.home": { - "handler": "internal.compter" - }, - - "compteur.cheat.notaname.home": { - "handler": "proxy_pass", - - "host": "127.0.0.1", - "port": 8080 - } + "vhosts": [ + { + "server_name": "notaname.home", + "handler": "static_serve", + "document_root": "/var/www/notaname/home" + }, + { + "server_name": "compteur.notaname.home", + "handler": "internal.compter" + }, + { + "server_name": "compteur.cheat.notaname.home", + "handler": "proxy_pass", + "hostname": "127.0.0.1", + "port": 0 + } + ] } diff --git a/src/configuration.cr b/src/configuration.cr new file mode 100644 index 0000000..d41e114 --- /dev/null +++ b/src/configuration.cr @@ -0,0 +1,23 @@ +require "json" + +class Configuration + include JSON::Serializable + + property hostname : String + property port : UInt32 + + property vhosts : Array(VHost) +end + +class VHost + include JSON::Serializable + + property handler : String + + property server_name : String? + + property hostname : String? + property port : UInt32? + + property document_root : String? +end diff --git a/src/http/handler/handler.cr b/src/http/handler/handler.cr index f267b56..c908488 100644 --- a/src/http/handler/handler.cr +++ b/src/http/handler/handler.cr @@ -2,8 +2,5 @@ require "json" require "../request" abstract class Handler - def initialize(@configuration : JSON::Any) - end - abstract def handle(request : Request) : Response end diff --git a/src/http/handler/proxy_handler.cr b/src/http/handler/proxy_handler.cr index 8f1e4d5..83228c3 100644 --- a/src/http/handler/proxy_handler.cr +++ b/src/http/handler/proxy_handler.cr @@ -2,12 +2,11 @@ require "./handler" require "../response" class ProxyHandler < Handler - def handle(request : Request) : Response - puts "ping" - host = @configuration["host"].to_s - port = @configuration["port"].to_s.to_i - return TCPSocket.open host, port do |tcp_socket| + def initialize (@host : String, @port : UInt32); end + + def handle(request : Request) : Response + return TCPSocket.open @host, @port do |tcp_socket| tcp_socket << request.to_s return Response.new tcp_socket.receive[0] end diff --git a/src/http/handler/static_handler.cr b/src/http/handler/static_handler.cr index 87a88e8..4168b62 100644 --- a/src/http/handler/static_handler.cr +++ b/src/http/handler/static_handler.cr @@ -1,11 +1,15 @@ require "./handler" +require "../../configuration" class StaticHandler < Handler + + def initialize (@document_root : String); end + def handle(request : Request) : Response - file = @configuration["document_root"].to_s + request.uri + file = @document_root + request.uri if request.uri.ends_with? "/" - file = @configuration["document_root"].to_s + request.uri + "index.html" + file = @document_root + request.uri + "index.html" end if !File.exists?(file) diff --git a/src/main.cr b/src/main.cr index 33e28cc..10ff420 100644 --- a/src/main.cr +++ b/src/main.cr @@ -1,35 +1,36 @@ -require "socket" -require "option_parser" -require "env" require "json" +require "socket" +require "./configuration" require "./http/request" require "./http/response" require "./http/handler/static_handler" require "./http/handler/proxy_handler" require "./http/handler/compter_handler" - -def handle_request(client) +def handle_request(client, vhosts) request = Request.new(client) - puts request - configuration_file = File.open("/home/kooka/config.json") do |file| - file.gets_to_end - end - configuration = Hash(String, JSON::Any).from_json configuration_file - configuration.each do |key, value| - if request.header("Host") != key + vhosts.each do |vhost| + if request.header("Host") != vhost.server_name next end - case value["handler"] + case vhost.handler when "proxy_pass" - handler = ProxyHandler.new value + if (hostname = vhost.hostname).nil? || (port = vhost.port).nil? + raise "hostname or port key should not be null" + end + + handler = ProxyHandler.new hostname, port when "static_serve" - handler = StaticHandler.new value + if (document_root = vhost.document_root).nil? + raise "document_root key should not be null" + end + + handler = StaticHandler.new document_root when "internal.compter" - handler = CompterHandler.new value + handler = CompterHandler.new else client << Response.new "HTTP", "1.0", HTTPStatus::BAD_GATEWAY break @@ -40,30 +41,11 @@ def handle_request(client) end end -tcp_port = 8090 -hostname = "127.0.0.1" +configuration_file = File.read("./config.json") +configuration = Configuration.from_json configuration_file -OptionParser.parse do |parser| - parser.banner = "Usage: webcrystal [arguments]" - parser.on("-p PORT", "--port=PORT", "Specify the port to listen, default to 8000") do |port| - tcp_port = port.to_u32 - end - parser.on("-n NAME", "--name NAME", "Hostname to listen, default to 127.0.0.1") do |name| - hostname = name - end - parser.on("-h", "--help", "Show this help") do - puts parser - exit - end - parser.invalid_option do |flag| - STDERR.puts "ERROR: #{flag} is not a valid option." - STDERR.puts parser - exit(1) - end -end - -server = TCPServer.new(hostname, tcp_port) +server = TCPServer.new(configuration.hostname, configuration.port) while client = server.accept? - spawn handle_request(client) + spawn handle_request(client, configuration.vhosts) end