mirror of
https://github.com/Icinga/icinga-powershell-framework.git
synced 2026-02-03 12:19:29 -05:00
141 lines
5.1 KiB
PowerShell
141 lines
5.1 KiB
PowerShell
function Read-IcingaRESTMessage()
|
|
{
|
|
param(
|
|
[string]$RestMessage = $null,
|
|
[hashtable]$Connection = $null
|
|
);
|
|
|
|
# Just in case we didn't receive anything - no need to
|
|
# parse through everything
|
|
if ([string]::IsNullOrEmpty($RestMessage)) {
|
|
return $null;
|
|
}
|
|
|
|
Write-IcingaDebugMessage (
|
|
[string]::Format(
|
|
'Receiving client message{0}{0}{1}',
|
|
(New-IcingaNewLine),
|
|
$RestMessage
|
|
)
|
|
);
|
|
|
|
[hashtable]$Request = @{ };
|
|
$RestMessage -match '(.+) (.+) (.+)' | Out-Null;
|
|
|
|
$Request.Add('Method', $Matches[1]);
|
|
$Request.Add('FullRequest', $Matches[2]);
|
|
$Request.Add('RequestPath', @{ });
|
|
$Request.Add('RequestArguments', @{ });
|
|
|
|
#Path
|
|
$PathMatch = $Matches[2];
|
|
$PathMatch -match '((\/[^\/\?]+)*)\??([^\/]*)' | Out-Null;
|
|
$Arguments = $Matches[3];
|
|
$Request.RequestPath.Add('FullPath', $Matches[1]);
|
|
$Request.RequestPath.Add('PathArray', $Matches[1].TrimStart('/').Split('/'));
|
|
|
|
$Matches = $null;
|
|
|
|
# Arguments
|
|
$ArgumentsSplit = $Arguments.Split('&');
|
|
$ArgumentsSplit+='\\\\\\\\\\\\=FIN';
|
|
foreach ( $Argument in $ArgumentsSplit | Sort-Object -Descending) {
|
|
if ($Argument.Contains('=')) {
|
|
$Argument -match '(.+)=(.+)' | Out-Null;
|
|
If (($Matches[1] -ne $Current) -And ($NULL -ne $Current)) {
|
|
$Request.RequestArguments.Add( $Current, $ArgumentContent );
|
|
[array]$ArgumentContent = $null;
|
|
}
|
|
$Current = $Matches[1];
|
|
[array]$ArgumentContent += ($Matches[2]);
|
|
} else {
|
|
$Request.RequestArguments.Add( $Argument, $null );
|
|
}
|
|
}
|
|
|
|
# Header
|
|
$Request.Add( 'Header', @{ } );
|
|
$SplitString = $RestMessage.Split("`r`n");
|
|
|
|
foreach ( $SingleString in $SplitString ) {
|
|
if ( ([string]::IsNullOrEmpty($SingleString) -eq $FALSE) -And ($SingleString -match '^{.+' -eq $FALSE) -And $SingleString.Contains(':') -eq $TRUE ) {
|
|
$SingleSplitString = $SingleString.Split(':', 2);
|
|
$Request.Header.Add( $SingleSplitString[0], $SingleSplitString[1].Trim());
|
|
}
|
|
}
|
|
|
|
$Request.Add('ContentLength', [int](Get-IcingaRESTHeaderValue -Header 'Content-Length' -Request $Request));
|
|
|
|
$Matches = $null;
|
|
|
|
# Body
|
|
$RestMessage -match '(\{(.*\n)*}|\{.*\})' | Out-Null;
|
|
|
|
# Store your messag body inside a stringbuilder object
|
|
$MessageBody = New-Object 'System.Text.StringBuilder';
|
|
|
|
# Our message is not complete
|
|
if ($null -eq $Matches) {
|
|
# Try to figure out if we received parts of your body from the already read message
|
|
$RestMsgArray = $RestMessage.Split("`r`n");
|
|
[bool]$EmptyLine = $FALSE;
|
|
[bool]$BeginBody = $FALSE;
|
|
|
|
foreach ($entry in $RestMsgArray) {
|
|
if ($BeginBody) {
|
|
$MessageBody.Append($entry) | Out-Null;
|
|
continue;
|
|
}
|
|
|
|
if ([string]::IsNullOrEmpty($entry)) {
|
|
Write-IcingaDebugMessage `
|
|
-Message 'Found end of header, lets check for body elements';
|
|
|
|
# In case we found two empty lines in a row, we found our body
|
|
if ($EmptyLine) {
|
|
$BeginBody = $TRUE;
|
|
continue;
|
|
}
|
|
|
|
# A first empty line means we found a possible header end
|
|
$EmptyLine = $TRUE;
|
|
} else {
|
|
#Reset the empty line in case the next line contains content
|
|
$EmptyLine = $FALSE;
|
|
}
|
|
}
|
|
|
|
Write-IcingaDebugMessage `
|
|
-Message 'We partially received the body of the message, but it might be incomplete. Lets check. Read body length' `
|
|
-Objects $MessageBody.Length, $MessageBody.ToString();
|
|
} else {
|
|
# Our message is already complete
|
|
$Request.Add('Body', $Matches[1]);
|
|
}
|
|
|
|
# We received a content length, but couldn't load the body. Some clients will send the body as separate message
|
|
# Lets try to read the body content
|
|
if ($null -ne $Connection) {
|
|
if ($Request.ContainsKey('ContentLength') -And $Request.ContentLength -gt 0 -And ($Request.ContainsKey('Body') -eq $FALSE -Or [string]::IsNullOrEmpty($Request.Body))) {
|
|
|
|
Write-IcingaDebugMessage `
|
|
-Message 'The message body was not send or incomplete. Received body size and content' `
|
|
-Objects $MessageBody.Length, $MessageBody.ToString();
|
|
|
|
# In case we received party of the message earlier, read the remaining bytes from the message
|
|
# and append it to our body
|
|
$MessageBody.Append(
|
|
(Read-IcingaTCPStream -Client $Connection.Client -Stream $Connection.Stream -ReadLength ($Request.ContentLength - $MessageBody.Length))
|
|
) | Out-Null;
|
|
|
|
# Add our fully read message to our body object
|
|
$Request.Body = $MessageBody.ToString();
|
|
|
|
# Some debug output
|
|
Write-IcingaDebugMessage -Message 'Full request dump' -Objects $Request;
|
|
Write-IcingaDebugMessage -Message 'Body Content' -Objects $Request.Body;
|
|
}
|
|
}
|
|
|
|
return $Request;
|
|
}
|