Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -9,4 +19,4 @@
* `DebugServer` (#5)
* `EventServer` (#6)
* `DualEventServer` (#7)

3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
68 changes: 68 additions & 0 deletions Servers/MethodSwitchServer.ps1
Original file line number Diff line number Diff line change
@@ -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='<h1>Hello World</h1>'}
}
)

$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.
4 changes: 2 additions & 2 deletions Servers/Server101.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -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.
Expand Down
74 changes: 74 additions & 0 deletions Servers/SwitchRegexServer.ps1
Original file line number Diff line number Diff line change
@@ -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='<h1>Hello World</h1>'}
}
)

$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) {
'/' {
"<h1>Home Sweet Home</h1>"
}
'/Hello/?' {
"<h1>Hello World</h1>"
}
'/(?<d1>[\d\.]+)x(?<d2>[\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.
14 changes: 11 additions & 3 deletions Servers101.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
RootModule = 'Servers101.psm1'

# Version number of this module.
ModuleVersion = '0.1'
ModuleVersion = '0.1.1'

# Supported PSEditions
# CompatiblePSEditions = @()
Expand Down Expand Up @@ -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
Expand All @@ -119,8 +129,6 @@ PrivateData = @{
* `DebugServer` (#5)
* `EventServer` (#6)
* `DualEventServer` (#7)


'@

# Prerelease string of this module
Expand Down
Loading