server icon indicating copy to clipboard operation
server copied to clipboard

Question: Extensibility to use other transport protocol?

Open fallenwood opened this issue 3 years ago • 2 comments

We are using version 5.x, and just realized version 7.x has been released, with lots of breaking changes. Of which the most confusing one for me is, looks like subscription implementation is hidden now, and I can no longer implement my own subscription transport such as ServerSentEvents (e.g. my toy project at https://github.com/fallenwood/GraphQL.Server.Transports.ServerSentEvents).

So my question is, is there any guide for me to add another transport for version 6.x/7.x?

fallenwood avatar Sep 24 '22 09:09 fallenwood

Are you implementing the 'Single connection mode' as documented in the protocol ? Or the 'Distinct connection mode' ?

I'm not very familiar with GraphQL over SSE or F# but in general it seems that:

  1. The 'Distinct connection mode' would be extremely easy to implement, but suffers from the fact that clients cannot send authentication headers along with the HTTP request. I'd probably just override GraphQLHttpMiddleware.HandleRequestAsync and see if the HTTP Accept header is text/event-stream. If not, call the base method, otherwise, execute the request and tie the subscription responses to the response stream. Easy. No need to deal with any of the WebSocket handling classes at all. Batched requests should be disabled in this scenario.

  2. The 'Single connection mode' could potentially reuse some of the functionality within BaseSubscriptionServer. One problem is that the message data type used is OperationMessage, which is incompatible with the SSE protocol. However, it maintains its connection to the endpoint via IOperationMessageProcessor and IWebSocketConnection. As such, the implementation of WebSocketConnection (which is what reads/writes messages to the WebSocket endpoint) could be rewritten to translate the messages in the protocol to OperationMessage messages quite easily. You'd still have to write the code that match IDs to a dictionary of active connections and forwards the message for starting/stopping messages through, etc. Even so, it may be questionable as to how much of the code within BaseSubscriptionServer is practically reusable.

Looks like subscription implementation is hidden now

Well, it's not really hidden -- almost all of the classes are public. We have simply rewritten it from scratch and removed the dependencies on third party libraries such as System.Threading.Tasks.Dataflow and System.Reactive. It's also been integrated into the main project to simplify configuration.

There is a section within the readme that gives a brief overview of all of the subscription-related classes at the below link, and every method has descriptive XML comments. Feel free to ask if anything is unclear.

https://github.com/graphql-dotnet/server#websocket-handler-classes

Shane32 avatar Sep 24 '22 14:09 Shane32

Thanks for answering. It should be 2) The 'Single connection mode'. I'll follow the section to see if I need to rewrite all the code.


I took a quick look at the code today, I need to write my own IWebSocketConnection (maybe it should not rename to something more general?) and IOperationMessageProcessor, could ReusableMemoryReaderStream and AsyncMessagePump<T> be public for easy extension?

fallenwood avatar Sep 24 '22 23:09 fallenwood

@fallenwood Do you need more help here or we may close?

sungam3r avatar Apr 08 '23 19:04 sungam3r

FYI, AsyncMessagePump is available within the Shane32.AsyncResetEvents nuget package

Shane32 avatar Apr 08 '23 19:04 Shane32

FYI, AsyncMessagePump is available within the Shane32.AsyncResetEvents nuget package

Thanks for the infos :)

@fallenwood Do you need more help here or we may close?

I am not working this area these days. I can close it, thanks for your help

fallenwood avatar Apr 09 '23 00:04 fallenwood