import Pkg using Sockets using Logging # Ensure Logging is explicitly used # Ensure necessary packages are installed and loaded function ensure_package(pkg::String) try @eval using $(Symbol(pkg)) @debug "Balík $pkg už je nainštalovaný a načítaný." catch @info "Balík $pkg nie je nainštalovaný, inštalujem..." Pkg.add(pkg) @eval using $(Symbol(pkg)) @info "Balík $pkg úspešne nainštalovaný a načítaný." end end ensure_package("HTTP") ensure_package("Logging") # No need to call this again, it's already done by ensure_package # However, it's good practice to ensure it's loaded before its first use # Set up logging for better insights global_logger(ConsoleLogger(stderr, Logging.Info)) # Define the root directory for serving files const ROOT = @__DIR__ """ content_type(path::String) Determines the appropriate Content-Type header based on the file extension. """ function content_type(path::String) ext = lowercase(splitext(path)[2]) return if ext == ".html" "text/html; charset=utf-8" elseif ext == ".css" "text/css; charset=utf-8" elseif ext == ".js" "application/javascript; charset=utf-8" elseif ext == ".json" "application/json; charset=utf-8" elseif ext == ".ico" "image/x-icon" elseif ext == ".png" "image/png" elseif ext == ".jpg" || ext == ".jpeg" "image/jpeg" elseif ext == ".gif" "image/gif" elseif ext == ".svg" "image/svg+xml" else "text/plain; charset=utf-8" # Default for unknown types end end """ handler(req::HTTP.Request) Handles incoming HTTP requests, serving static files or returning 404. """ function handler(req::HTTP.Request) target_path = String(req.target) @info "Prijatá požiadavka: $(req.method) $target_path" # Handle favicon requests efficiently if target_path == "/favicon.ico" @debug "Obsluhujem favicon.ico s 204 No Content." return HTTP.Response(204) # No Content end # Map root path to index.html file_name = (target_path == "/" || isempty(target_path)) ? "index.html" : target_path[2:end] file_path = joinpath(ROOT, file_name) if isfile(file_path) try content = read(file_path) mime_type = content_type(file_path) hdrs = HTTP.Headers(["Content-Type" => mime_type]) @info "Súbor nájdený: $(file_path) (Typ: $(mime_type)), vrátený 200 OK." return HTTP.Response(200, hdrs, content) catch e @error "Chyba pri čítaní súboru $(file_path): $e" hdrs = HTTP.Headers(["Content-Type" => "text/plain; charset=utf-8"]) return HTTP.Response(500, hdrs, "Interná chyba servera pri čítaní súboru.") end else hdrs = HTTP.Headers(["Content-Type" => "text/plain; charset=utf-8"]) @warn "Súbor nenájdený: $(file_path), vrátený 404 Not Found." return HTTP.Response(404, hdrs, "Súbor '$file_name' sa nenašiel na serveri.") end end """ open_browser(url::String) Attempts to open the given URL in the default web browser. """ function open_browser(url::String) try if Sys.iswindows() run(`cmd /c start $url`) elseif Sys.isapple() run(`open $url`) elseif Sys.islinux() run(`xdg-open $url`) else @warn "Nepodarilo sa automaticky otvoriť prehliadač: Neznámy operačný systém." end @info "Pokus o otvorenie prehliadača na $url" catch e @warn "Nepodarilo sa otvoriť prehliadač: $e" end end """ start_server(host::Sockets.IPAddr=ip"127.0.0.1", port::Int=8080) Starts the HTTP server on the specified host and port. """ function start_server(host::Sockets.IPAddr=ip"127.0.0.1", port::Int=8080) url = "http://$host:$port" @info "Spúšťam server na $url. Ak chcete server zastaviť, stlačte Ctrl+C." # Open browser after a short delay to allow server to start @async begin sleep(1.5) # Give the server a bit more time to fully initialize open_browser(url) end try HTTP.serve(handler, host, port) catch e if isa(e, InterruptException) @info "Server bol zastavený používateľom (Ctrl+C)." else @error "Chyba servera: $e" end end end # Start the server when the script is run start_server()