Tools/Server.ps1
function Server { param ( [Parameter(Mandatory=$true)] [ValidateNotNull()] [scriptblock] $ScriptBlock, [Parameter()] [ValidateNotNull()] [Alias('p')] [int] $Port = 0, [Parameter()] [ValidateNotNull()] [Alias('i')] [int] $Interval = 0, [Parameter()] [string] $IP, [Parameter()] [Alias('n')] [string] $Name, [Parameter()] [Alias('t')] [int] $Threads = 1, [switch] $Smtp, [switch] $Tcp, [switch] $Http, [switch] $Https, [switch] $DisableTermination, [switch] $DisableLogging, [switch] $FileMonitor ) # ensure the session is clean $PodeSession = $null # validate port passed if ($Port -lt 0) { throw "Port cannot be negative: $($Port)" } # if an ip address was passed, ensure it's valid if (!(Test-Empty $IP) -and !(Test-IPAddress $IP)) { throw "Invalid IP address has been supplied: $($IP)" } try { # get the current server type $serverType = Get-PodeServerType -Port $Port -Interval $Interval -Smtp:$Smtp -Tcp:$Tcp -Https:$Https # create session object $PodeSession = New-PodeSession -ScriptBlock $ScriptBlock ` -Threads $Threads ` -Interval $Interval ` -ServerRoot $MyInvocation.PSScriptRoot ` -DisableLogging:$DisableLogging ` -FileMonitor:$FileMonitor # for legacy support, create initial listener from Server parameters if (@('http', 'https', 'smtp', 'tcp') -icontains $serverType) { listen "$($IP):$($Port)" $serverType } # set it so ctrl-c can terminate [Console]::TreatControlCAsInput = $true # start the file monitor for interally restarting Start-PodeFileMonitor # start the server Start-PodeServer # at this point, if it's just a one-one off script, return if ([string]::IsNullOrWhiteSpace($PodeSession.Server.Type)) { return } # sit here waiting for termination or cancellation while (!(Test-TerminationPressed -Key $key) -and !($PodeSession.Tokens.Cancellation.IsCancellationRequested)) { Start-Sleep -Seconds 1 # get the next key presses $key = Get-ConsoleKey # check for internal restart if (($PodeSession.Tokens.Restart.IsCancellationRequested) -or (Test-RestartPressed -Key $key)) { Restart-PodeServer } } Write-Host 'Terminating...' -NoNewline -ForegroundColor Yellow $PodeSession.Tokens.Cancellation.Cancel() } finally { # clean the runspaces and tokens Close-Pode -Exit # clean the session $PodeSession = $null } } function Start-PodeServer { try { # setup temp drives for internal dirs Add-PodePSInbuiltDrives # run the logic Invoke-ScriptBlock -ScriptBlock $PodeSession.Server.Logic -NoNewClosure $_type = $PodeSession.Server.Type.ToUpperInvariant() if (![string]::IsNullOrWhiteSpace($_type)) { # start runspace for timers Start-TimerRunspace # start runspace for schedules Start-ScheduleRunspace # start runspace for gui Start-GuiRunspace } # start the appropriate server switch ($_type) { 'SMTP' { Start-SmtpServer } 'TCP' { Start-TcpServer } { $_ -ieq 'HTTP' -or $_ -ieq 'HTTPS' } { Start-WebServer } 'SERVICE' { Start-ServiceServer } } } catch { throw $_.Exception } } function Restart-PodeServer { try { # inform restart Write-Host 'Restarting server...' -NoNewline -ForegroundColor Cyan # cancel the session token $PodeSession.Tokens.Cancellation.Cancel() # close all current runspaces Close-PodeRunspaces # remove all of the pode temp drives Remove-PodePSDrives # clear up timers, schedules and loggers $PodeSession.Server.Routes.Keys.Clone() | ForEach-Object { $PodeSession.Server.Routes[$_].Clear() } $PodeSession.Server.Handlers.Keys.Clone() | ForEach-Object { $PodeSession.Server.Handlers[$_] = $null } $PodeSession.Timers.Clear() $PodeSession.Schedules.Clear() $PodeSession.Server.Logging.Methods.Clear() # clear middle/endware $PodeSession.Server.Middleware = @() $PodeSession.Server.Endware = @() # set view engine back to default $PodeSession.Server.ViewEngine = @{ 'Engine' = 'html'; 'Extension' = 'html'; 'Script' = $null; } # clear up cookie sessions $PodeSession.Server.Cookies.Session.Clear() # clear up authentication methods $PodeSession.Server.Authentications.Clear() # clear up shared state $PodeSession.Server.State.Clear() # recreate the session tokens dispose $PodeSession.Tokens.Cancellation $PodeSession.Tokens.Cancellation = New-Object System.Threading.CancellationTokenSource dispose $PodeSession.Tokens.Restart $PodeSession.Tokens.Restart = New-Object System.Threading.CancellationTokenSource Write-Host " Done" -ForegroundColor Green # restart the server Start-PodeServer } catch { $Error[0] | Out-Default throw $_.Exception } } function Get-PodeServerType { param ( [Parameter()] [int] $Port = 0, [Parameter()] [int] $Interval = 0, [switch] $Smtp, [switch] $Tcp, [switch] $Https ) if ($Smtp) { return 'SMTP' } if ($Tcp) { return 'TCP' } if ($Https) { return 'HTTPS' } if ($Port -gt 0) { return 'HTTP' } if ($Interval -gt 0) { return 'SERVICE' } return ([string]::Empty) } |