Public/RocketServer.psm1
using module ".\RocketRouter.psm1" using namespace System.Net using namespace System.Collections.Generic class RocketServer { [string] $Port [string] $Url [RocketRouter] $Router hidden [System.Net.HttpListener] $httpListener RocketServer() { $this.Url = $global:Url $this.Port = $global:Port $this.httpListener = [System.Net.HttpListener]::new() $this.Router = [RocketRouter]::new() $this.httpListener.Prefixes.Add($this.Url + ":" + $this.Port + "/") } [Void] Launch() { Clear-Host Write-Host "-------------------------------------------------" -BackgroundColor DarkBlue -ForegroundColor White Write-Host "🚀 Starting server on $($this.Url):$($this.Port)" Write-Host "-------------------------------------------------" -BackgroundColor DarkBlue -ForegroundColor White Write-Host "" Write-Host "Press Ctrl+C to stop the server" Write-Host "Request received:" try { $this.httpListener.Start() while ($this.httpListener.IsListening) { # start basic web server $httpContext = $this.httpListener.GetContext() $httpMethod = $httpContext.Request.HttpMethod $path = $httpContext.Request.Url.AbsolutePath $auxFilePath = $httpContext.Request.Url.AbsolutePath $auxFilePath = $auxFilePath.Replace("/", "\") $auxFilePath = $auxFilePath.TrimStart("\") $auxFilePath = $auxFilePath.TrimEnd("\") $loc = Get-Location $action = $this.Router.GetAction($path, $httpMethod) if ($action) { Write-Host "[$(Get-Date -Format "HH:mm:ss")] ($($httpContext.Response.StatusCode + " " + $httpContext.Reponse.StatusDescription)) $($httpContext.Request.Url) " $response = $action.Invoke($httpContext) if($response -and $response.GetType().Name -eq "Object[]") { $httpResponse = $httpContext.Response $httpResponse.ContentType = "text/html" if($response.length -eq 2) { $httpResponse.StatusCode = $response[1] } else { $httpResponse.StatusCode = [System.Net.HttpStatusCode]::OK } $buffer = [Text.Encoding]::UTF8.GetBytes($response[0]) $httpResponse.ContentLength64 = $buffer.length $httpResponse.OutputStream.Write($buffer, 0, $buffer.length) } } elseif ($global:ServeStaticFiles -and (Test-Path "$loc/$auxFilePath")){ $filePath = $httpContext.Request.Url.AbsolutePath.Replace("/public/", "/public/") $filePathSeparator = "/" # Fix for Windows path if (-not (Get-ChildItem Env:COMMAND_MODE -ErrorAction SilentlyContinue).Value.StartsWith("unix")) { $filePathSeparator = "\" } $filePath = $filePath.Replace("/", $filePathSeparator) $filePath = $filePath.TrimStart($filePathSeparator) $filePath = $filePath.TrimEnd($filePathSeparator) $httpResponse = $httpContext.Response if ($filePath.EndsWith(".js")) { $httpResponse.ContentType = "text/javascript" } elseif ($filePath.EndsWith(".css")) { $httpResponse.ContentType = "text/css" } elseif ($filePath.EndsWith(".png")) { $httpResponse.ContentType = "image/png" } elseif ($filePath.EndsWith(".jpg")) { $httpResponse.ContentType = "image/jpeg" } elseif ($filePath.EndsWith(".ico")) { $httpResponse.ContentType = "image/x-icon" } elseif ($filePath.EndsWith(".svg")) { $httpResponse.ContentType = "image/svg+xml" } elseif ($filePath.EndsWith(".json")) { $httpResponse.ContentType = "application/json" } elseif ($filePath.EndsWith(".ttf")) { $httpResponse.ContentType = "font/ttf" } else { $httpResponse.ContentType = "text/plain" } try { $httpResponse.StatusCode = [System.Net.HttpStatusCode]::OK $bytes = [System.IO.File]::ReadAllBytes($filePath) Write-Host "[$(Get-Date -Format "HH:mm:ss")] ($($httpContext.Response.StatusCode + " " + $httpContext.Reponse.StatusDescription)) $($httpContext.Request.Url) " $httpResponse.OutputStream.Write($bytes, 0, $bytes.Length) } catch { <#Do this if a terminating exception happens#> } } else { $response = "<h1>404 Not Found</h1>" if ($this.Router.HasErrorHandlers()) { $notFoundAction = $this.Router.GetErrorHandler([System.Net.HttpStatusCode]::NotFound) if ($notFoundAction) { $notFoundResponse = $notFoundAction.Invoke($httpContext) if($notFoundResponse -and $notFoundResponse.GetType().Name -eq "Object[]") { $response = $notFoundResponse[0] } } $httpResponse = $httpContext.Response $httpResponse.ContentType = "text/html" $httpResponse.StatusCode = [System.Net.HttpStatusCode]::NotFound Write-Host "💥 [$(Get-Date -Format "HH:mm:ss")] ($($httpContext.Response.StatusCode + " " + $httpContext.Reponse.StatusDescription)) $($httpContext.Request.Url) " $buffer = [Text.Encoding]::UTF8.GetBytes($response) $httpResponse.ContentLength64 = $buffer.length $httpResponse.OutputStream.Write($buffer, 0, $buffer.length) } } } } catch { $this.Stop() Write-Host "💥 Error: $($_.Exception.Message)" } } [Void] Stop() { $this.httpListener.Stop() } } |