Skip to content

Instantly share code, notes, and snippets.

@andrii-riabchun
Created September 25, 2016 12:52
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrii-riabchun/07f854939ce776f6e54ba6b64f43cc92 to your computer and use it in GitHub Desktop.
Save andrii-riabchun/07f854939ce776f6e54ba6b64f43cc92 to your computer and use it in GitHub Desktop.
Powershell static http server
#Requires -RunAsAdministrator
# Simple static http server.
Param(
[int]$port = 8080,
[string]$root = (Get-Location)
)
function Serve {
$listener = [System.Net.HttpListener]::new()
$listener.Prefixes.Add("http://+:$port/")
Write-Host "Root: $root"
try {
$listener.Start()
Write-Host "server started on :$port"
while ($listener.IsListening) {
$context = $null
$ctxTask = $listener.GetContextAsync()
do {
if ($ctxTask.Wait(100)) {
$context = $ctxTask.Result
}
}
while (-not $context)
Handle $context
}
}
catch [System.Exception] {
Write-Host $_
}
finally {
$listener.Stop()
}
}
function Handle([System.Net.HttpListenerContext] $context) {
try {
Write-Host $context.Request.RawUrl
$path = $context.Request.RawUrl.TrimStart("/")
if ([String]::IsNullOrWhiteSpace($path)) {
$path = "index.html"
}
$path = [System.IO.Path]::Combine($root, $path)
if ([System.IO.File]::Exists($path)) {
$fstream = [System.IO.FileStream]::new($path, [System.IO.FileMode]::Open)
$fstream.CopyTo($context.Response.OutputStream)
} else {
$context.Response.StatusCode = 404
}
}
catch [System.Exception] {
$context.Response.StatusCode = 500
Write-Error $_
}
finally {
$context.Response.Close()
}
}
Serve
@Tim-S
Copy link

Tim-S commented Aug 3, 2022

Thx - a handy little snippet ;)

Had a small issue with static content that required the MIME-type to be set correctly (Content contained scripts that use Webworkers).
Can be adapted to simply (try to) determine the MIMEtype from the filepath with the help of [System.Web.MimeMapping]::GetMimeMapping before writing the file to Outputstream.

# ...

# import System.Web for  [System.Web.MimeMapping]::GetMimeMapping
Add-Type -AssemblyName System.Web

function Handle([System.Net.HttpListenerContext] $context) {
    try {
        Write-Host $context.Request.RawUrl
        $path = $context.Request.RawUrl.TrimStart("/")

        if ([String]::IsNullOrWhiteSpace($path)) {
            $path = "index.html"
        }
        $path = [System.IO.Path]::Combine($root, $path)
        if ([System.IO.File]::Exists($path)) {
            $fstream = [System.IO.FileStream]::new($path, [System.IO.FileMode]::Open)
            
            # set proper Mimetype
            $mimeType = [System.Web.MimeMapping]::GetMimeMapping($path);
            $context.Response.ContentType = $mimeType;

            $fstream.CopyTo($context.Response.OutputStream)
        } else {
            $context.Response.StatusCode = 404
        }
    }
    catch [System.Exception] {
        $context.Response.StatusCode = 500
        Write-Error $_
    }
    finally {
        $context.Response.Close()
    }
}

@KirtCarson
Copy link

I was getting file lock errors. I modified the $fstream line to be read only

$fstream = [System.IO.FileStream]::new($path, [System.IO.FileMode]::open , [System.IO.FileAccess]::Read )
Cheers!

@KirtCarson
Copy link

KirtCarson commented Sep 11, 2022

Also if the files presented have spaces or other characters they will need to be escaped for URL and if accessing a SMB share the file path will need to be unescaped.

$path = [System.IO.Path]::Combine($root, $path) ; $path = [uri]::UnescapeDataString($path)

!!Awesome code!! Tim-S

@KirtCarson
Copy link

#Change root accordingly.  I like sym links.
function GenIndexHtml {
$root='C:\Link\Link\';$Body = ls -r -file |%{ $UT8=$_ ; $_.fullname.replace($root,'') |%{ "<p><a href='http://192.168.0.100/"+[string]([uri]::EscapeUriString(($_.split('\\')|%{$_}) -join "/"))+"'/>$UT8</a></p>" } }
$IndexFileContent=@(); $IndexFileContent += "<html><head><title>Title</title></head><body>" ; $IndexFileContent +=$Body  ; $IndexFileContent += "</body><html>"
$IndexFileContent |sc index.html
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment