src/WebServer/main.ps1
#Requires -Version 5.0 <# .SYNOPSIS run a web server to allow users to compile powershell scripts .DESCRIPTION run a web server to allow users to compile powershell scripts .PARAMETER HostUrl The url of the web server .PARAMETER Localize The language code to be used for server-side logging .PARAMETER help Display help message .EXAMPLE Start-ps12exeWebServer .EXAMPLE Start-ps12exeWebServer -HostUrl 'http://localhost:8080/' #> [CmdletBinding()] param ( $HostUrl = 'http://localhost:8080/', [ArgumentCompleter({ Param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) . "$PSScriptRoot\..\LocaleArgCompleter.ps1" @PSBoundParameters })] [string]$Localize, [switch]$help ) $LocalizeData = . $PSScriptRoot\..\LocaleLoader.ps1 -Localize $Localize if ($help) { $MyHelp = $LocalizeData.WebServerHelpData . $PSScriptRoot\..\HelpShower.ps1 -HelpData $MyHelp | Out-Host return } # 加载ps12exe用于处理编译请求 Import-Module $PSScriptRoot/../../ps12exe.psm1 -ErrorAction Stop # 创建 HttpListener 对象 $http = [System.Net.HttpListener]::new() $http.Prefixes.Add($HostUrl) $http.Start() if ($http.IsListening) { Write-Host $LocalizeData.ServerStarted -ForegroundColor Black -BackgroundColor Green Write-Host "$($LocalizeData.ServerListening) $($http.Prefixes)" -ForegroundColor Yellow } else { Write-Host $LocalizeData.ServerFailed -ForegroundColor Black -BackgroundColor Red return } # Set Console Window Title $BackUpTitle = $Host.UI.RawUI.WindowTitle $Host.UI.RawUI.WindowTitle = "ps12exe Web Server" Write-Host $LocalizeData.UnsafeWarning -ForegroundColor Yellow Write-Host $LocalizeData.ExitServerTip -ForegroundColor Yellow function HandleRequest($context) { if ($context.Request.RawUrl -eq '/compile') { # 处理编译请求 $context = $http.GetContext() # 获取用户提交的代码 $Reader = New-Object System.IO.StreamReader($context.Request.InputStream) $userInput = $Reader.ReadToEnd() $Reader.Close() $Reader.Dispose() if (!$userInput) { $context.Response.ContentType = "text/plain" $context.Response.ContentLength64 = 0 $context.Response.Close() return } # new uuid $uuid = [Guid]::NewGuid().ToString() $compiledExePath = "$PSScriptRoot/outputs/$uuid.exe" New-Item -Path $PSScriptRoot/outputs -ItemType Directory -Force | Out-Null # 编译代码 try { $userInput | ps12exe -outputFile $compiledExePath -ErrorAction Stop $context.Response.ContentType = "application/octet-stream" $buffer = [System.IO.File]::ReadAllBytes($compiledExePath) Remove-Item $compiledExePath -Force } catch { # 若ErrorId不是ParseError则写入日志 if ($_.ErrorId -ine "ParseError") { Write-Host $_ -ForegroundColor Red } $context.Response.ContentType = "text/plain" $buffer = [System.Text.Encoding]::UTF8.GetBytes("$_") } } elseif ($context.Request.RawUrl -eq '/') { $body = Get-Content -LiteralPath "$PSScriptRoot/index.html" -Encoding utf8 -Raw $buffer = [System.Text.Encoding]::UTF8.GetBytes($body) } $context.Response.ContentLength64 = $buffer.Length if ($buffer) { $context.Response.OutputStream.Write($buffer, 0, $buffer.Length) } $context.Response.Close() } try { # 无限循环,用于监听请求 直到用户按下 Ctrl+C while ($http.IsListening) { $Async = $http.BeginGetContext($null, $null) while (-not $Async.AsyncWaitHandle.WaitOne(100)) { } HandleRequest($http.EndGetContext($Async)) } } finally { # 关闭 HttpListener $http.Stop() Write-Host $LocalizeData.ServerStopped -ForegroundColor Yellow # Restore Console Window Title $Host.UI.RawUI.WindowTitle = $BackUpTitle # 清空缓存 Remove-Item $PSScriptRoot/outputs/* -Recurse -Force } |