dougmoscrop / serverless-http

Use your existing middleware framework (e.g. Express, Koa) in AWS Lambda 🎉
Other
1.74k stars 167 forks source link

Xmlrpc support ? #282

Open mjgs opened 1 year ago

mjgs commented 1 year ago

I’m trying to get an xmlrpc server running in a serverless function.

I’ve had very good experience in the past with serverless-http and express apps, so I figured I’d try to use it since as far as I can tell xmlrpc uses http under the hood.

I forked the repo and made a few attempts at modifying the getFramework function, adding a new check of the app object.

I’m out of my depth, just want a bit of advice before proceeding. Is this even possible?

dougmoscrop commented 1 year ago

It might be simpler to avoid modifying getFramework, and just extract this: https://github.com/baalexander/node-xmlrpc/blob/d9c88c4185e16637ed5a22c1b91c80e958e8d69e/lib/server.js#L38 in to your own app,

so you'd do something like (untested, sorry)

const EventEmitter = require('events').EventEmitter
const Serializer = require('xmlrpc/lib/serializer')
const Deserializer = require('xmlrpc/lib/deserializer')

const rpc = new EventEmitter()

rpc.on('foo', (error, params, callback) => {
})

module.exports.handler = serverlessHttp((request, response) => {
  const deserializer = new Deserializer()
  deserializer.deserializeMethodCall(request, function(error, methodName, params) {
    if (Object.prototype.hasOwnProperty.call(rpc._events, methodName)) {
       rpc.emit(methodName, null, params, function(error, value) {
          response.writeHead(200, {'Content-Type': 'text/xml'})
          response.end(error === null
            ? Serializer.serializeMethodResponse(value)
            : Serializer.serializeFault(error)
        })
    } else {
      response.writeHead(404)
      response.end()
    }
  })  
})
mjgs commented 1 year ago

@dougmoscrop Thanks for the reply and code snippet idea. I really appreciate it.

So if I’m understanding correctly serverless-http just requires a handler function, and your idea is to basically extract that from the xmlrpc library, but additionally to create a separate independent event emitter. And then instead of adding the handlers for each method I want to call via xmlrpc protocol onto the xmlrpc object, I just use the separate event emitter.

Am I understanding correctly?

dougmoscrop commented 1 year ago

yep!

dougmoscrop commented 1 year ago

also the event emitter 'style' is just one way of doing it.. you could come up with your own dispatch scheme (such as just having a plain object/hash to lookup methodName), if you prefer, and just rely on xmlrpc for the serialize/deserialize.

mjgs commented 1 year ago

Great advice thank you.

Do I end up loosing anything by extracting just the handle method? I’m thinking specifically about https, but maybe there’s something else. Btw it will be running in Netlify so https is configured by default.

How will that work in this setup, is it just as simple as using https in the url that I give to the client?

dougmoscrop commented 1 year ago

Right, in serverless functions, especially AWS Lambda-based ones, nothing is technically "listening", so the whole idea of HTTPS is externalized to your process and your code (your handler) is literally just a function that gets called by the runtime no different than any other function. This library is kind of like an abstraction that undoes another abstraction, if that makes sense.

I originally wrote it because we were fairly early adopters of AWS Lambda and wanted to be able to eject in to a Docker container/server with little to no changes (my attempt at Hexagonal architecture)

p.s. not sure if you've seen https://getampt.com but I will shamelessly plug it here :)

mjgs commented 1 year ago

Thanks for the background info. I think I’m starting to understand how the pieces are situated now.

The ‘ejection’ capability was one of the reasons I started using serverless-http initially. It’s really cool to be able to run normal express apps locally but then just seamlessly get them running in the cloud.

Thanks for the hexagonal architecture link, looks interesting, will definitely look more into that later. The last few projects I’ve built have been very influenced by domain driven design, especially when it comes to using layers, adapters and reusing code.

Getampt sounds really cool :)