Last active
September 1, 2025 10:05
-
-
Save anonhostpi/1cc0084b959a9ea9e97dca9dce414e1f to your computer and use it in GitHub Desktop.
Revisions
-
anonhostpi revised this gist
Aug 31, 2025 . 1 changed file with 29 additions and 269 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -38,7 +38,7 @@ function New-Webserver { $Server = New-Object psobject -Property @{ Binding = $Binding BaseDirectory = "$(Resolve-Path $BaseDirectory -ErrorAction SilentlyContinue)".TrimEnd('\/') Name = $Name Routes = $Routes Caching = [bool]$Cache @@ -100,7 +100,7 @@ function New-Webserver { } $Server | Add-Member -MemberType ScriptMethod -Name Read -Value (& { If( $null -ne $Reader ) { return $Reader } @@ -133,254 +133,11 @@ function New-Webserver { throw "Invalid path '$Path'." } return @{ Path = $file Content = (Get-Content "$root\$Path" -Raw -ErrorAction SilentlyContinue) } } }) $Server | Add-Member -MemberType ScriptMethod -Name Serve -Value { @@ -395,7 +152,10 @@ function New-Webserver { } Try { $result = $this.Read($File) $content = $result.Content $extension = [System.IO.Path]::GetExtension($result.Path) $mimetype = $this.ConvertExtension( $extension ) If( $this.Caching -and -not [string]::IsNullOrWhitespace($content) ) { @@ -451,8 +211,6 @@ function New-Webserver { } $Server | Add-Member -MemberType ScriptMethod -Name Stop -Value { If( $null -ne $this.Listener -and $this.Listener.IsListening ) { $this.Listener.Stop() $this.Listener.Close() @@ -461,8 +219,6 @@ function New-Webserver { } $Server | Add-Member -MemberType ScriptMethod -Name Start -Value { $this.Listener = New-Object System.Net.HttpListener $this.Listener.Prefixes.Add($this.Binding) $this.Listener.Start() @@ -479,7 +235,7 @@ function New-Webserver { # $context = $this.Listener.GetContext() # $task.Result $task = $this.Listener.GetContextAsync() While( -not $task.AsyncWaitHandle.WaitOne(300) ) { if( -not $this.Listener.IsListening ) { return } } @@ -488,8 +244,8 @@ function New-Webserver { $command = "{0} {1}" -f $request.HttpMethod, $request.Url.AbsolutePath If( $this.Routes.Before -is [scriptblock] ) { $allow = & $this.Routes.Before $Server $command $this.Listener $context If( -not $allow ) { continue } } @@ -507,28 +263,32 @@ function New-Webserver { If( $route -is [scriptblock] ) { & $route $this $command $request $response } Else { $this.Serve( $route, $response ) } } Catch { $response.StatusCode = 500 "500 Internal Server Error`n`n$($_.Exception.Message)" } if( -not [string]::IsNullOrWhiteSpace($result) ) { Try { $buffer = [System.Text.Encoding]::UTF8.GetBytes($result) $response.ContentLength64 = $buffer.Length If( [string]::IsNullOrWhiteSpace($response.Headers["Last-Modified"]) ){ $response.Headers.Add("Last-Modified", (Get-Date).ToString("r")) } If( [string]::IsNullOrWhiteSpace($response.Headers["Server"]) ){ $response.Headers.Add("Server", $Name) } $response.OutputStream.Write( $buffer, 0, $buffer.Length ) } Catch {} } Try { $response.Close() } Catch {} If( $this.Routes.After -is [scriptblock] ) { & $this.Routes.After $Server $command $this.Listener $context -
anonhostpi revised this gist
Aug 31, 2025 . 1 changed file with 247 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -214,6 +214,252 @@ function New-Webserver { } } $Server | Add-Member -MemberType ScriptMethod -Name Start -Value { param() $this.Listener = New-Object System.Net.HttpListener $this.Listener.Prefixes.Add($this.Binding) $this.Listener.Start() (& { Try { While ( $this.Listener.IsListening ) { <# $task = $this.Listener.GetContextAsync() if (-not ($task.Wait(300))) { Write-Host "Polling..." continue } #> # $context = $this.Listener.GetContext() # $task.Result $task = $this.Listener.GetContextAsync() while( -not $task.AsyncWaitHandle.WaitOne(300) ) { if( -not $this.Listener.IsListening ) { return } } $context = $task.GetAwaiter().GetResult() $request = $context.Request $command = "{0} {1}" -f $request.HttpMethod, $request.Url.AbsolutePath If( $this.Routes.Before -is [scriptblock] ) { $continue = & $this.Routes.Before $Server $command $this.Listener $context If( -not $continue ) { continue } function New-Webserver { param( [string] $Binding = "http://localhost:8080/", [string] $BaseDirectory = "$(Get-Location -PSProvider FileSystem)", [string] $Name = "PowerShell Web Server", [System.Collections.IDictionary] $Routes = @{ Before = { param( $Server, $Command, $Listener, $Context ) return $true } After = { param( $Server, $Command, $Listener, $Context ) return $true } # "GET /" = { param( $Server, $Command, $request, $response )... } # "GET /hello" = "./path/to/static/file.html" Default = { param( $Server, $Command, $Request, $Response ) $Command = $Command -split " ", 2 $path = $Command | Select-Object -Index 1 return $Server.Serve( $path, $Response ) } }, [switch] $Cache, [scriptblock] $Reader ) If( $Routes -eq $null ) { $Routes = [ordered]@{} } If( $Routes.Default -eq $null ) { $Routes.Default = { param( $Server, $Command, $Request, $Response ) $Response.StatusCode = 404 return "404 Not Found" } } $Server = New-Object psobject -Property @{ Binding = $Binding BaseDirectory = "$(Resolve-Path $BaseDirectory)".TrimEnd('\/') Name = $Name Routes = $Routes Caching = [bool]$Cache Cached = @{} Listener = $null } $Server | Add-Member -MemberType ScriptMethod -Name ConvertExtension -Value { param( [string] $Extension ) switch( $Extension.ToLower() ) { ".html" { "text/html; charset=utf-8" } ".htm" { "text/html; charset=utf-8" } ".css" { "text/css; charset=utf-8" } ".js" { "application/javascript; charset=utf-8" } ".json" { "application/json; charset=utf-8" } ".txt" { "text/plain; charset=utf-8" } ".xml" { "application/xml; charset=utf-8" } ".csv" { "text/csv; charset=utf-8" } ".tsv" { "text/tab-separated-values; charset=utf-8" } ".md" { "text/markdown; charset=utf-8" } ".png" { "image/png" } ".jpg" { "image/jpeg" } ".jpeg" { "image/jpeg" } ".gif" { "image/gif" } ".svg" { "image/svg+xml" } ".ico" { "image/x-icon" } ".bmp" { "image/bmp" } ".avif" { "image/avif" } ".webp" { "image/webp" } ".mp4" { "video/mp4" } ".webm" { "video/webm" } ".avi" { "video/x-msvideo" } ".mov" { "video/quicktime" } ".mp3" { "audio/mpeg" } ".wav" { "audio/wav" } ".ogg" { "audio/ogg" } ".pdf" { "application/pdf" } ".zip" { "application/zip" } ".tar" { "application/x-tar" } ".gz" { "application/gzip" } ".7z" { "application/x-7z-compressed" } ".bz2" { "application/x-bzip2" } ".woff" { "font/woff" } ".woff2" { "font/woff2" } ".ttf" { "font/ttf" } ".eot" { "application/vnd.ms-fontobject" } ".otf" { "font/otf" } default { "application/octet-stream" } } } $Server | Add-Member -MemberType ScriptMethod -Name Read -Value (& { If( $Reader -ne $null ) { return $Reader } return { param( [string] $Path ) $root = $this.BaseDirectory $Path = $Path.TrimStart('\/') $file = "$root\$Path".TrimEnd('\/') $file = Try { Resolve-Path $file -ErrorAction Stop } Catch { Try { Resolve-Path "$file.html" -ErrorAction Stop } Catch { Resolve-Path "$file\index.html" -ErrorAction SilentlyContinue } } $file = "$file" # Throw on directory traversal attacks and invalid paths $bad = @( [string]::IsNullOrWhitespace($file), -not (Test-Path $file -PathType Leaf -ErrorAction SilentlyContinue), -not ($file -like "$root*") ) if ( $bad -contains $true ) { throw "Invalid path '$Path'." } return (Get-Content "$root\$Path" -Raw -ErrorAction SilentlyContinue) } }) $Server | Add-Member -MemberType ScriptMethod -Name Serve -Value { param( [string] $File, $Response ) If( $null -ne $this.Cached[$File] ) { $Response.ContentType = $this.Cached[$File].Type return $this.Cached[$File].Content } Try { $content = $this.Read($File) $mimetype = $this.ConvertExtension( $extension ) If( $this.Caching -and -not [string]::IsNullOrWhitespace($content) ) { $this.Cached[$File] = @{ Content = $content Type = $mimetype } } $Response.ContentType = $mimetype return $content } Catch { $Response.StatusCode = 404 return "404 Not Found" } } $Server | Add-Member -MemberType ScriptMethod -Name ParseQuery -Value { param( $Request ) return [System.Web.HttpUtility]::ParseQueryString($Request.Url.Query) } $Server | Add-Member -MemberType ScriptMethod -Name ParseBody -Value { param( $Request ) If( -not $Request.HasEntityBody -or $Request.ContentLength64 -le 0 ) { return $null } $stream = $Request.InputStream $encoding = $Request.ContentEncoding $reader = New-Object System.IO.StreamReader( $stream, $encoding ) $body = $reader.ReadToEnd() $reader.Close() $stream.Close() switch -Wildcard ( $Request.ContentType ) { "application/x-www-form-urlencoded*" { return [System.Web.HttpUtility]::ParseQueryString($body) } "application/json*" { return $body | ConvertFrom-Json } "text/xml*" { return [xml]$body } default { return $body } } } $Server | Add-Member -MemberType ScriptMethod -Name Stop -Value { param() If( $null -ne $this.Listener -and $this.Listener.IsListening ) { $this.Listener.Stop() $this.Listener.Close() $this.Listener = $null } } $Server | Add-Member -MemberType ScriptMethod -Name Start -Value { param() @@ -276,7 +522,7 @@ function New-Webserver { $response.Headers.Add("Last-Modified", (Get-Date).ToString("r")) } If( [string]::IsNullOrWhiteSpace($response.Headers["Server"]) ){ $response.Headers.Add("Server", $Name) } $response.OutputStream.Write( $buffer, 0, $buffer.Length ) -
anonhostpi revised this gist
Aug 31, 2025 . 1 changed file with 7 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,7 +1,5 @@ # iex (iwr "https://gist.github.com/anonhostpi/1cc0084b959a9ea9e97dca9dce414e1f/raw/webserver.ps1").Content function New-Webserver { param( [string] $Binding = "http://localhost:8080/", @@ -28,12 +26,13 @@ function New-Webserver { ) If( $Routes -eq $null ) { $Routes = [ordered]@{} } If( $Routes.Default -eq $null ) { $Routes.Default = { param( $Server, $Command, $Request, $Response ) $Response.StatusCode = 404 return "404 Not Found" } } -
anonhostpi revised this gist
Aug 31, 2025 . 1 changed file with 59 additions and 57 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -126,7 +126,7 @@ function New-Webserver { # Throw on directory traversal attacks and invalid paths $bad = @( [string]::IsNullOrWhitespace($file), -not (Test-Path $file -PathType Leaf -ErrorAction SilentlyContinue), -not ($file -like "$root*") ) @@ -222,78 +222,80 @@ function New-Webserver { $this.Listener.Prefixes.Add($this.Binding) $this.Listener.Start() (& { Try { While ( $this.Listener.IsListening ) { <# $task = $this.Listener.GetContextAsync() if (-not ($task.Wait(300))) { Write-Host "Polling..." continue } #> # $context = $this.Listener.GetContext() # $task.Result $task = $this.Listener.GetContextAsync() while( -not $task.AsyncWaitHandle.WaitOne(300) ) { if( -not $this.Listener.IsListening ) { return } } $context = $task.GetAwaiter().GetResult() $request = $context.Request $command = "{0} {1}" -f $request.HttpMethod, $request.Url.AbsolutePath If( $this.Routes.Before -is [scriptblock] ) { $continue = & $this.Routes.Before $Server $command $this.Listener $context If( -not $continue ) { continue } } $response = $context.Response $response.ContentType = "text/plain; charset=utf-8" $result = Try { $route = If( $this.Routes[$command] ) { $this.Routes[$command] } Else { $this.Routes.Default } If( $route -is [scriptblock] ) { & $route $this $command $request $response } Else { & $this.Serve $route $response } } Catch { $response.StatusCode = 500 "500 Internal Server Error`n`n$($_.Exception.Message)" } if( -not [string]::IsNullOrWhiteSpace($result) ) { $buffer = [System.Text.Encoding]::UTF8.GetBytes($result) $response.ContentLength64 = $buffer.Length If( [string]::IsNullOrWhiteSpace($response.Headers["Last-Modified"]) ){ $response.Headers.Add("Last-Modified", (Get-Date).ToString("r")) } If( [string]::IsNullOrWhiteSpace($response.Headers["Server"]) ){ $response.Headers.Add("Server", $ServerName) } $response.OutputStream.Write( $buffer, 0, $buffer.Length ) } $response.Close() If( $this.Routes.After -is [scriptblock] ) { & $this.Routes.After $Server $command $this.Listener $context } } } finally { $this.Stop() } }) | Out-Null } return $Server } # $server = New-Webserver -
anonhostpi revised this gist
Aug 31, 2025 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -292,6 +292,8 @@ function New-Webserver { $this.Stop() } } return $server } # $server = New-Webserver -
anonhostpi revised this gist
Aug 31, 2025 . 1 changed file with 48 additions and 46 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -9,16 +9,18 @@ function New-Webserver { [string] $Name = "PowerShell Web Server", [System.Collections.IDictionary] $Routes = @{ Before = { param( $Server, $Command, $Listener, $Context ) return $true } After = { param( $Server, $Command, $Listener, $Context ) return $true } # "GET /" = { param( $Server, $Command, $request, $response )... } # "GET /hello" = "./path/to/static/file.html" Default = { param( $Server, $Command, $Request, $Response ) $Command = $Command -split " ", 2 $path = $Command | Select-Object -Index 1 return $Server.Serve( $path, $Response ) } }, [switch] $Cache, @@ -28,8 +30,8 @@ function New-Webserver { If( $Routes -eq $null ) { $Routes = @{ Default = { param( $Server, $Command, $Request, $Response ) $Response.StatusCode = 404 return "404 Not Found" } } @@ -45,44 +47,6 @@ function New-Webserver { Listener = $null } $Server | Add-Member -MemberType ScriptMethod -Name ConvertExtension -Value { param( [string] $Extension ) @@ -136,6 +100,44 @@ function New-Webserver { } } $Server | Add-Member -MemberType ScriptMethod -Name Read -Value (& { If( $Reader -ne $null ) { return $Reader } return { param( [string] $Path ) $root = $this.BaseDirectory $Path = $Path.TrimStart('\/') $file = "$root\$Path".TrimEnd('\/') $file = Try { Resolve-Path $file -ErrorAction Stop } Catch { Try { Resolve-Path "$file.html" -ErrorAction Stop } Catch { Resolve-Path "$file\index.html" -ErrorAction SilentlyContinue } } $file = "$file" # Throw on directory traversal attacks and invalid paths $bad = @( [string]::IsNullOrWhitespace($file), -not (Test-Path $file -ErrorAction SilentlyContinue), -not ($file -like "$root*") ) if ( $bad -contains $true ) { throw "Invalid path '$Path'." } return (Get-Content "$root\$Path" -Raw -ErrorAction SilentlyContinue) } }) $Server | Add-Member -MemberType ScriptMethod -Name Serve -Value { param( [string] $File, -
anonhostpi revised this gist
Aug 31, 2025 . 1 changed file with 247 additions and 94 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,144 +1,297 @@ # iex (iwr "https://gist.github.com/anonhostpi/1cc0084b959a9ea9e97dca9dce414e1f/raw/webserver.ps1").Content # An improved version of https://github.com/MScholtes/WebServer/blob/master/Module/Start-Webserver.ps1 function New-Webserver { param( [string] $Binding = "http://localhost:8080/", [string] $BaseDirectory = "$(Get-Location -PSProvider FileSystem)", [string] $Name = "PowerShell Web Server", [System.Collections.IDictionary] $Routes = @{ Before = { param( $server, $command, $listener, $context ) return $true } After = { param( $server, $command, $listener, $context ) return $true } # "GET /" = { param( $server, $command, $request, $response )... } # "GET /hello" = "./path/to/static/file.html" Default = { param( $server, $command, $request, $response ) $response.StatusCode = 404 return "404 Not Found" } }, [switch] $Cache, [scriptblock] $Reader ) If( $Routes -eq $null ) { $Routes = @{ Default = { param( $server, $command, $request, $response ) $response.StatusCode = 404 return "404 Not Found" } } } $Server = New-Object psobject -Property @{ Binding = $Binding BaseDirectory = "$(Resolve-Path $BaseDirectory)".TrimEnd('\/') Name = $Name Routes = $Routes Caching = [bool]$Cache Cached = @{} Listener = $null } $Server | Add-Member -MemberType ScriptMethod -Name Read -Value (& { If( $Reader -ne $null ) { return $Reader } return { param( [string] $Path ) $root = $this.BaseDirectory $Path = $Path.TrimStart('\/') $file = "$root\$Path" $file = Try { Resolve-Path $file -ErrorAction Stop } Catch { Try { Resolve-Path "$file.html" -ErrorAction Stop } Catch { Resolve-Path "$file\index.html" -ErrorAction SilentlyContinue } } $file = "$file" # Throw on directory traversal attacks and invalid paths $bad = @( [string]::IsNullOrWhitespace($file), -not (Test-Path $file -ErrorAction SilentlyContinue), -not ($file -like "$root*") ) if ( $bad -contains $true ) { throw "Invalid path '$Path'." } return (Get-Content "$root\$Path" -Raw -ErrorAction SilentlyContinue) } }) $Server | Add-Member -MemberType ScriptMethod -Name ConvertExtension -Value { param( [string] $Extension ) switch( $Extension.ToLower() ) { ".html" { "text/html; charset=utf-8" } ".htm" { "text/html; charset=utf-8" } ".css" { "text/css; charset=utf-8" } ".js" { "application/javascript; charset=utf-8" } ".json" { "application/json; charset=utf-8" } ".txt" { "text/plain; charset=utf-8" } ".xml" { "application/xml; charset=utf-8" } ".csv" { "text/csv; charset=utf-8" } ".tsv" { "text/tab-separated-values; charset=utf-8" } ".md" { "text/markdown; charset=utf-8" } ".png" { "image/png" } ".jpg" { "image/jpeg" } ".jpeg" { "image/jpeg" } ".gif" { "image/gif" } ".svg" { "image/svg+xml" } ".ico" { "image/x-icon" } ".bmp" { "image/bmp" } ".avif" { "image/avif" } ".webp" { "image/webp" } ".mp4" { "video/mp4" } ".webm" { "video/webm" } ".avi" { "video/x-msvideo" } ".mov" { "video/quicktime" } ".mp3" { "audio/mpeg" } ".wav" { "audio/wav" } ".ogg" { "audio/ogg" } ".pdf" { "application/pdf" } ".zip" { "application/zip" } ".tar" { "application/x-tar" } ".gz" { "application/gzip" } ".7z" { "application/x-7z-compressed" } ".bz2" { "application/x-bzip2" } ".woff" { "font/woff" } ".woff2" { "font/woff2" } ".ttf" { "font/ttf" } ".eot" { "application/vnd.ms-fontobject" } ".otf" { "font/otf" } default { "application/octet-stream" } } } $Server | Add-Member -MemberType ScriptMethod -Name Serve -Value { param( [string] $File, $Response ) If( $null -ne $this.Cached[$File] ) { $Response.ContentType = $this.Cached[$File].Type return $this.Cached[$File].Content } Try { $content = $this.Read($File) $mimetype = $this.ConvertExtension( $extension ) If( $this.Caching -and -not [string]::IsNullOrWhitespace($content) ) { $this.Cached[$File] = @{ Content = $content Type = $mimetype } } $Response.ContentType = $mimetype return $content } Catch { $Response.StatusCode = 404 return "404 Not Found" } } $Server | Add-Member -MemberType ScriptMethod -Name ParseQuery -Value { param( $Request ) return [System.Web.HttpUtility]::ParseQueryString($Request.Url.Query) } $Server | Add-Member -MemberType ScriptMethod -Name ParseBody -Value { param( $Request ) If( -not $Request.HasEntityBody -or $Request.ContentLength64 -le 0 ) { return $null } $stream = $Request.InputStream $encoding = $Request.ContentEncoding $reader = New-Object System.IO.StreamReader( $stream, $encoding ) $body = $reader.ReadToEnd() $reader.Close() $stream.Close() switch -Wildcard ( $Request.ContentType ) { "application/x-www-form-urlencoded*" { return [System.Web.HttpUtility]::ParseQueryString($body) } "application/json*" { return $body | ConvertFrom-Json } "text/xml*" { return [xml]$body } default { return $body } } } $Server | Add-Member -MemberType ScriptMethod -Name Stop -Value { param() If( $null -ne $this.Listener -and $this.Listener.IsListening ) { $this.Listener.Stop() $this.Listener.Close() $this.Listener = $null } } $Server | Add-Member -MemberType ScriptMethod -Name Start -Value { param() $this.Listener = New-Object System.Net.HttpListener $this.Listener.Prefixes.Add($this.Binding) $this.Listener.Start() Try { While ( $this.Listener.IsListening ) { <# $task = $this.Listener.GetContextAsync() if (-not ($task.Wait(300))) { Write-Host "Polling..." continue } #> # $context = $this.Listener.GetContext() # $task.Result $task = $this.Listener.GetContextAsync() while( -not $task.AsyncWaitHandle.WaitOne(300) ) { if( -not $this.Listener.IsListening ) { return } } $context = $task.GetAwaiter().GetResult() $request = $context.Request $command = "{0} {1}" -f $request.HttpMethod, $request.Url.AbsolutePath If( $this.Routes.Before -is [scriptblock] ) { $continue = & $this.Routes.Before $this $command $this.Listener $context If( -not $continue ) { continue } } $response = $context.Response $response.ContentType = "text/plain; charset=utf-8" $result = Try { $route = If( $this.Routes[$command] ) { $this.Routes[$command] } Else { $this.Routes.Default } If( $route -is [scriptblock] ) { & $route $this $command $request $response } Else { & $this.Serve $route $response } } Catch { $response.StatusCode = 500 "500 Internal Server Error`n`n$($_.Exception.Message)" } if( -not [string]::IsNullOrWhiteSpace($result) ) { $buffer = [System.Text.Encoding]::UTF8.GetBytes($result) $response.ContentLength64 = $buffer.Length If( [string]::IsNullOrWhiteSpace($response.Headers["Last-Modified"]) ){ $response.Headers.Add("Last-Modified", (Get-Date).ToString("r")) } If( [string]::IsNullOrWhiteSpace($response.Headers["Server"]) ){ $response.Headers.Add("Server", $ServerName) } $response.OutputStream.Write( $buffer, 0, $buffer.Length ) } $response.Close() If( $this.Routes.After -is [scriptblock] ) { & $this.Routes.After $server $command $this.Listener $context } } } finally { $this.Stop() } } } # $server = New-Webserver # Start "http://localhost:8080" # $server.Start() -
anonhostpi revised this gist
Aug 30, 2025 . 1 changed file with 12 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -68,11 +68,20 @@ function Start-Webserver { Try { While ( $listener.IsListening ) { <# $task = $listener.GetContextAsync() if (-not ($task.Wait(300))) { Write-Host "Polling..." continue } #> # $context = $listener.GetContext() # $task.Result $task = $listener.GetContextAsync() while( -not $task.AsyncWaitHandle.WaitOne(300) ) { if( -not $listener.IsListening ) { return } } $context = $task.GetAwaiter().GetResult() $request = $context.Request $command = "{0} {1}" -f $request.HttpMethod, $request.Url.AbsolutePath -
anonhostpi revised this gist
Aug 30, 2025 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -131,5 +131,5 @@ function Start-Webserver { } } # Start "http://localhost:8080" # Start-WebServer -
anonhostpi revised this gist
Aug 30, 2025 . 1 changed file with 48 additions and 26 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -23,29 +23,39 @@ function Start-Webserver { $BaseDirectory = "$(Resolve-Path $BaseDirectory)" $serve_static = { param( [string] $path, $response ) $file = "$BaseDirectory\$($path.TrimStart('/').Replace('/','\'))" $file = "$(Resolve-Path $file)" If( Test-Path $file ){ # Prevent directory traversal attacks If( -not $file.StartsWith($BaseDirectory) ){ $response.StatusCode = 403 return "403 Forbidden" } return (Get-Content $file -Raw) } Else { $response.StatusCode = 404 return "404 Not Found" } } If( [string]::IsNullOrWhitespace( $Routes.Default ) ) { If( [string]::IsNullOrWhitespace( $Routes["GET /"] ) ) { $Routes["GET /"] = { return "Hello, World!" } } # Simple static webfile server $Routes.Default = { param( $command, $request, $response ) & $serve_static $request.Url.AbsolutePath $response } } @@ -65,26 +75,34 @@ function Start-Webserver { $context = $task.Result $request = $context.Request $command = "{0} {1}" -f $request.HttpMethod, $request.Url.AbsolutePath If( $Routes.Before ) { $continue = & $Routes.Before $command $listener $context If( -not $continue ) { continue } } $response = $context.Response $response.ContentType = "text/plain; charset=utf-8" $result = try { If( $Routes[$command] ) { If ( $Routes[$command] -is [scriptblock] ) { & $Routes[$command] $command $request $response } Else { & $serve_static $Routes[$command] $response } } Else { If( $Routes.Default -is [scriptblock] ) { & $Routes.Default $command $request $response } Else { & $serve_static $Routes.Default $response } } } catch { $response.StatusCode = 500 "500 Internal Server Error`n`n$($_.Exception.Message)" } if( -not [string]::IsNullOrWhiteSpace($result) ) { @@ -102,6 +120,10 @@ function Start-Webserver { } $response.Close() If( $Routes.After ) { $null = & $Routes.After $command $listener $context } } } finally { $listener.Stop() -
anonhostpi revised this gist
Aug 30, 2025 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,4 +1,4 @@ # iex (iwr "https://gist.github.com/anonhostpi/1cc0084b959a9ea9e97dca9dce414e1f/raw/webserver.ps1").Content function Start-Webserver { param( -
anonhostpi revised this gist
Aug 30, 2025 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,5 @@ # iex (iwr "https://gist.github.com/anonhostpi/1cc0084b959a9ea9e97dca9dce414e1f/raw/webserver.ps1").Contents function Start-Webserver { param( [string] $Binding = "http://localhost:8080/", -
anonhostpi created this gist
Aug 30, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,111 @@ function Start-Webserver { param( [string] $Binding = "http://localhost:8080/", [string] $BaseDirectory = "$(Get-Location -PSProvider FileSystem)", [string] $ServerName = "PowerShell Webserver", [System.Collections.IDictionary] $Routes = @{ Before = { param( $command, $listener, $context ) return $true } After = { param( $command, $listener, $context ) return $true } # "GET /" = { ... } # "GET /hello" = "./path/to/static/file.html" Default = { param( $command, $request, $response ) $msg = "Hello, World!" # $response.OutputStream.Write( [System.Text.Encoding]::UTF8.GetBytes($msg), 0, $msg.Length ) return $msg } } ) $BaseDirectory = "$(Resolve-Path $BaseDirectory)" If( [string]::IsNullOrWhiteSpace($Routes.Default) ) { If( [string]::IsNullOrWhiteSpace($Routes["GET /"]) ) { $Routes["GET /"] = { param( $request, $response ) $msg = "Hello, World!" return $msg } } $Routes.Default = { param( $command, $request, $response ) $file = "$BaseDirectory\$($request.Url.AbsolutePath.TrimStart('/').Replace('/','\'))" If( Test-Path $file ) { # Prevent escaping the base directory If( -not $file.StartsWith($BaseDirectory) ) { $response.StatusCode = 403 return "403 Forbidden" } return Get-Content $file -Raw } Else { $response.StatusCode = 404 return "404 Not Found" } } } $listener = New-Object System.Net.HttpListener $listener.Prefixes.Add($Binding) $listener.Start() $Error.Clear() Try { While ( $listener.IsListening ) { $task = $listener.GetContextAsync() $ready = $task.Wait(100) # 100 ms timeout if (-not $ready) { continue } $context = $task.Result $request = $context.Request $command = "{0} {1}" -f $request.HttpMethod, $request.Url.LocalPath If( $routes.Before ) { $continue = & $routes.Before $command $listener $context If( -not $continue ) { continue } } $response = $context.Response $response.ContentType = "text/plain; charset=utf-8" try { $result = If( $routes[$command] ) { & $routes[$command] $request $response } Else { & $routes.Default $command $request $response } } catch { $response.StatusCode = 500 $result = "500 Internal Server Error`n`n$($_.Exception.Message)" } if( -not [string]::IsNullOrWhiteSpace($result) ) { $buffer = [System.Text.Encoding]::UTF8.GetBytes($result) $response.ContentLength64 = $buffer.Length If( [string]::IsNullOrWhiteSpace($response.Headers["Last-Modified"]) ){ $response.Headers.Add("Last-Modified", (Get-Date).ToString("r")) } If( [string]::IsNullOrWhiteSpace($response.Headers["Server"]) ){ $response.Headers.Add("Server", $ServerName) } $response.OutputStream.Write( $buffer, 0, $buffer.Length ) } $response.Close() } } finally { $listener.Stop() $listener.Close() } } Start "http://localhost:8080" Start-WebServer