Suggestions, proxy kind of thing

Hi There!

I have devices in the field, running their own servicestack Api on an embedded device.
These devices connect to a internet gateway, and have their own channel there to communicate with the server by ServerEvents

Would it be possible to connect by some App or something else, to that gateway server, to perform API Requests that would to be redirected to this Embedded client in the field, make it produce a result, and answering this to the Gateway, wich will return it to the App client?

I currently already use something like this, but use a standard socket connection to a server, and serialize / deserialize gateway webserver requests using protobuff, and make the embedded client return a result, wich i then respond to the GUI client that asked it to the server in the first place.

I want to make it nicer.

  • Use a Global Handler, to accept requests to the Gateway, using the Route’s that are configured in the EmbeddedClient’s Dto Library, and re-route them somehow.
  • Use a reverse SSH tunnel to connect to the embedded client’s HTTP Api directly, and using some kind of URL Rewrite / PortForwarding system on a webserver.

I’d rather make it a ServiceStack Only party, but i dont know what’s be best angle…

Thanks for brainstorming with me!

It’s hard to follow this from just the description without some kind of diagram, but does it look something like this?

Embedded Device (SS) <-> Gateway (SS) <-> App (SS Client)

If the goal is for the App to be able to connect from the App to the embedded device by the Gateway you can just have all the embedded Device and App clients all connect to the same Server Events channel on the Gateway then provide a Service that allows Direct Messages to a user that way they can send direct messages to each other.

We do something similar in our Real-time Networked Time Traveller example where we enable Users to send direct messages to each other to return a clients initial state.

Another approach could be to use ServiceStack Messaging where you can use a Reply MQ pattern where the App client can make an MQ Request to the Gateway, which handles the message sends a Server Event to the embedded device with the temp queue name (ReplyTo in the IMessage), the embedded client then calls a Service on the Gateway passing the ReplyTo MQ name which the Gateway uses to send a response to. The App client is blocking on the MQ Broker listening for a response on its ReplyTo temp queue, so it looks something like:

Embedded Device (SS) <-> Gateway (SS) <-> MQ Broker <-> App (SS Client)

Going through an MQ Broker makes it a bit more heavy weight than the first option just using Server Events but would still be a viable option.

Yes… i’m curious about RabbitMq, i was hoping i could use it here, also from a scalability pov.

Though im curious, it seems i only need the Gateway Server with ServerEvents to communicate about the temp queue name to the Embedded Device. I can’t just use a fixed queue name for a client for example ? Or does the temp queue only functions as the temporary ‘session’ the request/reply is served in, existing as long as the request/reply does?

You couldn’t use a fixed queue for all App clients as you wouldn’t be able to guarantee that the right App client would receive the message. You could use a fixed queue for each App client, but then you’ll need to correlate which message in the queue belongs to which App client request, so instead of passing a replyTo queue name you’d pass a correlationId (e.g. Guid) originating from the App that they can use to correlate any responses they receive.

Using a temp queue (non durable, exclusive, auto-delete) essentially takes care of the correlating the request for you since the only message that will be sent to the temp queue is the response for the request. But yeah I’d expect using a fixed queue for each App client would be more efficient, but you’d need to correlate the Responses for each Request that was sent.

Thnx! I will try what fits best!

Hi Mythz,

i’m trying to come up with a way to make this work:

i have a gateway server, on which i could use a FallbackRoute. In that request handler, i would like to be able to determine what what actual request dto type was, and parse it to that. In that typed shape i would like to forward it to the client by SSE and MQ.

Since al my Routes are defined in the Client’s Dto Object, and i have that Dto object referenced in the Gateway, i should be able to know what the original request type was, and Deserialize it to that type, right in my Fallback Service handler.

Having:

  [FallbackRoute("/{Path}")]
    public class Fallback
    {
        public string Path { get; set; }
    }

    public class ServerServices : Service
    {
        public object Any(Fallback request)
        {
            // Deserialize Request to be a typed class again.
            // Forward it to client by MQ or ServerEvents
            // Wait for answer, and return that as response to this request.
        }
    }

Can you point me in the right direction, how can i make it a typed object in here ?

Not sure what you mean by determining the Request DTO type? The Fallback is the Request DTO Type and its [FallbackRoute] only gets called if it doesn’t match any existing Routes which means there is no Request DTO Type.

Why aren’t you sending the Typed Request DTO and handling it in ServiceStack as normal? that way you can forward the Request DTO as a typed model:

public object Any(MyRequest request) =>  ServiceClient.Send(request);

If you’re trying to send everything to one Service there’s no special magic in ServiceStack that will help since the Route is what determines which Request DTO to deserialize into which is lost when going through a generic route. You’re basically going to need to explicitly specify the Type property to capture the Request DTO Type and a Body property to capture the serialized Request DTO body, my preference would be JSV since encoding JSON in a JSON string will become verbose with double-escaping.

Yes, I can still it like normal, however i’d have to create ‘forward only’ implementations for all requests that are in the client service. Somebody once told me; a good programmer is a lazy one…

I will have to make al those Service’s twice then, in the client handling it like normal, and in de Gateway, using it for forwarding purposes only.

Thanks!

You could use a generic proxy service to forward the request through as-is to a downstream HTTP Server, but it would be a “dumb” pass through and you still wont be able to know the Request DTO Type without an extra argument.