Implements a RequestDelegate for executing PowerShell scripts
The scripts are executed in a new PowerShell per request. The pipelines are connected to the request and response bodies.
param(
[parameter(Mandatory=$true)]
$HttpContext
)
$Response=$HttpContext.Response
$Response.StatusCode=200
$Response.ContentType='text/plain'
[System.Text.Encoding]::ASCII
'Hello World'
Writing the ASCII encoding to the output allows control of the encoding.
param(
[parameter(Mandatory=$true)]
$HttpContext,
[parameter(ValueFromPipeline=$true,Mandatory=$true)]
$pipelineInput
)
$Response=$HttpContext.Response
$Response.StatusCode=200
$Response.ContentType=$HttpContext.Request.ContentType
Write-Output $pipelineInput -NoEnumerate
The -NoEnumerate is to write a byte array rather than individual bytes onto the pipeline.
The delegate uses the asynchronous programming model in order to allow overlapping of both input and output.
An InitialSessionState can be used to provide state that will be shared by each request invocation.
The request body is fed into to the input pipeline. The input can either be an IFormCollection, a byte array or a string depending on the Content-Type.
The output pipeline is written to the response body. The output is written as the objects are added to the pipeline. Only primitives that can be converted to characters or bytes are supported. An Encoding type will set the current character encoding.
The response status and any headers should be applied to the HttpContext before the output is written.
The HttpRequest.RequestAborted is forwarded to the PowerShell.StopAsync to cancel long running pipelines when client has disconnected and response is no longer possible.
The code includes some hopefully interesting techniques
PowerShelldelegate uses asynchronous programming to simultaneously read and write the input and output pipelines while executing thePowerShellscript without using threads; see PowerShellDelegate/PowerShellDelegate.cs- Test harness uses
WebApplicationFactorywith top-level programs; see UnitTests/WebApplicationFactoryBuilder.cs - Generates native packages to install matching
AspNetCoreruntime; see AspNetForPowerShell/package.ps1 PowerShellcan be used at different levels;- Standalone app; see DemoApp/DemoApp.ps1
- Main
Program; see TestPs1/Program.ps1 Startupconfiguration; see TestEol/Startup.ps1RequestDelegatehandler; see TestCgi/RequestDelegate.ps1
- Combining with
Controllers; see TestApi/Program.cs - Combining with static content; see TestCgi/Program.cs
- Access resources from
PowerShell; see TestEol/Startup.ps1 - Get services by type, eg
ILogger; TestPs1/Program.ps1 - Extension to add
CmdletstoInitialSessionState; see Extensions/InitialSessionStateExtensions.cs - Using unit tests to validate
PowerShellimplementation; see UnitTests/TestPs1Tests.cs