forked from dispatchframework/powershell-base-image
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ps1
138 lines (107 loc) · 4.51 KB
/
index.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
Param(
[Parameter(Mandatory=$True, Position=0)]
[string]$handler
)
$scriptFile, $func = $handler.split('::')
. $PSScriptRoot\function\$scriptFile
Set-Variable INPUT_ERROR -option Constant -value "InputError"
Set-Variable FUNCTION_ERROR -option Constant -value "FunctionError"
Set-Variable SYSTEM_ERROR -option Constant -value "SystemError"
# Takes HttpListenerRequest and returns request body
function getRequestBody($request) {
[System.IO.StreamReader]$reader = [System.IO.StreamReader]::new($request.InputStream, $request.ContentEncoding)
$in = $reader.ReadToEnd() | ConvertFrom-Json
$reader.Close()
return $in
}
function collectLogs($output) {
# Contains Write-Host, Write-Information, Write-Verbose, Write-Debug
[System.Collections.Generic.List[String]]$stdout = $output | ?{ $_ -isnot [System.Management.Automation.ErrorRecord] -and $_ -isnot [System.Management.Automation.WarningRecord] }
if ($stdout -eq $null) {
$stdout = @()
}
# Contains Write-Error, Write-Warning
[System.Collections.Generic.List[String]]$stderr = $output | ?{ $_ -is [System.Management.Automation.ErrorRecord] -or $_ -is [System.Management.Automation.WarningRecord] }
if ($stderr -eq $null) {
$stderr = @()
}
return @{stderr=$stderr; stdout=$stdout}
}
# Standard error message displayed when exception encountered
function getErrorMessage($err) {
$errorMessage = $err | Out-String
$errorMessage = $errorMessage.Trim()
return $errorMessage.Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries)
}
function applyFunction($in, $handle) {
# Capture Debug and Verbose from function
$DebugPreference = 'Continue'
$VerbosePreference = 'Continue'
try {
# Run the function and get the result and output (contains all output streams)
$output = $($result = & $handle $in.context $in.payload) *>&1
} catch [System.ArgumentException] {
$stderr = getErrorMessage $_
$stacktrace = $_.ScriptStackTrace.Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries)
$err = @{type=$INPUT_ERROR; message=$_.Exception.Message; stacktrace=$stacktrace}
} catch {
$stderr = getErrorMessage $_
$stacktrace = $_.ScriptStackTrace.Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries)
$err = @{type=$FUNCTION_ERROR; message=$_.Exception.Message; stacktrace=$stacktrace}
} finally {
# Set back to default values
$DebugPreference = 'SilentlyContinue'
$VerbosePreference = 'SilentlyContinue'
$logs = collectLogs $output
# If encounter error, append error message to stderr
if ($err -ne $null) {
$logs.stderr += $stderr
}
$r = @{context=@{logs=$logs; error=$err}; payload=$result}
}
return $r
}
function processRequest($request) {
try {
$in = getRequestBody $request
} catch {
$stderr = getErrorMessage $_
$stacktrace = $_.ScriptStackTrace.Split([Environment]::NewLine, [System.StringSplitOptions]::RemoveEmptyEntries)
$err = @{type=$SYSTEM_ERROR; message=$_.Exception.Message; stacktrace=$stacktrace}
return @{context=@{logs=@{stderr=$stderr; stdout=@()}; error=$err}; payload=$null}
}
return applyFunction $in $func
}
# If this script is not imported
if ($MyInvocation.Line.Trim() -notmatch '^\.\s+') {
# Create a listener on port 8000
$listener = New-Object System.Net.HttpListener
$listener.Prefixes.Add('http://+:8080/')
$listener.Start()
'PowerShell Runtime API Listening ...'
# Run until you send a GET request to /end
while ($true) {
$context = $listener.GetContext()
# Capture the details about the request
$request = $context.Request
# Setup a place to deliver a response
$response = $context.Response
if ($request.Url -match '/healthz$') {
$message = '{}';
} else {
$r = processRequest $request
$message = $r | ConvertTo-Json -Compress -Depth 3
}
$response.ContentType = 'application/json'
# Convert the data to UTF8 bytes
[byte[]]$buffer = [System.Text.Encoding]::UTF8.GetBytes($message)
# Set length of response
$response.ContentLength64 = $buffer.length
# Write response out and close
$output = $response.OutputStream
$output.Write($buffer, 0, $buffer.length)
$output.Close()
}
#Terminate the listener
$listener.Stop()
}