feat: configuration system

This commit is contained in:
Aymeric GUERACAGUE 2021-04-07 01:03:54 +02:00
parent e6f616148a
commit 399e5a6461
Signed by: Superkooka
GPG Key ID: F78F2B172E894865
6 changed files with 73 additions and 64 deletions

View File

@ -1,18 +1,22 @@
{ {
"notaname.home": { "hostname": "192.168.50.50",
"handler": "static_serve", "port": 80,
"vhosts": [
{
"server_name": "notaname.home",
"handler": "static_serve",
"document_root": "/var/www/notaname/home" "document_root": "/var/www/notaname/home"
}, },
{
"compteur.notaname.home": { "server_name": "compteur.notaname.home",
"handler": "internal.compter" "handler": "internal.compter"
}, },
{
"compteur.cheat.notaname.home": { "server_name": "compteur.cheat.notaname.home",
"handler": "proxy_pass", "handler": "proxy_pass",
"hostname": "127.0.0.1",
"host": "127.0.0.1", "port": 0
"port": 8080
} }
]
} }

23
src/configuration.cr Normal file
View File

@ -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

View File

@ -2,8 +2,5 @@ require "json"
require "../request" require "../request"
abstract class Handler abstract class Handler
def initialize(@configuration : JSON::Any)
end
abstract def handle(request : Request) : Response abstract def handle(request : Request) : Response
end end

View File

@ -2,12 +2,11 @@ require "./handler"
require "../response" require "../response"
class ProxyHandler < Handler 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 tcp_socket << request.to_s
return Response.new tcp_socket.receive[0] return Response.new tcp_socket.receive[0]
end end

View File

@ -1,11 +1,15 @@
require "./handler" require "./handler"
require "../../configuration"
class StaticHandler < Handler class StaticHandler < Handler
def initialize (@document_root : String); end
def handle(request : Request) : Response def handle(request : Request) : Response
file = @configuration["document_root"].to_s + request.uri file = @document_root + request.uri
if request.uri.ends_with? "/" if request.uri.ends_with? "/"
file = @configuration["document_root"].to_s + request.uri + "index.html" file = @document_root + request.uri + "index.html"
end end
if !File.exists?(file) if !File.exists?(file)

View File

@ -1,35 +1,36 @@
require "socket"
require "option_parser"
require "env"
require "json" require "json"
require "socket"
require "./configuration"
require "./http/request" require "./http/request"
require "./http/response" require "./http/response"
require "./http/handler/static_handler" require "./http/handler/static_handler"
require "./http/handler/proxy_handler" require "./http/handler/proxy_handler"
require "./http/handler/compter_handler" require "./http/handler/compter_handler"
def handle_request(client, vhosts)
def handle_request(client)
request = Request.new(client) 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 vhosts.each do |vhost|
configuration.each do |key, value| if request.header("Host") != vhost.server_name
if request.header("Host") != key
next next
end end
case value["handler"] case vhost.handler
when "proxy_pass" 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" 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" when "internal.compter"
handler = CompterHandler.new value handler = CompterHandler.new
else else
client << Response.new "HTTP", "1.0", HTTPStatus::BAD_GATEWAY client << Response.new "HTTP", "1.0", HTTPStatus::BAD_GATEWAY
break break
@ -40,30 +41,11 @@ def handle_request(client)
end end
end end
tcp_port = 8090 configuration_file = File.read("./config.json")
hostname = "127.0.0.1" configuration = Configuration.from_json configuration_file
OptionParser.parse do |parser| server = TCPServer.new(configuration.hostname, configuration.port)
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)
while client = server.accept? while client = server.accept?
spawn handle_request(client) spawn handle_request(client, configuration.vhosts)
end end