CloudEvents.Sdk.psm1
# ************************************************************************** # Copyright (c) Cloud Native Foundation. # SPDX-License-Identifier: Apache-2.0 # ************************************************************************** $xmlDataSerilizationLibPath = Join-Path (Join-Path $PSScriptRoot 'dataserialization') 'xml.ps1' . $xmlDataSerilizationLibPath function New-CloudEvent { <# .SYNOPSIS This function creates a new cloud event. .DESCRIPTION This function creates a new cloud event object with the provided parameters. The result cloud event object has no data. Use Add-CloudEvent* functions to add data to the cloud event object. .PARAMETER Type Specifies the 'type' attribute of the cloud event. .PARAMETER Source Specifies the 'source' attribute of the cloud event. .PARAMETER Id Specifies the 'id' attribute of the cloud event. .PARAMETER Time Specifies the 'time' attribute of the cloud event. .EXAMPLE New-CloudEvent -Type 'com.example.object.deleted.v2' -Source 'mailto:cncf-wg-serverless@lists.cncf.io' -Id '6e8bc430-9c3a-11d9-9669-0800200c9a66' -Time (Get-Date) Creates a cloud event with Type, Source, Id, and Time #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $Type, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [System.Uri] $Source, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string] $Id, [Parameter(Mandatory = $false)] [ValidateNotNullOrEmpty()] [DateTime] $Time ) PROCESS { $cloudEvent = New-Object ` -TypeName 'CloudNative.CloudEvents.CloudEvent' ` -ArgumentList @( $Type, $Source, $Id, $Time, @()) Write-Output $cloudEvent } } #region Set Data Functions function Set-CloudEventData { <# .SYNOPSIS This function sets data in a cloud event. .DESCRIPTION This function sets data in a cloud event object with the provided parameters. .PARAMETER CloudEvent Specifies the cloud event object that receives the data. .PARAMETER Data Specifies the data object for the cloud event 'data' attribute. .PARAMETER DataContentType Specifies the 'datacontenttype' attribute of the cloud event. .EXAMPLE $cloudEvent = New-CloudEvent -Type 'com.example.object.deleted.v2' -Source 'mailto:cncf-wg-serverless@lists.cncf.io' -Id '6e8bc430-9c3a-11d9-9669-0800200c9a66' -Time (Get-Date) $cloudEvent | Set-CloudEventData -Data '<much wow="xml"/>' -DataContentType 'application/xml' Sets xml data to the cloud event #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [CloudNative.CloudEvents.CloudEvent] $CloudEvent, [Parameter(Mandatory = $true, ValueFromPipeline = $false)] [ValidateNotNullOrEmpty()] [object] $Data, # CloudEvent 'datacontenttype' attribute. Content type of the 'data' attribute value. # This attribute enables the data attribute to carry any type of content, whereby # format and encoding might differ from that of the chosen event format. [Parameter(Mandatory = $false, ValueFromPipeline = $false)] [string] $DataContentType) PROCESS { # https://github.com/cloudevents/spec/blob/master/spec.md#datacontenttype $contentType = New-Object ` -TypeName 'System.Net.Mime.ContentType' ` -ArgumentList ($DataContentType) $cloudEvent.Data = $Data $cloudEvent.DataContentType = $dataContentType Write-Output $CloudEvent } } function Set-CloudEventJsonData { <# .SYNOPSIS This function sets JSON format data in a cloud event. .DESCRIPTION This function converts a PowerShell hashtable to JSON format data and sets it in a cloud event. .PARAMETER CloudEvent Specifies the cloud event object that receives the data. .PARAMETER Data Specifies the PowerShell hashtable object that is set as JSON on the cloud event 'data' attribute. The 'datacontenttype' attribute is set to 'application/json' .PARAMETER Depth The maximum depth of the input hashtable specified on the `Data` parameter that will be converted to JSON. This parameter is passed on the `-Depth` parameter of the `ConvertTo-Json` cmdlet. The default value is 3 .EXAMPLE $cloudEvent = New-CloudEvent -Type 'com.example.object.deleted.v2' -Source 'mailto:cncf-wg-serverless@lists.cncf.io' -Id '6e8bc430-9c3a-11d9-9669-0800200c9a66' -Time (Get-Date) $cloudEvent | Set-CloudEventJsonData -Data @{ 'key1' = 'value1'; 'key2' = 'value2'; } Sets JSON data to the cloud event #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [CloudNative.CloudEvents.CloudEvent] $CloudEvent, [Parameter(Mandatory = $true, ValueFromPipeline = $false)] [ValidateNotNull()] [Hashtable] $Data, [Parameter(Mandatory = $false, ValueFromPipeline = $false)] [int] $Depth = 3) PROCESS { # DataContentType is set to 'application/json' # https://github.com/cloudevents/spec/blob/master/spec.md#datacontenttype $dataContentType = New-Object ` -TypeName 'System.Net.Mime.ContentType' ` -ArgumentList ([System.Net.Mime.MediaTypeNames+Application]::Json) $cloudEvent.DataContentType = $dataContentType $cloudEvent.Data = ConvertTo-Json -InputObject $Data -Depth $Depth Write-Output $CloudEvent } } function Set-CloudEventXmlData { <# .SYNOPSIS This function sets XML format data in a cloud event. .DESCRIPTION This function converts a PowerShell hashtable to XML format data and sets it in a cloud event. .PARAMETER CloudEvent Specifies the cloud event object that receives the data. .PARAMETER Data Specifies the PowerShell hashtable object that is set as XML on the cloud event 'data' attribute. The 'datacontenttype' attribute is set to 'application/xml' .PARAMETER AttributesKeysInElementAttributes Specifies how to format the XML. If specified and the input Data hashtable has pairs of 'Attributes', 'Value' keys creates XML element with attributes, otherwise each key is formatted as XML element. If true @{'root' = @{'Attributes' = @{'att1' = 'true'}; 'Value' = 'val-1'}} would be '<root att1="true">val-1</root>' Otherwise @{'root' = @{'Attributes' = @{'att1' = 'true'}; 'Value' = 'val-1'}} would be '<root><Attributes><att1>true</att1></Attributes><Value>val-1</Value></root>' .EXAMPLE $cloudEvent = New-CloudEvent -Type 'com.example.object.deleted.v2' -Source 'mailto:cncf-wg-serverless@lists.cncf.io' -Id '6e8bc430-9c3a-11d9-9669-0800200c9a66' -Time (Get-Date) $cloudEvent | Set-CloudEventXmlData -Data @{ 'key1' = 'value1'; 'key2' = 'value2'; } -AttributesKeysInElementAttributes $true Sets XML data in the cloud event #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [CloudNative.CloudEvents.CloudEvent] $CloudEvent, [Parameter(Mandatory = $true, ValueFromPipeline = $false)] [ValidateNotNull()] [Hashtable] $Data, [Parameter(Mandatory = $true)] [bool] $AttributesKeysInElementAttributes) PROCESS { # DataContentType is set to 'application/xml' $dataContentType = New-Object ` -TypeName 'System.Net.Mime.ContentType' ` -ArgumentList ([System.Net.Mime.MediaTypeNames+Application]::Xml) $cloudEvent.DataContentType = $dataContentType $cloudEvent.Data = ConvertTo-CEDataXml -InputObject $Data -AttributesKeysInElementAttributes $AttributesKeysInElementAttributes Write-Output $CloudEvent } } #endregion Set Data Functions #region Read Data Functions function Read-CloudEventData { <# .SYNOPSIS This function gets the data from a cloud event. .DESCRIPTION This function gets the data as-is from a cloud event. It is equiualent of accessing the Data property of a CloudEvent object .PARAMETER CloudEvent Specifies the cloud event object to get data from. .EXAMPLE $cloudEvent = ConvertFrom-HttpMessage -Headers $httpResponse.Headers -Body $httpResponse.Content $cloudEvent | Read-CloudEventData Reads data from a cloud event received on the http response #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [CloudNative.CloudEvents.CloudEvent] $CloudEvent ) PROCESS { Write-Output $CloudEvent.Data } } function Read-CloudEventJsonData { <# .SYNOPSIS This function gets JSON fromat data from a cloud event as a PowerShell hashtable. .DESCRIPTION This function gets the data from a cloud event and converts it to a PowerShell hashtable. If the cloud event datacontenttype is not 'application/json' nothing is returned. .PARAMETER CloudEvent Specifies the cloud event object to get data from. .PARAMETER Depth Specifies how many levels of contained objects are included in the JSON representation. The default value is 3. .EXAMPLE $cloudEvent = ConvertFrom-HttpMessage -Headers $httpResponse.Headers -Body $httpResponse.Content $hashtable = $cloudEvent | Read-CloudEventJsonData Reads JSON data as a hashtable from a cloud event received on the http response #> <# .DESCRIPTION Returns PowerShell hashtable that represents the CloudEvent Json Data if the data content type is 'application/json', otherwise otherwise non-terminating error and no result #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [CloudNative.CloudEvents.CloudEvent] $CloudEvent, [Parameter(Mandatory = $false, ValueFromPipeline = $false)] [int] $Depth = 3 ) PROCESS { # DataContentType is expected to be 'application/json' # https://github.com/cloudevents/spec/blob/master/spec.md#datacontenttype $dataContentType = New-Object ` -TypeName 'System.Net.Mime.ContentType' ` -ArgumentList ([System.Net.Mime.MediaTypeNames+Application]::Json) if ($CloudEvent.DataContentType -eq $dataContentType -or ` ($CloudEvent.DataContentType -eq $null -and # Datacontent Type is Optional, if it is not specified we assume it is JSON as per https://github.com/cloudevents/spec/blob/v1.0.1/spec.md#datacontenttype $cloudEvent.Data -is [Newtonsoft.Json.Linq.JObject])) { $data = $cloudEvent.Data if ($cloudEvent.Data -is [byte[]]) { $data = [System.Text.Encoding]::UTF8.GetString($data) } $result = $data.ToString() | ConvertFrom-Json -AsHashtable -Depth $Depth Write-Output $result } else { Write-Error "Cloud Event '$($cloudEvent.Id)' has no json data" } } } function Read-CloudEventXmlData { <# .SYNOPSIS This function gets XML fromat data from a cloud event as a PowerShell hashtable. .DESCRIPTION This function gets the data from a cloud event and converts it to a PowerShell hashtable. If the cloud event datacontenttype is not 'application/xml' nothing is returned. .PARAMETER CloudEvent Specifies the cloud event object to get data from. .PARAMETER ConvertMode Specifies the how to convert the xml data to a hashtable 'SkipAttributes' - Skips attributes of the XML elements. XmlElement is represented as a Key-Value pair where key is the xml element name, and the value is the xml element inner text Example: "<key att='true'>value1</key>" is converted to @{'key' = 'value-1'} 'AlwaysAttrValue' - Each element is represented as a hashtable with two keys 'Attributes' - key-value pair of the cml element attributes if any, otherwise null 'Value' - string value represinting the xml element inner text Example: "<key1 att='true'>value1</key1><key2>value2</key2>" is converted to @{ 'key1' = @{ 'Attributes' = @{ 'att' = 'true' } 'Value' = 'value1' } 'key2' = @{ 'Attributes' = $null 'Value' = 'value2' } } 'AttrValueWhenAttributes' - Uses 'SkipAttributes' for xml elements without attributes and 'AlwaysAttrValue' for xml elements with attributes Example: "<key1 att='true'>value1</key1><key2>value2</key2>" is converted to @{ 'key1' = @{ 'Attributes' = @{ 'att' = 'true' } 'Value' = 'value1' } 'key2' = 'value2' } .EXAMPLE $cloudEvent = ConvertFrom-HttpMessage -Headers $httpResponse.Headers -Body $httpResponse.Content $hashtable = $cloudEvent | Read-CloudEventXmlData -ConvertMode AttrValueWhenAttributes Reads XML data as a hashtable from a cloud event received on the http response #> <# .DESCRIPTION Returns PowerShell hashtable that represents the CloudEvent Xml Data if the data content type is 'application/xml', otherwise non-terminating error and no result #> [CmdletBinding()] param( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [ValidateNotNullOrEmpty()] [CloudNative.CloudEvents.CloudEvent] $CloudEvent, [Parameter(Mandatory = $true)] [ValidateSet("SkipAttributes", "AlwaysAttrValue", "AttrValueWhenAttributes")] [string] $ConvertMode ) PROCESS { # DataContentType is expected to be 'application/xml' $dataContentType = New-Object ` -TypeName 'System.Net.Mime.ContentType' ` -ArgumentList ([System.Net.Mime.MediaTypeNames+Application]::Xml) if ($CloudEvent.DataContentType -eq $dataContentType) { $data = $cloudEvent.Data if ($cloudEvent.Data -is [byte[]]) { $data = [System.Text.Encoding]::UTF8.GetString($data) } $result = $data.ToString() | ConvertFrom-CEDataXml -ConvertMode $ConvertMode Write-Output $result } else { Write-Error "Cloud Event '$($cloudEvent.Id)' has no xml data" } } } #endregion Read Data Functions #region HTTP Protocol Binding Conversion Functions function ConvertTo-HttpMessage { <# .SYNOPSIS This function converts a cloud event object to a Http Message. .DESCRIPTION This function converts a cloud event object to a PSObject with Headers and Body properties. The 'Headers' propery is a hashtable that can pe provided to the 'Headers' parameter of the Inveok-WebRequest cmdlet. The 'Body' propery is byte[] that can pe provided to the 'Body' parameter of the Inveok-WebRequest cmdlet. .PARAMETER CloudEvent Specifies the cloud event object to convert. .PARAMETER ContentMode Specifies the cloud event content mode. Structured and Binary content modes are supporterd. .EXAMPLE $cloudEvent = New-CloudEvent -Type 'com.example.object.deleted.v2' -Source 'mailto:cncf-wg-serverless@lists.cncf.io' -Id '6e8bc430-9c3a-11d9-9669-0800200c9a66' -Time (Get-Date) $cloudEvent | Add-CloudEventJsonData -Data @{ 'key1' = 'value1'; 'key2' = 'value2'; } $cloudEvent | ConvertTo-HttpMessage -ContentMode Binary Converts a cloud event object to Headers and Body formatted in Binary content mode. .EXAMPLE $cloudEvent = New-CloudEvent -Type 'com.example.object.deleted.v2' -Source 'mailto:cncf-wg-serverless@lists.cncf.io' -Id '6e8bc430-9c3a-11d9-9669-0800200c9a66' -Time (Get-Date) $cloudEvent | Add-CloudEventJsonData -Data @{ 'key1' = 'value1'; 'key2' = 'value2'; } $cloudEvent | ConvertTo-HttpMessage -ContentMode Structured Converts a cloud event object to Headers and Body formatted in Structured content mode. .EXAMPLE $httpMessage = New-CloudEvent -Type 'com.example.object.deleted.v2' -Source 'mailto:cncf-wg-serverless@lists.cncf.io' -Id '6e8bc430-9c3a-11d9-9669-0800200c9a66' -Time (Get-Date) | ` Add-CloudEventJsonData -Data @{ 'key1' = 'value1'; 'key2' = 'value2'; } | ` ConvertTo-HttpMessage -ContentMode Structured Invoke-WebRequest -Uri 'http://localhost:52673/' -Headers $httpMessage.Headers -Body $httpMessage.Body Sends a cloud event http requests to a server #> [CmdletBinding()] param( [Parameter( Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $false)] [ValidateNotNull()] [CloudNative.CloudEvents.CloudEvent] $CloudEvent, [Parameter( Mandatory = $true, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $false)] [CloudNative.CloudEvents.ContentMode] $ContentMode) PROCESS { # Output Object $result = New-Object -TypeName PSCustomObject $cloudEventFormatter = New-Object 'CloudNative.CloudEvents.JsonEventFormatter' $HttpHeaderPrefix = "ce-"; $SpecVersionHttpHeader1 = $HttpHeaderPrefix + "cloudEventsVersion"; $SpecVersionHttpHeader2 = $HttpHeaderPrefix + "specversion"; $headers = @{} # Build HTTP headers foreach ($attribute in $cloudEvent.GetAttributes()) { if (-not $attribute.Key.Equals([CloudNative.CloudEvents.CloudEventAttributes]::DataAttributeName($cloudEvent.SpecVersion)) -and ` -not $attribute.Key.Equals([CloudNative.CloudEvents.CloudEventAttributes]::DataContentTypeAttributeName($cloudEvent.SpecVersion))) { if ($attribute.Value -is [string]) { $headers.Add(($HttpHeaderPrefix + $attribute.Key), $attribute.Value.ToString()) } elseif ($attribute.Value -is [DateTime]) { $headers.Add(($HttpHeaderPrefix + $attribute.Key), $attribute.Value.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffZ')) } elseif ($attribute.Value -is [Uri] -or $attribute.Value -is [int]) { $headers.Add(($HttpHeaderPrefix + $attribute.Key), $attribute.Value.ToString()) } else { $headers.Add(($HttpHeaderPrefix + $attribute.Key), [System.Text.Encoding]::UTF8.GetString($cloudEventFormatter.EncodeAttribute($cloudEvent.SpecVersion, $attribute.Key, $attribute.Value, $cloudEvent.Extensions.Values))); } } } # Add Headers property to the output object $result | Add-Member -MemberType NoteProperty -Name 'Headers' -Value $headers # Process Structured Mode # Structured Mode supports non-batching JSON format only # https://github.com/cloudevents/spec/blob/v1.0.1/http-protocol-binding.md#14-event-formats if ($ContentMode -eq [CloudNative.CloudEvents.ContentMode]::Structured) { # Format Body as byte[] $contentType = $null # CloudEventFormatter is instance of 'CloudNative.CloudEvents.JsonEventFormatter' from the # .NET CloudEvents SDK for the purpose of fomatting structured mode $buffer = $cloudEventFormatter.EncodeStructuredEvent($cloudEvent, [ref] $contentType) $result | Add-Member -MemberType NoteProperty -Name 'Body' -Value $buffer $result.Headers.Add('Content-Type', $contentType) } # Process Binary Mode if ($ContentMode -eq [CloudNative.CloudEvents.ContentMode]::Binary) { $bodyData = $null if ($cloudEvent.DataContentType -ne $null) { $result.Headers.Add('Content-Type', $cloudEvent.DataContentType) } if ($cloudEvent.Data -is [byte[]]) { $bodyData = $cloudEvent.Data } elseif ($cloudEvent.Data -is [string]) { $bodyData = [System.Text.Encoding]::UTF8.GetBytes($cloudEvent.Data.ToString()) } elseif ($cloudEvent.Data -is [IO.Stream]) { $buffer = New-Object 'byte[]' -ArgumentList 1024 $ms = New-Object 'IO.MemoryStream' try { $read = 0 while (($read = $cloudEvent.Data.Read($buffer, 0, 1024)) -gt 0) { $ms.Write($buffer, 0, $read); } $bodyData = $ms.ToArray() } finally { $ms.Dispose() } } else { $bodyData = $cloudEventFormatter.EncodeAttribute($cloudEvent.SpecVersion, [CloudNative.CloudEvents.CloudEventAttributes]::DataAttributeName($cloudEvent.SpecVersion), $cloudEvent.Data, $cloudEvent.Extensions.Values) } # Add Body property to the output object $result | Add-Member -MemberType NoteProperty -Name 'Body' -Value $bodyData } Write-Output $result } } function ConvertFrom-HttpMessage { <# .SYNOPSIS This function converts a Http Message to a cloud event object .DESCRIPTION This function converts a Http Message (Headers and Body) to a cloud event object. Result of Invoke-WebRequest that contains a cloud event can be passed as input to this function binding the the 'Headers' and 'Content' properties to the 'Headers' and 'Body' paramters. .PARAMETER Headers Specifies the Http Headers as a PowerShell hashtable. .PARAMETER Body Specifies the Http body as string or byte[]. .EXAMPLE $httpReponse = Invoke-WebRequest -Uri 'http://localhost:52673/' -Headers $httpMessage.Headers -Body $httpMessage.Body $cloudEvent = ConvertFrom-HttpMessage -Headers $httpResponse.Headers -Body $httpResponse.Content Converts a http response to a cloud event object #> [CmdletBinding()] param( [Parameter( Mandatory = $true, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $false)] [ValidateNotNull()] [hashtable] $Headers, [Parameter( Mandatory = $false, ValueFromPipeline = $false, ValueFromPipelineByPropertyName = $false)] [ValidateNotNull()] $Body) PROCESS { $HttpHeaderPrefix = "ce-"; $SpecVersionHttpHeader = $HttpHeaderPrefix + "specversion"; $result = $null # Always Convert Body to byte[] # Conversion works with byte[] while # body can be string in HTTP responses # for text content type if ($Body -is [string]) { $Body = [System.Text.Encoding]::UTF8.GetBytes($Body) } if ($null -ne $Headers['Content-Type']) { $ContentType = $Headers['Content-Type'] if ($ContentType -is [array]) { # Get the first content-type value $ContentType = $ContentType[0] } if ($ContentType.StartsWith([CloudNative.CloudEvents.CloudEvent]::MediaType, [StringComparison]::InvariantCultureIgnoreCase)) { # Handle Structured Mode $ctParts = $ContentType.Split(';') if ($ctParts[0].Trim().StartsWith(([CloudNative.CloudEvents.CloudEvent]::MediaType) + ([CloudNative.CloudEvents.JsonEventFormatter]::MediaTypeSuffix), [StringComparison]::InvariantCultureIgnoreCase)) { # Structured Mode supports non-batching JSON format only # https://github.com/cloudevents/spec/blob/v1.0.1/http-protocol-binding.md#14-event-formats # .NET SDK 'CloudNative.CloudEvents.JsonEventFormatter' type is used # to decode the Structured Mode CloudEvents $json = [System.Text.Encoding]::UTF8.GetString($Body) $jObject = [Newtonsoft.Json.Linq.JObject]::Parse($json) $formatter = New-Object 'CloudNative.CloudEvents.JsonEventFormatter' $result = $formatter.DecodeJObject($jObject, $null) $result.Data = $result.Data } else { # Throw error for unsupported encoding throw "Unsupported CloudEvents encoding" } } else { # Handle Binary Mode $version = $null if ($Headers.Contains($SpecVersionHttpHeader) -and ` $null -ne $Headers[$SpecVersionHttpHeader] -and ` ($Headers[$SpecVersionHttpHeader] | Select-Object -First 1).StartsWith('1.0')) { # We do support the 1.0 cloud event version $version = [CloudNative.CloudEvents.CloudEventsSpecVersion]::V1_0 } if ($null -ne $version) { # SpecVersion is REQUIRED attribute, it it is not specified this is not a CloudEvent # https://github.com/cloudevents/spec/blob/v1.0.1/spec.md#specversion $cloudEvent = New-Object ` -TypeName 'CloudNative.CloudEvents.CloudEvent' ` -ArgumentList @($version, $null); $attributes = $cloudEvent.GetAttributes(); # Get attributes from HTTP Headers foreach ($httpHeader in $Headers.GetEnumerator()) { if ($httpHeader.Key.Equals($SpecVersionHttpHeader, [StringComparison]::InvariantCultureIgnoreCase)) { continue } if ($httpHeader.Key.StartsWith($HttpHeaderPrefix, [StringComparison]::InvariantCultureIgnoreCase)) { $headerValue = $httpHeader.Value if ($headerValue -is [array]) { # Get the first object $headerValue = $headerValue[0] } $name = $httpHeader.Key.Substring(3); # Abolished structures in headers in 1.0 if ( $null -ne $headerValue -and ` $headerValue.StartsWith('"') -and ` $headerValue.EndsWith('"') -or ` $headerValue.StartsWith("'") -and $headerValue.EndsWith("'") -or ` $headerValue.StartsWith("{") -and $headerValue.EndsWith("}") -or ` $headerValue.StartsWith("[") -and $headerValue.EndsWith("]")) { $jsonFormatter = New-Object 'CloudNative.CloudEvents.JsonEventFormatter' $attributes[$name] = $jsonFormatter.DecodeAttribute($version, $name, [System.Text.Encoding]::UTF8.GetBytes($headerValue), $null); } else { $attributes[$name] = $headerValue } } } # Verify parsed attributes from HTTP Headers if ($null -ne $attributes['datacontenttype']) { # ce-datatype is prohibitted by the protocol -> throw error # https://github.com/cloudevents/spec/blob/v1.0.1/http-protocol-binding.md#311-http-content-type throw "'ce-datacontenttype' HTTP header is prohibited for Binary ContentMode CloudEvent" } if ($Headers['Content-Type'] -is [string]) { $cloudEvent.DataContentType = New-Object 'System.Net.Mime.ContentType' -ArgumentList @($Headers['Content-Type']) } elseif ($Headers['Content-Type'][0] -is [string]) { $cloudEvent.DataContentType = New-Object 'System.Net.Mime.ContentType' -ArgumentList @($Headers['Content-Type'][0]) } # Id, Type, and Source are reuiqred to be non-empty strings otherwise consider this is not a CloudEvent # https://github.com/cloudevents/spec/blob/v1.0.1/spec.md#required-attributes if ( -not [string]::IsNullOrEmpty($cloudEvent.Id) -and ` -not [string]::IsNullOrEmpty($cloudEvent.Source) -and ` -not [string]::IsNullOrEmpty($cloudEvent.Type)) { # Get Data from HTTP Body $cloudEvent.Data = $Body $result = $cloudEvent } } } } Write-Output $result } } #endregion HTTP Protocol Binding Conversion Functions |