sdk-powershell/test/integration/HttpServer.ps1

151 lines
4.9 KiB
PowerShell

# **************************************************************************
# Copyright (c) Cloud Native Foundation.
# SPDX-License-Identifier: Apache-2.0
# **************************************************************************
param(
[Parameter(Mandatory = $true)]
[ValidateScript({Test-Path $_})]
[string]
$CloudEventsModulePath,
[Parameter(
Mandatory = $true,
ValueFromPipeline = $false,
ValueFromPipelineByPropertyName = $false)]
[ValidateNotNull()]
[string]
$ServerUrl
)
. (Join-Path $PSScriptRoot 'ProtocolConstants.ps1')
# Import SDK Module
Import-Module $CloudEventsModulePath
function Start-HttpCloudEventListener {
<#
.DESCRIPTION
Starts a HTTP CloudEvent Listener on specified Url
#>
[CmdletBinding()]
param(
[Parameter(
Mandatory = $true,
ValueFromPipeline = $false,
ValueFromPipelineByPropertyName = $false)]
[ValidateNotNull()]
[string]
$Url,
[Parameter(
Mandatory = $false,
ValueFromPipeline = $false,
ValueFromPipelineByPropertyName = $false)]
[scriptblock]
$Handler
)
$listener = New-Object -Type 'System.Net.HttpListener'
$listener.AuthenticationSchemes = [System.Net.AuthenticationSchemes]::Anonymous
$listener.Prefixes.Add($Url)
try {
$listener.Start()
$context = $listener.GetContext()
# Read Input Stream
$buffer = New-Object 'byte[]' -ArgumentList 1024
$ms = New-Object 'IO.MemoryStream'
$read = 0
while (($read = $context.Request.InputStream.Read($buffer, 0, 1024)) -gt 0) {
$ms.Write($buffer, 0, $read);
}
$bodyData = $ms.ToArray()
$ms.Dispose()
# Read Headers
$headers = @{}
for($i =0; $i -lt $context.Request.Headers.Count; $i++) {
$headers[$context.Request.Headers.GetKey($i)] = $context.Request.Headers.GetValues($i)
}
$cloudEvent = ConvertFrom-HttpMessage -Headers $headers -Body $bodyData
if ( $cloudEvent -ne $null ) {
$Handler.Invoke($cloudEvent, $context.Response)
$context.Response.Close();
} else {
$context.Response.StatusCode = [int]([System.Net.HttpStatusCode]::BadRequest)
$context.Response.Close();
}
} catch {
Write-Error $_
$context.Response.StatusCode = [int]([System.Net.HttpStatusCode]::InternalServerError)
$context.Response.Close();
} finally {
$listener.Stop()
}
}
$global:serverStopRequested = $false
while ( -not $global:serverStopRequested ) {
Start-HttpCloudEventListener -Url $ServerUrl -Handler {
$requestCloudEvent = $args[0]
$response = $args[1]
# When CloudEvent Type is 'echo-structured' or 'echo-binary' the Server responds
# with CloudEvent in corresponding content mode
if ( $requestCloudEvent.Type -eq $script:EchoBinaryType -or `
$requestCloudEvent.Type -eq $script:EchoStructuredType ) {
# Create Cloud Event for the response
$cloudEvent = New-CloudEvent `
-Type $requestCloudEvent.Type `
-Source $script:ServerSource `
-Time (Get-Date) `
-Id $requestCloudEvent.Id
# Add Data to the new Cloud Event
$requestCloudEventJsonData = $requestCloudEvent | Read-CloudEventJsonData
$requestCloudEventXmlData = $requestCloudEvent | Read-CloudEventXmlData -ConvertMode 'SkipAttributes'
if ($requestCloudEventJsonData) {
$cloudEvent = $cloudEvent | Add-CloudEventJsonData `
-Data $requestCloudEventJsonData
} elseif ($requestCloudEventXmlData) {
$cloudEvent = $cloudEvent | Add-CloudEventXmlData `
-Data $requestCloudEventXmlData `
-AttributesKeysInElementAttributes $false
} else {
$requestCloudEventData = $requestCloudEvent | Read-CloudEventData
$cloudEvent = $cloudEvent | Add-CloudEventData `
-Data $requestCloudEventData `
-DataContentType $requestCloudEvent.DataContentType
}
# Convert Cloud Event to HTTP Response
$contentMode = $requestCloudEvent.Type.TrimStart('echo-')
$httpMessage = $cloudEvent | ConvertTo-HttpMessage -ContentMode $contentMode
$response.Headers = New-Object 'System.Net.WebHeaderCollection'
foreach ($keyValue in $httpMessage.Headers.GetEnumerator()) {
$response.Headers.Add($keyValue.Key, $keyValue.Value)
}
$response.ContentLength64 = $httpMessage.Body.Length
$response.OutputStream.Write($httpMessage.Body, 0, $httpMessage.Body.Length)
$response.StatusCode = [int]([System.Net.HttpStatusCode]::OK)
} else {
# No Content in all other cases
$response.StatusCode = [int]([System.Net.HttpStatusCode]::NoContent)
}
if ( $requestCloudEvent.Type -eq $script:ServerStopType ) {
# Server Stop is requested
$global:serverStopRequested = $true
}
}
}