diff --git a/CHANGELOG.md b/CHANGELOG.md index c25ce90..13be87a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## Servers101 0.1.1: + +* New Servers: + * MethodSwitchServer (#9) + * SwitchRegexServer (#11) +* Fixed + * ContentType in Server101 (#10) + +--- + ## Servers101 0.1: * Initial Release of Servers101 @@ -9,4 +19,4 @@ * `DebugServer` (#5) * `EventServer` (#6) * `DualEventServer` (#7) - + diff --git a/README.md b/README.md index 75998a4..a420747 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,9 @@ Feel free to [contribute](contributing.md) and add your own. * [DebugServer.ps1](/Servers/DebugServer.ps1) * [DualEventServer.ps1](/Servers/DualEventServer.ps1) * [EventServer.ps1](/Servers/EventServer.ps1) +* [MethodSwitchServer.ps1](/Servers/MethodSwitchServer.ps1) * [Server101.ps1](/Servers/Server101.ps1) -* [SwitchServer.ps1](/Servers/SwitchServer.ps1) +* [SwitchRegexServer.ps1](/Servers/SwitchRegexServer.ps1) ## Using this module diff --git a/Servers/MethodSwitchServer.ps1 b/Servers/MethodSwitchServer.ps1 new file mode 100644 index 0000000..12b8e10 --- /dev/null +++ b/Servers/MethodSwitchServer.ps1 @@ -0,0 +1,68 @@ +<# +.SYNOPSIS + Method Switch Server +.DESCRIPTION + A simple server implemented in a single switch. + + Each HTTP Method is processed in a separate case. +.EXAMPLE + ./MethodSwitchServer.ps1 +#> +param( +# The rootUrl of the server. By default, a random loopback address. +[string]$RootUrl= + "http://127.0.0.1:$(Get-Random -Minimum 4200 -Maximum 42000)/", + +[Collections.IDictionary] +$Dictionary = [Ordered]@{ + "/" = @{ContentType='text/html';Content='

Hello World

'} +} +) + +$httpListener = [Net.HttpListener]::new() +$httpListener.Prefixes.Add($RootUrl) +Write-Warning "Listening on $RootUrl $($httpListener.Start())" + +$io = [Ordered]@{ # Pack our job input into an IO dictionary + HttpListener = $httpListener ; +} + +# Our server is a thread job +Start-ThreadJob -ScriptBlock {param([Collections.IDictionary]$io) + $psvariable = $ExecutionContext.SessionState.PSVariable + foreach ($key in $io.Keys) { # First, let's unpack. + if ($io[$key] -is [PSVariable]) { $psvariable.set($io[$key]) } + else { $psvariable.set($key, $io[$key]) } + } + + # Listen for the next request + :nextRequest while ($httpListener.IsListening) { + $getContext = $httpListener.GetContextAsync() + while (-not $getContext.Wait(17)) { } + $time = [DateTime]::Now + $request, $reply = + $getContext.Result.Request, $getContext.Result.Response + switch ($request.httpMethod) { + get { + $reply.Close( + $OutputEncoding.GetBytes( + "Getting $($request.Url)" + ), $false) + } + head { + $reply.ContentLength = 0 + $reply.Close() + } + default { + $timeToRespond = [DateTime]::Now - $time + $myReply = "$($request.HttpMethod) $($request.Url) $($timeToRespond)" + $reply.Close($OutputEncoding.GetBytes($myReply), $false) + } + } + } +} -ThrottleLimit 100 -ArgumentList $IO -Name "$RootUrl" | # Output our job, + Add-Member -NotePropertyMembers @{ # but attach a few properties first: + HttpListener=$httpListener # * The listener (so we can stop it) + IO=$IO # * The IO (so we can change it) + Url="$RootUrl" # The URL (so we can easily access it). + } -Force -PassThru # Pass all of that thru and return it to you. \ No newline at end of file diff --git a/Servers/Server101.ps1 b/Servers/Server101.ps1 index 17b2a6d..030d95b 100644 --- a/Servers/Server101.ps1 +++ b/Servers/Server101.ps1 @@ -70,7 +70,7 @@ Start-ThreadJob -ScriptBlock {param([Collections.IDictionary]$io) $reply.Length=$file.Length; $reply.Close(); continue nextRequest } filter outputFile { - $reply.ContentType = $contentTypes[$potentialPath] + $reply.ContentType = $contentTypes[$localPath] $fileStream = $file.OpenRead() $fileStream.CopyTo($reply.OutputStream) $fileStream.Close(); $fileStream.Dispose(); $reply.Close() @@ -88,7 +88,7 @@ Start-ThreadJob -ScriptBlock {param([Collections.IDictionary]$io) if ($method -notin 'get', 'head') { outputError 405 } # If the file does not exist, output error 404 if (-not ($files -and $files[$localPath])) { outputError 404 } - $file = $files[$request.Url.LocalPath] + $file = $files[$localPath] # If they asked for header information, output it. if ($request.httpMethod -eq 'head') { outputHeader } outputFile # otherwise, output the file. diff --git a/Servers/SwitchRegexServer.ps1 b/Servers/SwitchRegexServer.ps1 new file mode 100644 index 0000000..a25c254 --- /dev/null +++ b/Servers/SwitchRegexServer.ps1 @@ -0,0 +1,74 @@ +<# +.SYNOPSIS + Switch -RegEx Server +.DESCRIPTION + A simple server implemented in a single switch -regex. + + Any match can provide results. +.EXAMPLE + ./SwitchRegexServer.ps1 +#> +param( +# The rootUrl of the server. By default, a random loopback address. +[string]$RootUrl= + "http://127.0.0.1:$(Get-Random -Minimum 4200 -Maximum 42000)/", + +[Collections.IDictionary] +$Dictionary = [Ordered]@{ + "/" = @{ContentType='text/html';Content='

