Compare commits
24 Commits
Author | SHA1 | Date |
---|---|---|
|
e4c6eb2053 | |
|
de78f7abc0 | |
|
fce1f2a05b | |
|
69b301acc5 | |
|
62f0995896 | |
|
033df40cea | |
|
685b0fb6c2 | |
|
f81400785b | |
|
112e84313d | |
|
7fe15200b3 | |
|
32f333ba86 | |
|
5e2e221c24 | |
|
23e8b6714b | |
|
c8b5958909 | |
|
eda44f45bb | |
|
4cebfdf75e | |
|
c715c5c97e | |
|
7eb0f9b4bd | |
|
4e380882f8 | |
|
941816a414 | |
|
4a8a5abcca | |
|
7876104118 | |
|
36f8b25dce | |
|
75b318093c |
|
@ -14,4 +14,4 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check WIP in PR Title
|
||||
uses: embano1/wip@v1
|
||||
uses: embano1/wip@v2
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
name: Release
|
||||
|
||||
on:
|
||||
create:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
workflow_dispatch:
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
|
||||
<a name="v0.3.3"></a>
|
||||
## [Release v0.3.3](https://github.com/cloudevents/sdk-powershell/compare/v0.3.2...v0.3.3)
|
||||
|
||||
> Release Date: 2021-09-08
|
||||
|
||||
### 🧹 Chore
|
||||
|
||||
- [32f333b] Bump module version for new release
|
||||
- [5e2e221] Trigger release on tag push (#47)
|
||||
|
||||
### ⚠️ BREAKING
|
||||
|
||||
### 📖 Commits
|
||||
|
||||
- [32f333b] chore: Bump module version for new release
|
||||
- [5e2e221] chore: Trigger release on tag push (#47)
|
||||
|
||||
<a name="v0.3.2"></a>
|
||||
## [Release v0.3.2](https://github.com/cloudevents/sdk-powershell/compare/v0.3.1...v0.3.2)
|
||||
|
||||
> Release Date: 2021-09-08
|
||||
|
||||
### 🧹 Chore
|
||||
|
||||
- [c8b5958] Add Project URI in the module manifest
|
||||
|
||||
### ⚠️ BREAKING
|
||||
|
||||
### 📖 Commits
|
||||
|
||||
- [c8b5958] chore: Add Project URI in the module manifest
|
||||
|
||||
<a name="v0.3.1"></a>
|
||||
## [Release v0.3.1](https://github.com/cloudevents/sdk-powershell/compare/v0.3.0...v0.3.1)
|
||||
|
||||
> Release Date: 2021-08-30
|
||||
|
||||
### 🐞 Fix
|
||||
|
||||
- [7eb0f9b] Incorrect parsing of Binary Content Mode cloud events
|
||||
|
||||
### 🧹 Chore
|
||||
|
||||
- [941816a] Add RELEASE instructions (#40)
|
||||
|
||||
### ⚠️ BREAKING
|
||||
|
||||
### 📖 Commits
|
||||
|
||||
- [7eb0f9b] fix: Incorrect parsing of Binary Content Mode cloud events
|
||||
- [941816a] chore: Add RELEASE instructions (#40)
|
||||
- [7876104] Update README with the new version output
|
||||
|
||||
<a name="v0.3.0"></a>
|
||||
## v0.3.0
|
||||
|
||||
> Release Date: 2021-06-21
|
||||
|
||||
### 🧹 Chore
|
||||
|
||||
- [5b14f75] Include commit details in CHANGELOG (#35)
|
||||
- [2c4d0ed] Add check WIP action (#31)
|
||||
- [5764180] Add CHANGELOG configuration (#29)
|
||||
- [0bd4192] Verify PRs and push to main (#6)
|
||||
- [e08a275] Add stale action (#7)
|
||||
|
||||
### ⚠️ BREAKING
|
||||
|
||||
### 📖 Commits
|
||||
|
||||
- [2144695] Bump module version 0.3.0
|
||||
- [5b14f75] chore: Include commit details in CHANGELOG (#35)
|
||||
- [78b7e9e] Implement publish script
|
||||
- [2c4d0ed] chore: Add check WIP action (#31)
|
||||
- [5764180] chore: Add CHANGELOG configuration (#29)
|
||||
- [a0e1078] Add PR template (#3)
|
||||
- [ae6f848] Update issue templates
|
||||
- [3a9010a] Improve examples. Remove unnecessary details.
|
||||
- [401a475] Implement wait server to start in the integrations tests BeforeAll Fix Binary Mode HTTP Header DateTime format. It is UTC time formatted in ISO 8601 format including milliseconds. Bump revision of the module version
|
||||
- [0bd4192] chore: Verify PRs and push to main (#6)
|
||||
- [e08a275] chore: Add stale action (#7)
|
||||
- [3629c77] Add Install Module Instructions to README ([#17](https://github.com/cloudevents/sdk-powershell/issues/17)) (#17) (#16)
|
||||
- [aac584a] Enable process exit in build.ps1
|
||||
- [84606b0] Create CONTRIBUTING.md ([#15](https://github.com/cloudevents/sdk-powershell/issues/15)) (#15)
|
||||
- [d305f16] Renames Add-CloudEvent*Data to Set-CloudEvent*Data ([#12](https://github.com/cloudevents/sdk-powershell/issues/12)) (#12) (#9)
|
||||
- [f23df54] Adds license headers in source code files ([#11](https://github.com/cloudevents/sdk-powershell/issues/11)) (#11)
|
||||
- [62f14b6] Remove install instructions from an internal PS repository ([#10](https://github.com/cloudevents/sdk-powershell/issues/10)) (#10) (#1)
|
||||
- [b2afcf8] Initial commit
|
|
@ -0,0 +1,9 @@
|
|||
# Maintainers
|
||||
|
||||
Current active maintainers of this SDK:
|
||||
|
||||
- [William Lam](https://github.com/lamw)
|
||||
- [Mark Peek](https://github.com/markpeek
|
||||
- [Dimitar Milov](https://github.com/dmilov)
|
||||
- [Michael Gasch](https://github.com/embano1)
|
||||
- [Simeon Gerginov](https://github.com/SimeonGerginov)
|
64
README.md
64
README.md
|
@ -1,5 +1,7 @@
|
|||
# PowerShell 7.0 SDK for CloudEvents based on [.NET SDK for CloudEvents](https://github.com/cloudevents/sdk-csharp)
|
||||
|
||||
Official CloudEvents SDK to integrate your application with CloudEvents.
|
||||
|
||||
## Status
|
||||
|
||||
Supported CloudEvents versions:
|
||||
|
@ -26,16 +28,17 @@ Install-Module CloudEvents.Sdk
|
|||
Import-Module CloudEvents.Sdk
|
||||
Get-Command -Module CloudEvents.Sdk
|
||||
|
||||
CommandType Name Version Source ----------- ---- ------- ------
|
||||
Function ConvertFrom-HttpMessage 0.2.0 CloudEvents.Sdk
|
||||
Function ConvertTo-HttpMessage 0.2.0 CloudEvents.Sdk
|
||||
Function New-CloudEvent 0.2.0 CloudEvents.Sdk
|
||||
Function Read-CloudEventData 0.2.0 CloudEvents.Sdk
|
||||
Function Read-CloudEventJsonData 0.2.0 CloudEvents.Sdk
|
||||
Function Read-CloudEventXmlData 0.2.0 CloudEvents.Sdk
|
||||
Function Set-CloudEventData 0.2.0 CloudEvents.Sdk
|
||||
Function Set-CloudEventJsonData 0.2.0 CloudEvents.Sdk
|
||||
Function Set-CloudEventXmlData 0.2.0 CloudEvents.Sdk
|
||||
CommandType Name Version Source
|
||||
----------- ---- ------- ------
|
||||
Function ConvertFrom-HttpMessage 0.3.0 CloudEvents.Sdk
|
||||
Function ConvertTo-HttpMessage 0.3.0 CloudEvents.Sdk
|
||||
Function New-CloudEvent 0.3.0 CloudEvents.Sdk
|
||||
Function Read-CloudEventData 0.3.0 CloudEvents.Sdk
|
||||
Function Read-CloudEventJsonData 0.3.0 CloudEvents.Sdk
|
||||
Function Read-CloudEventXmlData 0.3.0 CloudEvents.Sdk
|
||||
Function Set-CloudEventData 0.3.0 CloudEvents.Sdk
|
||||
Function Set-CloudEventJsonData 0.3.0 CloudEvents.Sdk
|
||||
Function Set-CloudEventXmlData 0.3.0 CloudEvents.Sdk
|
||||
```
|
||||
|
||||
## Using **`CloudEvents.Sdk`** Module
|
||||
|
@ -73,7 +76,7 @@ $cloudEvent | Set-CloudEventXmlData -Data @{
|
|||
'xml' = @{
|
||||
'Foo' = 'Hello'
|
||||
'Bar' = 'World'
|
||||
}
|
||||
}
|
||||
} `
|
||||
-AttributesKeysInElementAttributes $true
|
||||
|
||||
|
@ -158,4 +161,41 @@ Read-CloudEventData -CloudEvent $cloudEvent
|
|||
108
|
||||
100
|
||||
33
|
||||
```
|
||||
```
|
||||
|
||||
## Community
|
||||
|
||||
- There are bi-weekly calls immediately following the
|
||||
[Serverless/CloudEvents call](https://github.com/cloudevents/spec#meeting-time)
|
||||
at 9am PT (US Pacific). Which means they will typically start at 10am PT, but
|
||||
if the other call ends early then the SDK call will start early as well. See
|
||||
the
|
||||
[CloudEvents meeting minutes](https://docs.google.com/document/d/1OVF68rpuPK5shIHILK9JOqlZBbfe91RNzQ7u_P7YCDE/edit#)
|
||||
to determine which week will have the call.
|
||||
- Slack: #cloudeventssdk channel under
|
||||
[CNCF's Slack workspace](https://slack.cncf.io/).
|
||||
- Email: https://lists.cncf.io/g/cncf-cloudevents-sdk
|
||||
- Contact for additional information: Michael Gasch (`@Michael Gasch`
|
||||
on slack).
|
||||
|
||||
Each SDK may have its own unique processes, tooling and guidelines, common
|
||||
governance related material can be found in the
|
||||
[CloudEvents `community`](https://github.com/cloudevents/spec/tree/master/community)
|
||||
directory. In particular, in there you will find information concerning
|
||||
how SDK projects are
|
||||
[managed](https://github.com/cloudevents/spec/blob/master/community/SDK-GOVERNANCE.md),
|
||||
[guidelines](https://github.com/cloudevents/spec/blob/master/community/SDK-maintainer-guidelines.md)
|
||||
for how PR reviews and approval, and our
|
||||
[Code of Conduct](https://github.com/cloudevents/spec/blob/master/community/GOVERNANCE.md#additional-information)
|
||||
information.
|
||||
|
||||
If there is a security concern with one of the CloudEvents specifications, or
|
||||
with one of the project's SDKs, please send an email to
|
||||
[cncf-cloudevents-security@lists.cncf.io](mailto:cncf-cloudevents-security@lists.cncf.io).
|
||||
|
||||
## Additional SDK Resources
|
||||
|
||||
- [List of current active maintainers](MAINTAINERS.md)
|
||||
- [How to contribute to the project](CONTRIBUTING.md)
|
||||
- [SDK's License](LICENSE)
|
||||
- [SDK's Release process](RELEASING.md)
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
# How to create a Release
|
||||
|
||||
We use `tags` to drive the creation of the releases. This is handled by the
|
||||
Github Actions release workflow in
|
||||
[`ps-ce-sdk-release.yaml`](.github/workflows/ps-ce-sdk-release.yaml).
|
||||
|
||||
A new release will upload the `PowerShell` module artifacts to the `PowerShell`
|
||||
[gallery](https://www.powershellgallery.com/packages/CloudEvents.Sdk).
|
||||
|
||||
## Step 1 - Bump Module Version
|
||||
|
||||
Bump the `ModuleVersion` in
|
||||
[`src/CloudEventsPowerShell/CloudEvents.Sdk.psd1`](./src/CloudEventsPowerShell/CloudEvents.Sdk.psd1)
|
||||
to the next semantic release version (without `"v"` prefix).
|
||||
|
||||
```powershell
|
||||
# Version number of this module.
|
||||
ModuleVersion = '0.3.0'
|
||||
```
|
||||
|
||||
Create a pull request with this change, review and approve it **after** all checks
|
||||
have passed.
|
||||
|
||||
|
||||
## Step 2 - Update local `main` branch
|
||||
|
||||
Pull in the latest changes, incl. the merged PR above, into your local `main`
|
||||
branch of this repository **before** creating a `tag` via the `git` CLI.
|
||||
|
||||
```console
|
||||
git checkout main
|
||||
git fetch -avp
|
||||
git pull upstream main
|
||||
```
|
||||
|
||||
**Note:** the above commands assume `upstream` pointing to the remote
|
||||
`https://github.com/cloudevents/sdk-powershell.git`
|
||||
|
||||
## Step 3 - Create and push a Tag
|
||||
|
||||
|
||||
```console
|
||||
RELEASE=v0.3.0
|
||||
git tag -a $RELEASE -m "Release ${RELEASE}"
|
||||
git push upstream refs/tags/${RELEASE}
|
||||
```
|
||||
|
||||
|
||||
This will trigger the release
|
||||
[workflow](https://github.com/cloudevents/sdk-powershell/actions/workflows/ps-ce-sdk-release.yaml).
|
||||
**Verify** that it executed successfully and that a new Github
|
||||
[release](https://github.com/cloudevents/sdk-powershell/releases) was created.
|
||||
|
||||
The release workflow also creates a pull request with the updated
|
||||
[`CHANGELOG.md`](CHANGELOG.md). **Verify**, approve and merge accordingly.
|
||||
|
||||
If you need to make changes to the Github release notes, you can edit them on the [release](https://github.com/cloudevents/sdk-powershell/releases) page.
|
|
@ -9,7 +9,7 @@
|
|||
RootModule = 'CloudEvents.Sdk.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '0.3.0'
|
||||
ModuleVersion = '0.3.3'
|
||||
|
||||
# Supported PSEditions
|
||||
CompatiblePSEditions = @('Core')
|
||||
|
@ -80,5 +80,38 @@ VariablesToExport = '*'
|
|||
# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export.
|
||||
AliasesToExport = @()
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell.
|
||||
PrivateData = @{
|
||||
|
||||
PSData = @{
|
||||
|
||||
# Tags applied to this module. These help with module discovery in online galleries.
|
||||
Tags = 'CloudEvents','SDK'
|
||||
|
||||
# A URL to the license for this module.
|
||||
# LicenseUri = ''
|
||||
|
||||
# A URL to the main website for this project.
|
||||
ProjectUri = 'https://github.com/cloudevents/sdk-powershell'
|
||||
|
||||
# A URL to an icon representing this module.
|
||||
# IconUri = ''
|
||||
|
||||
# ReleaseNotes of this module
|
||||
# ReleaseNotes = ''
|
||||
|
||||
# Prerelease string of this module
|
||||
# Prerelease = ''
|
||||
|
||||
# Flag to indicate whether the module requires explicit user acceptance for install/update
|
||||
# RequireLicenseAcceptance = $false
|
||||
|
||||
# External dependent modules of this module
|
||||
# ExternalModuleDependencies = @()
|
||||
|
||||
} # End of PSData hashtable
|
||||
|
||||
} # End of PrivateData hashtable
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ $xmlDataSerilizationLibPath = Join-Path (Join-Path $PSScriptRoot 'dataserializat
|
|||
. $xmlDataSerilizationLibPath
|
||||
|
||||
function New-CloudEvent {
|
||||
<#
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This function creates a new cloud event.
|
||||
|
||||
|
@ -35,46 +35,46 @@ function New-CloudEvent {
|
|||
Creates a cloud event with Type, Source, Id, and Time
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]
|
||||
$Type,
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]
|
||||
$Type,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[System.Uri]
|
||||
$Source,
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[System.Uri]
|
||||
$Source,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]
|
||||
$Id,
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[string]
|
||||
$Id,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[DateTime]
|
||||
$Time
|
||||
)
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[DateTime]
|
||||
$Time
|
||||
)
|
||||
|
||||
PROCESS {
|
||||
$cloudEvent = New-Object `
|
||||
-TypeName 'CloudNative.CloudEvents.CloudEvent' `
|
||||
-ArgumentList @(
|
||||
$Type,
|
||||
$Source,
|
||||
$Id,
|
||||
$Time,
|
||||
@())
|
||||
PROCESS {
|
||||
$cloudEvent = New-Object `
|
||||
-TypeName 'CloudNative.CloudEvents.CloudEvent' `
|
||||
-ArgumentList @(
|
||||
$Type,
|
||||
$Source,
|
||||
$Id,
|
||||
$Time,
|
||||
@())
|
||||
|
||||
Write-Output $cloudEvent
|
||||
}
|
||||
Write-Output $cloudEvent
|
||||
}
|
||||
}
|
||||
|
||||
#region Set Data Functions
|
||||
function Set-CloudEventData {
|
||||
<#
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This function sets data in a cloud event.
|
||||
|
||||
|
@ -98,45 +98,45 @@ function Set-CloudEventData {
|
|||
Sets xml data to the cloud event
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[CloudNative.CloudEvents.CloudEvent]
|
||||
$CloudEvent,
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[CloudNative.CloudEvents.CloudEvent]
|
||||
$CloudEvent,
|
||||
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $false)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[object]
|
||||
$Data,
|
||||
[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)
|
||||
# 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 {
|
||||
PROCESS {
|
||||
|
||||
# https://github.com/cloudevents/spec/blob/master/spec.md#datacontenttype
|
||||
$contentType = New-Object `
|
||||
-TypeName 'System.Net.Mime.ContentType' `
|
||||
-ArgumentList ($DataContentType)
|
||||
# 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
|
||||
$cloudEvent.Data = $Data
|
||||
$cloudEvent.DataContentType = $dataContentType
|
||||
|
||||
Write-Output $CloudEvent
|
||||
}
|
||||
Write-Output $CloudEvent
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function Set-CloudEventJsonData {
|
||||
<#
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This function sets JSON format data in a cloud event.
|
||||
|
||||
|
@ -163,43 +163,43 @@ function Set-CloudEventJsonData {
|
|||
Sets JSON data to the cloud event
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[CloudNative.CloudEvents.CloudEvent]
|
||||
$CloudEvent,
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[CloudNative.CloudEvents.CloudEvent]
|
||||
$CloudEvent,
|
||||
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $false)]
|
||||
[ValidateNotNull()]
|
||||
[Hashtable]
|
||||
$Data,
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $false)]
|
||||
[ValidateNotNull()]
|
||||
[Hashtable]
|
||||
$Data,
|
||||
|
||||
[Parameter(Mandatory = $false,
|
||||
ValueFromPipeline = $false)]
|
||||
[int]
|
||||
$Depth = 3)
|
||||
[Parameter(Mandatory = $false,
|
||||
ValueFromPipeline = $false)]
|
||||
[int]
|
||||
$Depth = 3)
|
||||
|
||||
PROCESS {
|
||||
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)
|
||||
# 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
|
||||
$cloudEvent.DataContentType = $dataContentType
|
||||
$cloudEvent.Data = ConvertTo-Json -InputObject $Data -Depth $Depth
|
||||
|
||||
Write-Output $CloudEvent
|
||||
}
|
||||
Write-Output $CloudEvent
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function Set-CloudEventXmlData {
|
||||
<#
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This function sets XML format data in a cloud event.
|
||||
|
||||
|
@ -229,43 +229,43 @@ function Set-CloudEventXmlData {
|
|||
Sets XML data in the cloud event
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[CloudNative.CloudEvents.CloudEvent]
|
||||
$CloudEvent,
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[CloudNative.CloudEvents.CloudEvent]
|
||||
$CloudEvent,
|
||||
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $false)]
|
||||
[ValidateNotNull()]
|
||||
[Hashtable]
|
||||
$Data,
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $false)]
|
||||
[ValidateNotNull()]
|
||||
[Hashtable]
|
||||
$Data,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[bool]
|
||||
$AttributesKeysInElementAttributes)
|
||||
[Parameter(Mandatory = $true)]
|
||||
[bool]
|
||||
$AttributesKeysInElementAttributes)
|
||||
|
||||
PROCESS {
|
||||
PROCESS {
|
||||
|
||||
# DataContentType is set to 'application/xml'
|
||||
$dataContentType = New-Object `
|
||||
-TypeName 'System.Net.Mime.ContentType' `
|
||||
-ArgumentList ([System.Net.Mime.MediaTypeNames+Application]::Xml)
|
||||
# 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
|
||||
$cloudEvent.DataContentType = $dataContentType
|
||||
$cloudEvent.Data = ConvertTo-CEDataXml -InputObject $Data -AttributesKeysInElementAttributes $AttributesKeysInElementAttributes
|
||||
|
||||
Write-Output $CloudEvent
|
||||
}
|
||||
Write-Output $CloudEvent
|
||||
}
|
||||
|
||||
}
|
||||
#endregion Set Data Functions
|
||||
|
||||
#region Read Data Functions
|
||||
function Read-CloudEventData {
|
||||
<#
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This function gets the data from a cloud event.
|
||||
|
||||
|
@ -282,23 +282,23 @@ function 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
|
||||
)
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[CloudNative.CloudEvents.CloudEvent]
|
||||
$CloudEvent
|
||||
)
|
||||
|
||||
PROCESS {
|
||||
Write-Output $CloudEvent.Data
|
||||
}
|
||||
PROCESS {
|
||||
Write-Output $CloudEvent.Data
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function Read-CloudEventJsonData {
|
||||
<#
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This function gets JSON fromat data from a cloud event as a PowerShell hashtable.
|
||||
|
||||
|
@ -320,56 +320,57 @@ function Read-CloudEventJsonData {
|
|||
#>
|
||||
|
||||
|
||||
<#
|
||||
<#
|
||||
.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,
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[CloudNative.CloudEvents.CloudEvent]
|
||||
$CloudEvent,
|
||||
|
||||
[Parameter(Mandatory = $false,
|
||||
ValueFromPipeline = $false)]
|
||||
[int]
|
||||
$Depth = 3
|
||||
)
|
||||
[Parameter(Mandatory = $false,
|
||||
ValueFromPipeline = $false)]
|
||||
[int]
|
||||
$Depth = 3
|
||||
)
|
||||
|
||||
PROCESS {
|
||||
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)
|
||||
# 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])) {
|
||||
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
|
||||
$data = $cloudEvent.Data
|
||||
|
||||
if ($cloudEvent.Data -is [byte[]]) {
|
||||
$data = [System.Text.Encoding]::UTF8.GetString($data)
|
||||
}
|
||||
if ($cloudEvent.Data -is [byte[]]) {
|
||||
$data = [System.Text.Encoding]::UTF8.GetString($data)
|
||||
}
|
||||
|
||||
$result = $data.ToString() | ConvertFrom-Json -AsHashtable -Depth $Depth
|
||||
$result = $data.ToString() | ConvertFrom-Json -AsHashtable -Depth $Depth
|
||||
|
||||
Write-Output $result
|
||||
} else {
|
||||
Write-Error "Cloud Event '$($cloudEvent.Id)' has no json data"
|
||||
}
|
||||
}
|
||||
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.
|
||||
|
||||
|
@ -430,55 +431,56 @@ function Read-CloudEventXmlData {
|
|||
#>
|
||||
|
||||
|
||||
<#
|
||||
<#
|
||||
.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,
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true,
|
||||
ValueFromPipeline = $true)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[CloudNative.CloudEvents.CloudEvent]
|
||||
$CloudEvent,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateSet("SkipAttributes", "AlwaysAttrValue", "AttrValueWhenAttributes")]
|
||||
[string]
|
||||
$ConvertMode
|
||||
)
|
||||
[Parameter(Mandatory = $true)]
|
||||
[ValidateSet("SkipAttributes", "AlwaysAttrValue", "AttrValueWhenAttributes")]
|
||||
[string]
|
||||
$ConvertMode
|
||||
)
|
||||
|
||||
PROCESS {
|
||||
PROCESS {
|
||||
|
||||
# DataContentType is expected to be 'application/xml'
|
||||
$dataContentType = New-Object `
|
||||
-TypeName 'System.Net.Mime.ContentType' `
|
||||
-ArgumentList ([System.Net.Mime.MediaTypeNames+Application]::Xml)
|
||||
# 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) {
|
||||
if ($CloudEvent.DataContentType -eq $dataContentType) {
|
||||
|
||||
$data = $cloudEvent.Data
|
||||
$data = $cloudEvent.Data
|
||||
|
||||
if ($cloudEvent.Data -is [byte[]]) {
|
||||
$data = [System.Text.Encoding]::UTF8.GetString($data)
|
||||
}
|
||||
if ($cloudEvent.Data -is [byte[]]) {
|
||||
$data = [System.Text.Encoding]::UTF8.GetString($data)
|
||||
}
|
||||
|
||||
$result = $data.ToString() | ConvertFrom-CEDataXml -ConvertMode $ConvertMode
|
||||
$result = $data.ToString() | ConvertFrom-CEDataXml -ConvertMode $ConvertMode
|
||||
|
||||
Write-Output $result
|
||||
} else {
|
||||
Write-Error "Cloud Event '$($cloudEvent.Id)' has no xml data"
|
||||
}
|
||||
}
|
||||
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.
|
||||
|
||||
|
@ -519,121 +521,121 @@ function ConvertTo-HttpMessage {
|
|||
Sends a cloud event http requests to a server
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(
|
||||
Mandatory = $true,
|
||||
ValueFromPipeline = $true,
|
||||
ValueFromPipelineByPropertyName = $false)]
|
||||
[ValidateNotNull()]
|
||||
[CloudNative.CloudEvents.CloudEvent]
|
||||
$CloudEvent,
|
||||
[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)
|
||||
[Parameter(
|
||||
Mandatory = $true,
|
||||
ValueFromPipeline = $false,
|
||||
ValueFromPipelineByPropertyName = $false)]
|
||||
[CloudNative.CloudEvents.ContentMode]
|
||||
$ContentMode)
|
||||
|
||||
PROCESS {
|
||||
# Output Object
|
||||
$result = New-Object -TypeName PSCustomObject
|
||||
PROCESS {
|
||||
# Output Object
|
||||
$result = New-Object -TypeName PSCustomObject
|
||||
|
||||
$cloudEventFormatter = New-Object 'CloudNative.CloudEvents.JsonEventFormatter'
|
||||
$cloudEventFormatter = New-Object 'CloudNative.CloudEvents.JsonEventFormatter'
|
||||
|
||||
$HttpHeaderPrefix = "ce-";
|
||||
$SpecVersionHttpHeader1 = $HttpHeaderPrefix + "cloudEventsVersion";
|
||||
$SpecVersionHttpHeader2 = $HttpHeaderPrefix + "specversion";
|
||||
$HttpHeaderPrefix = "ce-";
|
||||
$SpecVersionHttpHeader1 = $HttpHeaderPrefix + "cloudEventsVersion";
|
||||
$SpecVersionHttpHeader2 = $HttpHeaderPrefix + "specversion";
|
||||
|
||||
$headers = @{}
|
||||
$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);
|
||||
# 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)));
|
||||
}
|
||||
}
|
||||
$bodyData = $ms.ToArray()
|
||||
} finally {
|
||||
$ms.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
$bodyData = $cloudEventFormatter.EncodeAttribute($cloudEvent.SpecVersion,
|
||||
[CloudNative.CloudEvents.CloudEventAttributes]::DataAttributeName($cloudEvent.SpecVersion),
|
||||
$cloudEvent.Data, $cloudEvent.Extensions.Values)
|
||||
}
|
||||
# Add Headers property to the output object
|
||||
$result | Add-Member -MemberType NoteProperty -Name 'Headers' -Value $headers
|
||||
|
||||
# Add Body property to the output object
|
||||
$result | Add-Member -MemberType NoteProperty -Name 'Body' -Value $bodyData
|
||||
}
|
||||
# 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
|
||||
|
||||
Write-Output $result
|
||||
}
|
||||
# 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
|
||||
|
||||
|
@ -655,136 +657,150 @@ function ConvertFrom-HttpMessage {
|
|||
Converts a http response to a cloud event object
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(
|
||||
Mandatory = $true,
|
||||
ValueFromPipeline = $false,
|
||||
ValueFromPipelineByPropertyName = $false)]
|
||||
[ValidateNotNull()]
|
||||
[hashtable]
|
||||
$Headers,
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(
|
||||
Mandatory = $true,
|
||||
ValueFromPipeline = $false,
|
||||
ValueFromPipelineByPropertyName = $false)]
|
||||
[ValidateNotNull()]
|
||||
[hashtable]
|
||||
$Headers,
|
||||
|
||||
[Parameter(
|
||||
Mandatory = $false,
|
||||
ValueFromPipeline = $false,
|
||||
ValueFromPipelineByPropertyName = $false)]
|
||||
[ValidateNotNull()]
|
||||
$Body)
|
||||
[Parameter(
|
||||
Mandatory = $false,
|
||||
ValueFromPipeline = $false,
|
||||
ValueFromPipelineByPropertyName = $false)]
|
||||
[ValidateNotNull()]
|
||||
$Body)
|
||||
|
||||
PROCESS {
|
||||
$HttpHeaderPrefix = "ce-";
|
||||
$SpecVersionHttpHeader1 = $HttpHeaderPrefix + "cloudEventsVersion";
|
||||
$SpecVersionHttpHeader2 = $HttpHeaderPrefix + "specversion";
|
||||
PROCESS {
|
||||
$HttpHeaderPrefix = "ce-";
|
||||
$SpecVersionHttpHeader = $HttpHeaderPrefix + "specversion";
|
||||
|
||||
$result = $null
|
||||
$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)
|
||||
}
|
||||
# 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 ($Headers['Content-Type'] -ne $null) {
|
||||
$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 = [CloudNative.CloudEvents.CloudEventsSpecVersion]::Default
|
||||
if ($Headers.Contains($SpecVersionHttpHeader1)) {
|
||||
$version = [CloudNative.CloudEvents.CloudEventsSpecVersion]::V0_1
|
||||
}
|
||||
|
||||
if ($Headers.Contains($SpecVersionHttpHeader2)) {
|
||||
if ($Headers[$SpecVersionHttpHeader2][0] -eq "0.2") {
|
||||
$version = [CloudNative.CloudEvents.CloudEventsSpecVersion]::V0_2
|
||||
} elseif ($Headers[$SpecVersionHttpHeader2][0] -eq "0.3") {
|
||||
$version = [CloudNative.CloudEvents.CloudEventsSpecVersion]::V0_3
|
||||
if ($null -ne $Headers['Content-Type']) {
|
||||
$ContentType = $Headers['Content-Type']
|
||||
if ($ContentType -is [array]) {
|
||||
# Get the first content-type value
|
||||
$ContentType = $ContentType[0]
|
||||
}
|
||||
}
|
||||
|
||||
$cloudEvent = New-Object `
|
||||
-TypeName 'CloudNative.CloudEvents.CloudEvent' `
|
||||
-ArgumentList @($version, $null);
|
||||
if ($ContentType.StartsWith([CloudNative.CloudEvents.CloudEvent]::MediaType,
|
||||
[StringComparison]::InvariantCultureIgnoreCase)) {
|
||||
|
||||
$attributes = $cloudEvent.GetAttributes();
|
||||
# Handle Structured Mode
|
||||
$ctParts = $ContentType.Split(';')
|
||||
if ($ctParts[0].Trim().StartsWith(([CloudNative.CloudEvents.CloudEvent]::MediaType) + ([CloudNative.CloudEvents.JsonEventFormatter]::MediaTypeSuffix),
|
||||
[StringComparison]::InvariantCultureIgnoreCase)) {
|
||||
|
||||
# Get attributes from HTTP Headers
|
||||
foreach ($httpHeader in $Headers.GetEnumerator()) {
|
||||
if ($httpHeader.Key.Equals($SpecVersionHttpHeader1, [StringComparison]::InvariantCultureIgnoreCase) -or `
|
||||
$httpHeader.Key.Equals($SpecVersionHttpHeader2, [StringComparison]::InvariantCultureIgnoreCase)) {
|
||||
continue
|
||||
}
|
||||
# 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 ($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);
|
||||
# .NET SDK 'CloudNative.CloudEvents.JsonEventFormatter' type is used
|
||||
# to decode the Structured Mode CloudEvents
|
||||
|
||||
# Abolished structures in headers in 1.0
|
||||
if ($version -ne [CloudNative.CloudEvents.CloudEventsSpecVersion]::V0_1 -and `
|
||||
$headerValue -ne $null -and `
|
||||
$headerValue.StartsWith('"') -and `
|
||||
$headerValue.EndsWith('"') -or `
|
||||
$headerValue.StartsWith("'") -and $headerValue.EndsWith("'") -or `
|
||||
$headerValue.StartsWith("{") -and $headerValue.EndsWith("}") -or `
|
||||
$headerValue.StartsWith("[") -and $headerValue.EndsWith("]")) {
|
||||
$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)
|
||||
|
||||
$jsonFormatter = New-Object 'CloudNative.CloudEvents.JsonEventFormatter'
|
||||
$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
|
||||
}
|
||||
|
||||
$attributes[$name] = $jsonFormatter.DecodeAttribute($version, $name,
|
||||
[System.Text.Encoding]::UTF8.GetBytes($headerValue), $null);
|
||||
} else {
|
||||
$attributes[$name] = $headerValue
|
||||
}
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
if ($Headers['Content-Type'] -ne $null -and $Headers['Content-Type'][0] -is [string]) {
|
||||
$cloudEvent.DataContentType = New-Object 'System.Net.Mime.ContentType' -ArgumentList @($Headers['Content-Type'][0])
|
||||
}
|
||||
$attributes = $cloudEvent.GetAttributes();
|
||||
|
||||
# Get Data from HTTP Body
|
||||
$cloudEvent.Data = $Body
|
||||
# Get attributes from HTTP Headers
|
||||
foreach ($httpHeader in $Headers.GetEnumerator()) {
|
||||
if ($httpHeader.Key.Equals($SpecVersionHttpHeader, [StringComparison]::InvariantCultureIgnoreCase)) {
|
||||
continue
|
||||
}
|
||||
|
||||
$result = $cloudEvent
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
||||
Write-Output $result
|
||||
}
|
||||
# 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
|
|
@ -4,9 +4,9 @@
|
|||
# **************************************************************************
|
||||
|
||||
Describe "ConvertFrom-HttpMessage Function Tests" {
|
||||
BeforeAll {
|
||||
$expectedSpecVersion = '1.0'
|
||||
$expectedStructuredContentType = 'application/cloudevents+json'
|
||||
BeforeEach {
|
||||
$script:expectedSpecVersion = '1.0'
|
||||
$script:expectedStructuredContentType = 'application/cloudevents+json'
|
||||
}
|
||||
|
||||
Context "Converts CloudEvent in Binary Content Mode" {
|
||||
|
@ -77,6 +77,7 @@ Describe "ConvertFrom-HttpMessage Function Tests" {
|
|||
$expectedType = 'test'
|
||||
$expectedSource = 'urn:test'
|
||||
$expectedDataContentType = 'application/xml'
|
||||
$expectedId = 'test-id-2'
|
||||
$expectedData = [Text.Encoding]::UTF8.GetBytes('<much wow="xml"/>')
|
||||
|
||||
$headers = @{
|
||||
|
@ -84,6 +85,7 @@ Describe "ConvertFrom-HttpMessage Function Tests" {
|
|||
'ce-specversion' = $expectedSpecVersion
|
||||
'ce-type' = $expectedType
|
||||
'ce-source' = $expectedSource
|
||||
'ce-id' = $expectedId
|
||||
}
|
||||
|
||||
$body = $expectedData
|
||||
|
@ -95,6 +97,7 @@ Describe "ConvertFrom-HttpMessage Function Tests" {
|
|||
|
||||
# Assert
|
||||
$actual | Should -Not -Be $null
|
||||
$actual.Id | Should -Be $expectedId
|
||||
$actual.Type | Should -Be $expectedType
|
||||
$actual.Source | Should -Be $expectedSource
|
||||
$actual.DataContentType | Should -Be $expectedDataContentType
|
||||
|
@ -105,6 +108,81 @@ Describe "ConvertFrom-HttpMessage Function Tests" {
|
|||
|
||||
$actualData | Should -Be $expectedData
|
||||
}
|
||||
|
||||
It 'Returns null when ce-id is not specified' {
|
||||
# Arrange
|
||||
$expectedType = 'test'
|
||||
$expectedSource = 'urn:test'
|
||||
$expectedDataContentType = 'application/xml'
|
||||
$expectedData = [Text.Encoding]::UTF8.GetBytes('<much wow="xml"/>')
|
||||
|
||||
$headers = @{
|
||||
'Content-Type' = @($expectedDataContentType, 'charset=utf-8')
|
||||
'ce-specversion' = $expectedSpecVersion
|
||||
'ce-type' = $expectedType
|
||||
'ce-source' = $expectedSource
|
||||
}
|
||||
|
||||
$body = $expectedData
|
||||
|
||||
# Act
|
||||
$actual = ConvertFrom-HttpMessage `
|
||||
-Headers $headers `
|
||||
-Body $body
|
||||
|
||||
# Assert
|
||||
$actual | Should -Be $null
|
||||
}
|
||||
|
||||
It 'Returns null when ce-source is not specified' {
|
||||
# Arrange
|
||||
$expectedType = 'test'
|
||||
$expectedDataContentType = 'application/xml'
|
||||
$expectedId = 'test-id-3'
|
||||
$expectedData = [Text.Encoding]::UTF8.GetBytes('<much wow="xml"/>')
|
||||
|
||||
$headers = @{
|
||||
'Content-Type' = @($expectedDataContentType, 'charset=utf-8')
|
||||
'ce-specversion' = $expectedSpecVersion
|
||||
'ce-type' = $expectedType
|
||||
'ce-id' = $expectedId
|
||||
}
|
||||
|
||||
$body = $expectedData
|
||||
|
||||
# Act
|
||||
$actual = ConvertFrom-HttpMessage `
|
||||
-Headers $headers `
|
||||
-Body $body
|
||||
|
||||
# Assert
|
||||
$actual | Should -Be $null
|
||||
}
|
||||
|
||||
It 'Returns null when ce-type is not specified' {
|
||||
# Arrange
|
||||
$expectedSource = 'urn:test'
|
||||
$expectedDataContentType = 'application/xml'
|
||||
$expectedId = 'test-id-4'
|
||||
$expectedData = [Text.Encoding]::UTF8.GetBytes('<much wow="xml"/>')
|
||||
|
||||
$headers = @{
|
||||
'Content-Type' = @($expectedDataContentType, 'charset=utf-8')
|
||||
'ce-specversion' = $expectedSpecVersion
|
||||
'ce-source' = $expectedSource
|
||||
'ce-id' = $expectedId
|
||||
}
|
||||
|
||||
$body = $expectedData
|
||||
|
||||
# Act
|
||||
$actual = ConvertFrom-HttpMessage `
|
||||
-Headers $headers `
|
||||
-Body $body
|
||||
|
||||
# Assert
|
||||
$actual | Should -Be $null
|
||||
}
|
||||
}
|
||||
|
||||
Context "Converts CloudEvent in Structured Content Mode" {
|
||||
|
@ -245,5 +323,29 @@ Describe "ConvertFrom-HttpMessage Function Tests" {
|
|||
-Body $body } | `
|
||||
Should -Throw "*Unsupported CloudEvents encoding*"
|
||||
}
|
||||
|
||||
It 'Returns null when no Content-Type header' {
|
||||
# Arrange
|
||||
|
||||
$expectedType = 'test'
|
||||
$expectedSource = 'urn:test'
|
||||
$expectedDataContentType = 'application/xml'
|
||||
$expectedData = [Text.Encoding]::UTF8.GetBytes('<much wow="xml"/>')
|
||||
$structuredJsonBody = @{
|
||||
'specversion' = $expectedSpecVersion
|
||||
'type' = $expectedType
|
||||
'source' = $expectedSource
|
||||
'datacontenttype' = $expectedDataContentType
|
||||
'data' = $expectedData
|
||||
}
|
||||
|
||||
$body = [Text.Encoding]::UTF8.GetBytes(($structuredJsonBody | ConvertTo-Json))
|
||||
|
||||
# Act & Assert
|
||||
$ce = ConvertFrom-HttpMessage `
|
||||
-Headers @{} `
|
||||
-Body $body
|
||||
$ce | Should -Be $null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue