151 lines
4.9 KiB
PowerShell
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
|
|
}
|
|
}
|
|
} |