Is anyone aware of any example C# code anywhere for consuming any of the streaming API?
I am a +1 on this topic, I have been trying to find examples - mainly so I can debug whats wrong with mine… I am using an HttpClient() and I cant seem to get it to work with the streaming api and I am wondering if I should give up and use something else…
Here’s a naive example using TcpClient. You’ll need to weigh up whether you want to validate the remote certificate and also add error handling PLUS restarting the stream when it disconnects (as CH do daily).
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Buffers;
using System.IO.Pipelines;
string _host = "stream.companieshouse.gov.uk";
int _port = 443;
var linefeed = Encoding.UTF8.GetBytes("\n").First();
string CHStream = "companies";
StringBuilder sb = new StringBuilder();
sb.AppendLine($"GET https://{_host}/{CHStream} HTTP/1.0");
sb.AppendLine("Host: stream.companieshouse.gov.uk");
sb.AppendLine("Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
sb.AppendLine("Accept: application/json");
sb.AppendLine();
using TcpClient _tclient = new TcpClient(_host, _port);
NetworkStream _netStream = _tclient.GetStream();
var mempool = MemoryPool<byte>.Shared;
mempool.Rent(8192);
ReadOnlySequence<byte> buffer = new();
ReadOnlySequence<byte> line = new();
PipeReader? pReader = null;
using (SslStream ssl = new SslStream(_netStream, true))
{
ssl.AuthenticateAsClient(_host, null, SslProtocols.Tls12, true);
ssl.Write(Encoding.UTF8.GetBytes(sb.ToString()));
ssl.Flush();
pReader = PipeReader.Create(ssl, new StreamPipeReaderOptions(pool: mempool, bufferSize: 6144, minimumReadSize: 3072, leaveOpen: true));
ReadResult pipeReadResult = await pReader.ReadAsync();
buffer = pipeReadResult.Buffer;
while (ssl.CanRead == true && pipeReadResult.IsCompleted == false)
{
while (buffer.Length > 0 && ChannelReadLine(ref buffer, ref line, ref linefeed))
{
if (line.Length > 3)
{
//your payload is in line
}
pReader.AdvanceTo(buffer.Start, buffer.End);
}
pipeReadResult = await pReader.ReadAsync();
}
//here we are exiting loop (e.g daily reset form companies house)
await pReader!.CompleteAsync();
}
static bool ChannelReadLine(ref ReadOnlySequence<byte> buffer, ref ReadOnlySequence<byte> target, ref byte linefeed)
{
try
{
if (buffer.IsEmpty || buffer.Length == 0)
return false;
SequencePosition? position1 = buffer.PositionOf(linefeed);
if (position1 == null)
return false;
target = new ReadOnlySequence<byte>(buffer.Slice(0, position1.Value).ToArray()); //read to the first occurrance on a line feed
buffer = buffer.Slice(buffer.GetPosition(1, position1.Value)); //remove the part of the buffer read into target
return true;
}
catch (InvalidOperationException)
{
return false;
}
}