Skip to content

Commit 46cd4c4

Browse files
Merge pull request #12 from PowerShellWeb/servers102
Servers101 0.1.1
2 parents c30e50d + 11dec0a commit 46cd4c4

File tree

6 files changed

+168
-7
lines changed

6 files changed

+168
-7
lines changed

CHANGELOG.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
## Servers101 0.1.1:
2+
3+
* New Servers:
4+
* MethodSwitchServer (#9)
5+
* SwitchRegexServer (#11)
6+
* Fixed
7+
* ContentType in Server101 (#10)
8+
9+
---
10+
111
## Servers101 0.1:
212

313
* Initial Release of Servers101
@@ -9,4 +19,4 @@
919
* `DebugServer` (#5)
1020
* `EventServer` (#6)
1121
* `DualEventServer` (#7)
12-
22+

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ Feel free to [contribute](contributing.md) and add your own.
2424
* [DebugServer.ps1](/Servers/DebugServer.ps1)
2525
* [DualEventServer.ps1](/Servers/DualEventServer.ps1)
2626
* [EventServer.ps1](/Servers/EventServer.ps1)
27+
* [MethodSwitchServer.ps1](/Servers/MethodSwitchServer.ps1)
2728
* [Server101.ps1](/Servers/Server101.ps1)
28-
* [SwitchServer.ps1](/Servers/SwitchServer.ps1)
29+
* [SwitchRegexServer.ps1](/Servers/SwitchRegexServer.ps1)
2930

3031
## Using this module
3132

Servers/MethodSwitchServer.ps1

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<#
2+
.SYNOPSIS
3+
Method Switch Server
4+
.DESCRIPTION
5+
A simple server implemented in a single switch.
6+
7+
Each HTTP Method is processed in a separate case.
8+
.EXAMPLE
9+
./MethodSwitchServer.ps1
10+
#>
11+
param(
12+
# The rootUrl of the server. By default, a random loopback address.
13+
[string]$RootUrl=
14+
"http://127.0.0.1:$(Get-Random -Minimum 4200 -Maximum 42000)/",
15+
16+
[Collections.IDictionary]
17+
$Dictionary = [Ordered]@{
18+
"/" = @{ContentType='text/html';Content='<h1>Hello World</h1>'}
19+
}
20+
)
21+
22+
$httpListener = [Net.HttpListener]::new()
23+
$httpListener.Prefixes.Add($RootUrl)
24+
Write-Warning "Listening on $RootUrl $($httpListener.Start())"
25+
26+
$io = [Ordered]@{ # Pack our job input into an IO dictionary
27+
HttpListener = $httpListener ;
28+
}
29+
30+
# Our server is a thread job
31+
Start-ThreadJob -ScriptBlock {param([Collections.IDictionary]$io)
32+
$psvariable = $ExecutionContext.SessionState.PSVariable
33+
foreach ($key in $io.Keys) { # First, let's unpack.
34+
if ($io[$key] -is [PSVariable]) { $psvariable.set($io[$key]) }
35+
else { $psvariable.set($key, $io[$key]) }
36+
}
37+
38+
# Listen for the next request
39+
:nextRequest while ($httpListener.IsListening) {
40+
$getContext = $httpListener.GetContextAsync()
41+
while (-not $getContext.Wait(17)) { }
42+
$time = [DateTime]::Now
43+
$request, $reply =
44+
$getContext.Result.Request, $getContext.Result.Response
45+
switch ($request.httpMethod) {
46+
get {
47+
$reply.Close(
48+
$OutputEncoding.GetBytes(
49+
"Getting $($request.Url)"
50+
), $false)
51+
}
52+
head {
53+
$reply.ContentLength = 0
54+
$reply.Close()
55+
}
56+
default {
57+
$timeToRespond = [DateTime]::Now - $time
58+
$myReply = "$($request.HttpMethod) $($request.Url) $($timeToRespond)"
59+
$reply.Close($OutputEncoding.GetBytes($myReply), $false)
60+
}
61+
}
62+
}
63+
} -ThrottleLimit 100 -ArgumentList $IO -Name "$RootUrl" | # Output our job,
64+
Add-Member -NotePropertyMembers @{ # but attach a few properties first:
65+
HttpListener=$httpListener # * The listener (so we can stop it)
66+
IO=$IO # * The IO (so we can change it)
67+
Url="$RootUrl" # The URL (so we can easily access it).
68+
} -Force -PassThru # Pass all of that thru and return it to you.

Servers/Server101.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ Start-ThreadJob -ScriptBlock {param([Collections.IDictionary]$io)
7070
$reply.Length=$file.Length; $reply.Close(); continue nextRequest
7171
}
7272
filter outputFile {
73-
$reply.ContentType = $contentTypes[$potentialPath]
73+
$reply.ContentType = $contentTypes[$localPath]
7474
$fileStream = $file.OpenRead()
7575
$fileStream.CopyTo($reply.OutputStream)
7676
$fileStream.Close(); $fileStream.Dispose(); $reply.Close()
@@ -88,7 +88,7 @@ Start-ThreadJob -ScriptBlock {param([Collections.IDictionary]$io)
8888
if ($method -notin 'get', 'head') { outputError 405 }
8989
# If the file does not exist, output error 404
9090
if (-not ($files -and $files[$localPath])) { outputError 404 }
91-
$file = $files[$request.Url.LocalPath]
91+
$file = $files[$localPath]
9292
# If they asked for header information, output it.
9393
if ($request.httpMethod -eq 'head') { outputHeader }
9494
outputFile # otherwise, output the file.

Servers/SwitchRegexServer.ps1

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<#
2+
.SYNOPSIS
3+
Switch -RegEx Server
4+
.DESCRIPTION
5+
A simple server implemented in a single switch -regex.
6+
7+
Any match can provide results.
8+
.EXAMPLE
9+
./SwitchRegexServer.ps1
10+
#>
11+
param(
12+
# The rootUrl of the server. By default, a random loopback address.
13+
[string]$RootUrl=
14+
"http://127.0.0.1:$(Get-Random -Minimum 4200 -Maximum 42000)/",
15+
16+
[Collections.IDictionary]
17+
$Dictionary = [Ordered]@{
18+
"/" = @{ContentType='text/html';Content='<h1>Hello World</h1>'}
19+
}
20+
)
21+
22+
$httpListener = [Net.HttpListener]::new()
23+
$httpListener.Prefixes.Add($RootUrl)
24+
Write-Warning "Listening on $RootUrl $($httpListener.Start())"
25+
26+
$io = [Ordered]@{ # Pack our job input into an IO dictionary
27+
HttpListener = $httpListener ;
28+
}
29+
30+
# Our server is a thread job
31+
Start-ThreadJob -ScriptBlock {param([Collections.IDictionary]$io)
32+
$psvariable = $ExecutionContext.SessionState.PSVariable
33+
foreach ($key in $io.Keys) { # First, let's unpack.
34+
if ($io[$key] -is [PSVariable]) { $psvariable.set($io[$key]) }
35+
else { $psvariable.set($key, $io[$key]) }
36+
}
37+
38+
# Listen for the next request
39+
:nextRequest while ($httpListener.IsListening) {
40+
$getContext = $httpListener.GetContextAsync()
41+
while (-not $getContext.Wait(17)) { }
42+
$time = [DateTime]::Now
43+
$request, $reply =
44+
$getContext.Result.Request, $getContext.Result.Response
45+
$result = $null
46+
$result =
47+
switch -regex ($request.Url.LocalPath) {
48+
'/' {
49+
"<h1>Home Sweet Home</h1>"
50+
}
51+
'/Hello/?' {
52+
"<h1>Hello World</h1>"
53+
}
54+
'/(?<d1>[\d\.]+)x(?<d2>[\d\.]+)/?' {
55+
($matches.d1 -as [double]) * ($matches.d2 -as [double])
56+
}
57+
default {
58+
$timeToRespond = [DateTime]::Now - $time
59+
"$($request.HttpMethod) $($request.Url) $($timeToRespond)"
60+
}
61+
}
62+
if ($result) {
63+
$reply.Close($OutputEncoding.GetBytes("$result"), $false)
64+
} else {
65+
$reply.StatusCode = 404
66+
$reply.Close()
67+
}
68+
}
69+
} -ThrottleLimit 100 -ArgumentList $IO -Name "$RootUrl" | # Output our job,
70+
Add-Member -NotePropertyMembers @{ # but attach a few properties first:
71+
HttpListener=$httpListener # * The listener (so we can stop it)
72+
IO=$IO # * The IO (so we can change it)
73+
Url="$RootUrl" # The URL (so we can easily access it).
74+
} -Force -PassThru # Pass all of that thru and return it to you.

Servers101.psd1

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
RootModule = 'Servers101.psm1'
1313

1414
# Version number of this module.
15-
ModuleVersion = '0.1'
15+
ModuleVersion = '0.1.1'
1616

1717
# Supported PSEditions
1818
# CompatiblePSEditions = @()
@@ -108,6 +108,16 @@ PrivateData = @{
108108

109109
# ReleaseNotes of this module
110110
ReleaseNotes = @'
111+
## Servers101 0.1.1:
112+
113+
* New Servers:
114+
* MethodSwitchServer (#9)
115+
* SwitchRegexServer (#11)
116+
* Fixed
117+
* ContentType in Server101 (#10)
118+
119+
---
120+
111121
## Servers101 0.1:
112122
113123
* Initial Release of Servers101
@@ -119,8 +129,6 @@ PrivateData = @{
119129
* `DebugServer` (#5)
120130
* `EventServer` (#6)
121131
* `DualEventServer` (#7)
122-
123-
124132
'@
125133

126134
# Prerelease string of this module

0 commit comments

Comments
 (0)