@@ -188,8 +188,9 @@ function Get-WebSocket {
188188 [Collections.IDictionary ]
189189 $QueryParameter ,
190190
191- # A ScriptBlock that will handle the output of the WebSocket.
192- [Parameter (ParameterSetName = ' WebSocketServer' )]
191+ # A ScriptBlock that can handle the output of the WebSocket or the Http Request.
192+ # This may be run in a separate `-Runspace` or `-RunspacePool`.
193+ # The output of the WebSocket or the Context will be passed as an object.
193194 [ScriptBlock ]
194195 $Handler ,
195196
@@ -222,6 +223,9 @@ function Get-WebSocket {
222223 [int ]
223224 $BufferSize = 64 kb ,
224225
226+ # If provided, will send an object.
227+ # If this is a scriptblock, it will be run and the output will be sent.
228+ [Alias (' Send' )]
225229 [PSObject ]
226230 $Broadcast ,
227231
@@ -352,13 +356,13 @@ function Get-WebSocket {
352356
353357 # The Runspace where the handler should run.
354358 # Runspaces allow you to limit the scope of the handler.
355- [Parameter (ValueFromPipelineByPropertyName , ParameterSetName = ' WebSocketClient ' )]
359+ [Parameter (ValueFromPipelineByPropertyName )]
356360 [Runspace ]
357361 $Runspace ,
358362
359363 # The RunspacePool where the handler should run.
360364 # RunspacePools allow you to limit the scope of the handler to a pool of runspaces.
361- [Parameter (ValueFromPipelineByPropertyName , ParameterSetName = ' WebSocketClient ' )]
365+ [Parameter (ValueFromPipelineByPropertyName )]
362366 [Management.Automation.Runspaces.RunspacePool ]
363367 [Alias (' Pool' )]
364368 $RunspacePool
@@ -913,6 +917,7 @@ function Get-WebSocket {
913917 MessageQueue = [Collections.Queue ]::new()
914918 MessageCount = [long ]0
915919 }
920+
916921 if (-not $httpListener.SocketRequests [" $ ( $webSocketResult.RequestUri ) " ]) {
917922 $httpListener.SocketRequests [" $ ( $webSocketResult.RequestUri ) " ] = [Collections.Queue ]::new()
918923 }
@@ -964,6 +969,40 @@ function Get-WebSocket {
964969 }
965970 }
966971
972+ if (-not $routedTo -and $handler ) {
973+ # If we have an output handler, try to run it and get the output
974+ $routedTo = if ($handler ) {
975+ # We may need to run the handler in a `[PowerShell]` command.
976+ $psCmd =
977+ # This is true if we want `NoLanguage` mode.
978+ if ($runspace.LanguageMode -eq ' NoLanguage' -or
979+ $runspacePool.InitialSessionState.LanguageMode -eq ' NoLanguage' ) {
980+ # (in which case we'll call .GetPowerShell())
981+ $handler.GetPowerShell ()
982+ } elseif (
983+ # or if we have a runspace or runspace pool
984+ $Runspace -or $RunspacePool
985+ ) {
986+ # (in which case we'll `.Create()` and `.AddScript()`)
987+ [PowerShell ]::Create().AddScript($handler , $true )
988+ }
989+ if ($psCmd ) {
990+ # If we have a runspace, we'll use that.
991+ if ($Runspace ) {
992+ $psCmd.Runspace = $Runspace
993+ } elseif ($RunspacePool ) {
994+ # or, alternatively, we can use a runspace pool.
995+ $psCmd.RunspacePool = $RunspacePool
996+ }
997+ # Now, we can invoke the command.
998+ $psCmd.Invoke (@ ($context ))
999+ } else {
1000+ # Otherwise, we'll just run the handler.
1001+ $context | . $handler
1002+ }
1003+ }
1004+ }
1005+
9671006 if (-not $routedTo -and $html ) {
9681007 $routedTo =
9691008 # If the content is already html, we will use it as is.
@@ -1170,33 +1209,7 @@ function Get-WebSocket {
11701209 if (-not $Broadcast ) {
11711210 $httpListenerJob
11721211 }
1173- }
1174-
1175- if ($Broadcast ) {
1176- if (-not $httpListener.SocketRequests ) {
1177- Write-Warning " No WebSocket connections to broadcast to."
1178- } else {
1179- if ($broadcast -is [byte []]) {
1180- $broadcast = [ArraySegment [byte ]]::new($broadcast )
1181- }
1182- if ($broadcast -is [System.ArraySegment [byte ]]) {
1183- foreach ($socketRequest in @ ($httpListener.SocketRequests.Values )) {
1184- $socketRequest.WebSocket.SendAsync ($broadcast , ' Binary' , ' EndOfMessage' , [Threading.CancellationToken ]::None)
1185- }
1186- }
1187- else {
1188- foreach ($broadcastItem in $Broadcast ) {
1189- $broadcastJson = ConvertTo-Json - InputObject $broadcastItem
1190- $broadcastJsonBytes = $OutputEncoding.GetBytes ($broadcastJson )
1191- $broadcastSegment = [ArraySegment [byte ]]::new($broadcastJsonBytes )
1192- foreach ($socketRequest in @ ($httpListener.SocketRequests.Values | . { process { $_ } })) {
1193- $socketRequest.WebSocket.SendAsync ($broadcastSegment , ' Text' , ' EndOfMessage' , [Threading.CancellationToken ]::None)
1194- }
1195- }
1196- }
1197- }
1198-
1199- }
1212+ }
12001213 }
12011214
12021215 # If `-Debug` was passed,
@@ -1267,7 +1280,58 @@ function Get-WebSocket {
12671280 )
12681281 }
12691282 $webSocketJob.pstypenames.insert (0 , ' WebSocket.ThreadJob' )
1270- }
1283+ }
1284+
1285+ # If we're broadcasting a message
1286+ if ($Broadcast ) {
1287+ # find out who is listening.
1288+ $socketList = @ (
1289+ if ($httpListener.SocketRequests ) {
1290+ @ (foreach ($queue in $httpListener.SocketRequests.Values ) {
1291+ foreach ($socket in $queue ) {
1292+ if ($socket.WebSocket.State -eq ' Open' ) {
1293+ $socket.WebSocket
1294+ }
1295+ }
1296+ })
1297+ }
1298+ if ($webSocketJob.WebSocket ) {
1299+ $webSocketJob.WebSocket
1300+ }
1301+ )
1302+
1303+ # If no one is listening, write a warning.
1304+ if (-not $socketList ) {
1305+ Write-Warning " No one is listening"
1306+ }
1307+
1308+ # If the broadcast is a scriptblock or command, run it.
1309+ if ($Broadcast -is [ScriptBlock ] -or
1310+ $Broadcast -is [Management.Automation.CommandInfo ]) {
1311+ $Broadcast = & $Broadcast
1312+ }
1313+ # If the broadcast is a byte array, convert it to an array segment.
1314+ if ($broadcast -is [byte []]) {
1315+ $broadcast = [ArraySegment [byte ]]::new($broadcast )
1316+ }
1317+
1318+ # If the broadcast is an array segment, send it as binary.
1319+ if ($broadcast -is [ArraySegment [byte ]]) {
1320+ foreach ($socket in $socketList ) {
1321+ $null = $socket.SendAsync ($broadcast , ' Binary' , ' EndOfMessage' , [Threading.CancellationToken ]::None)
1322+ }
1323+ }
1324+ else {
1325+ # Otherwise, convert the broadcast to JSON.
1326+ $broadcastJson = ConvertTo-Json - InputObject $Broadcast
1327+ $broadcastJsonBytes = $OutputEncoding.GetBytes ($broadcastJson )
1328+ $broadcastSegment = [ArraySegment [byte ]]::new($broadcastJsonBytes )
1329+ foreach ($socket in $socketList ) {
1330+ $null = $socket.SendAsync ($broadcastSegment , ' Text' , ' EndOfMessage' , [Threading.CancellationToken ]::None)
1331+ }
1332+ }
1333+ $Broadcast # emit the broadcast.
1334+ }
12711335
12721336 if ($Watch -and $webSocketJob ) {
12731337 do {
@@ -1303,8 +1367,8 @@ function Get-WebSocket {
13031367 }
13041368 }
13051369 }
1306- }
1307- elseif ($webSocketJob ) {
1370+ }
1371+ elseif ($webSocketJob -and -not $broadcast ) {
13081372 $webSocketJob
13091373 }
13101374 }
0 commit comments