Hello World

'} +} +) + +$httpListener = [Net.HttpListener]::new() +$httpListener.Prefixes.Add($RootUrl) +Write-Warning "Listening on $RootUrl $($httpListener.Start())" + +$io = [Ordered]@{ # Pack our job input into an IO dictionary + HttpListener = $httpListener ; +} + +# Our server is a thread job +Start-ThreadJob -ScriptBlock {param([Collections.IDictionary]$io) + $psvariable = $ExecutionContext.SessionState.PSVariable + foreach ($key in $io.Keys) { # First, let's unpack. + if ($io[$key] -is [PSVariable]) { $psvariable.set($io[$key]) } + else { $psvariable.set($key, $io[$key]) } + } + + # Listen for the next request + :nextRequest while ($httpListener.IsListening) { + $getContext = $httpListener.GetContextAsync() + while (-not $getContext.Wait(17)) { } + $time = [DateTime]::Now + $request, $reply = + $getContext.Result.Request, $getContext.Result.Response + $result = $null + $result = + switch -regex ($request.Url.LocalPath) { + '/' { + "

Home Sweet Home

" + } + '/Hello/?' { + "

Hello World

" + } + '/(?[\d\.]+)x(?[\d\.]+)/?' { + ($matches.d1 -as [double]) * ($matches.d2 -as [double]) + } + default { + $timeToRespond = [DateTime]::Now - $time + "$($request.HttpMethod) $($request.Url) $($timeToRespond)" + } + } + if ($result) { + $reply.Close($OutputEncoding.GetBytes("$result"), $false) + } else { + $reply.StatusCode = 404 + $reply.Close() + } + } +} -ThrottleLimit 100 -ArgumentList $IO -Name "$RootUrl" | # Output our job, + Add-Member -NotePropertyMembers @{ # but attach a few properties first: + HttpListener=$httpListener # * The listener (so we can stop it) + IO=$IO # * The IO (so we can change it) + Url="$RootUrl" # The URL (so we can easily access it). + } -Force -PassThru # Pass all of that thru and return it to you. \ No newline at end of file diff --git a/Servers101.psd1 b/Servers101.psd1 index bb578c9..ee12d79 100644 --- a/Servers101.psd1 +++ b/Servers101.psd1 @@ -12,7 +12,7 @@ RootModule = 'Servers101.psm1' # Version number of this module. -ModuleVersion = '0.1' +ModuleVersion = '0.1.1' # Supported PSEditions # CompatiblePSEditions = @() @@ -108,6 +108,16 @@ PrivateData = @{ # ReleaseNotes of this module ReleaseNotes = @' +## Servers101 0.1.1: + +* New Servers: + * MethodSwitchServer (#9) + * SwitchRegexServer (#11) +* Fixed + * ContentType in Server101 (#10) + +--- + ## Servers101 0.1: * Initial Release of Servers101 @@ -119,8 +129,6 @@ PrivateData = @{ * `DebugServer` (#5) * `EventServer` (#6) * `DualEventServer` (#7) - - '@ # Prerelease string of this module