Skip to content

Instantly share code, notes, and snippets.

@ChrisStro
Last active June 19, 2022 20:52
Show Gist options
  • Save ChrisStro/e1b67bc6d553c25fe2c2a2bba954350d to your computer and use it in GitHub Desktop.
Save ChrisStro/e1b67bc6d553c25fe2c2a2bba954350d to your computer and use it in GitHub Desktop.
Simple function to start short running powershell "webserver" ; I mainly use it for Cloud-Init files
function Start-psHTTPServer {
[CmdletBinding()]
param (
[Parameter(Mandatory = $False, Position = 0, HelpMessage = 'Enter a port for the HTTP Server to listen on. Valid ports are between 1 and 65535. Example: 1234')]
[ValidateRange(1, 65535)][int32]$Port = 8081,
[Parameter(Mandatory = $False, Position = 1, HelpMessage = 'Enter hostname or ip for listener')]
[string]$HostNameOrIP = "*",
[Parameter(Mandatory = $False, Position = 2, HelpMessage = 'End listener after single request')]
[switch]$SingleRequest
)
begin {
# init
###########
$listener = New-Object System.Net.HttpListener;
$listener.Prefixes.Add("http://$HostNameOrIP`:$Port/");
$listener.Start()
$webcontent_table = @{
".txt" = "text/plain; charset=utf-8"
".ps1" = "text/plain; charset=utf-8"
".yml" = "text/plain; charset=utf-8"
".yaml" = "text/plain; charset=utf-8"
".cmd" = "text/plain; charset=utf-8"
".bat" = "text/plain; charset=utf-8"
}
# prevent directory traversal attacks
#####################################
$real_path = $PWD
New-PSDrive -Name "webroot" -PSProvider FileSystem -Root $PWD.Path | Out-Null
Push-Location -Path "webroot:\"
}
process {
Write-Host "Browse files via http://$HostNameOrIP`:$Port/"
Write-Host "Stop listener via http://$HostNameOrIP`:$Port/stop"
while ($listener.IsListening) {
try {
# request vars
$context = $listener.GetContext()
$Response = $Context.Response
$Response.ContentType = "text/html; charset=utf-8"
# console output vars
$remote_host = $context.Request.RemoteEndPoint.Address
$access_url = $context.Request.Url
if ($context.Request.RawUrl -eq "/") {
[array]$content = @()
$content += "<html><head><title>PS HTTP Server</title></head><body><h1>PS HTTP Server</h1><hr>"
$content += "<table cellpadding='5'>"
$content += foreach ($file in $(Get-ChildItem -Path $real_path.Path -File)) {
$file_url = $file.FullName -Replace [regex]::Escape($real_path), '' -replace '\\', '/'
$file_length = $file.Length
"<tr><td align='right'>$($file.LastWriteTime)</td>"
"<td align='right'>$file_length</td>"
"<td align='left'><a href='$($file_url)'>$($File.Name)</a></td></tr>"
}
$content += "</table></body></html>"
} elseif ($context.Request.RawUrl -eq "/stop") { $content = "<h1>shutting down listener</h1>"; $stop_listener = $true }
elseif ($context.Request.RawUrl -match "\/[A-Za-z0-9-\s.)(\[\]]") {
$requested_file_path = Join-Path -Path $real_path.Path -ChildPath $context.Request.RawUrl.Trim("/\")
$requested_file = Get-Item $requested_file_path
if (Test-Path $requested_file_path) {
$Response.ContentType = "application/octet-stream"
# handle plain text files
#########################
if ($webcontent_table.Keys -contains $requested_file.Extension) {
$content = Get-Content -Path $requested_file -Raw
$Response.ContentType = $webcontent_table[$requested_file.Extension]
}
}
else {
throw [System.Management.Automation.ItemNotFoundException]::new()
}
}
if ($SingleRequest) { $stop_listener = $true }
# console output
Write-Host "[$(Get-Date -Format g)] $remote_host => $access_url"
Write-Verbose $($content | Out-String)
} catch [System.Management.Automation.ItemNotFoundException] {
Write-Host "Could not reach. Verify server is accessible over the network" -ForegroundColor Magenta
$Response.StatusCode = 404
$content = "<h1>404 - Page Not Found</h1>"
} catch [System.Net.HttpListenerException] {
Write-Host $_ -ForegroundColor Yellow
} finally {
$content = [System.Text.Encoding]::UTF8.GetBytes($content)
$Response.ContentLength64 = $content.Length
$Response.OutputStream.Write($content, 0, $content.Length)
$Response.Close()
Write-Host "Return $($Response.StatusCode)" -ForegroundColor Cyan
# stop listener
###############
if ($stop_listener) { $listener.Stop() ; Pop-Location ; Remove-PSDrive -Name "webroot" }
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment