Kong: [request] pushpin plugin

Created on 29 May 2015  路  13Comments  路  Source: Kong/kong

To make it easier to deploy Kong and Pushpin together, there should be a way to route traffic to Pushpin as well as have its configuration inherited from Kong's configuration.

Some ideas for the plugin:

1) Route incoming traffic (HTTP requests and WebSocket connections) to Pushpin.
2) Automatically generate a Pushpin routes file, using Kong's origin server settings, so that the user doesn't have to configure it independently.
3) Maybe the plugin could start Pushpin automatically, and shut it down when Kong shuts down?

ideintegration idenew plugin proposal

Most helpful comment

The necessary Pushpin changes have been implemented in the kong-stuff branch of the pushpin git.

All 13 comments

Which integration did we decide to start with? After we know exactly what to build, we can brainstorm on how to build it.

I'd say a minimum viable plugin should do the following:

1) Route all traffic to Pushpin instead of the API's configured origin server.
2) Rewrite Pushpin's routes file with the API origin server information.

This would be enough for a user to create a "Kong -> Pushpin -> Backend" proxy chain without any additional configuration.

+1

I think the MVP I posted above is still the simplest plan forward, with the addition that the plugin should launch the Pushpin server on startup (and terminate it when Kong terminates). This would be the simplest user experience because then the user wouldn't have to manage a separate service.

Later on we could consider how to run the code in the same process (via a libpushpin library with C interface, that the Kong plugin loads), but for now we'll have the plugin do some process management.

Tonight we also talked about the possibility of Kong/Nginx handling the outbound proxying. This way, other plugins get a chance to do post processing on whatever requests Pushpin might send out to the API backend. So instead of Pushpin doing the proxying directly to the API backend, it would feed proxied requests back into Kong. Perhaps this could be done by having the plugin listen on a private port that Pushpin could be pointed at for outbound requests.

Getting WebSockets to work through Pushpin is probably not too hard. Detect if an incoming request is a WebSocket connection, and if it is then just proxy it out without invoking any of the plugins (and if the Pushpin plugin is in use, then that would mean proxying to Pushpin). However, for this to be of much value, you'll want to be able to run plugin processing, especially Auth related stuff for example. Now, if we supported feeding Pushpin's own proxied requests back into Kong, and Pushpin's WebSocket->HTTP conversion mode is enabled, then Kong could run all the normal plugins against the HTTP requests generated by Pushpin. This should allow the Auth plugin to work.

An auth failure flow could look like this:

  1. Kong receives WebSocket request, proxies the entire session as a passthrough to Pushpin.
  2. Pushpin generates HTTP request containing WebSocket OPEN event and sends to Kong.
  3. Kong invokes Auth plugin which inspects the request. There is no valid auth key header so it replies with 403 Forbidden.
  4. Pushpin receives the HTTP response from Kong, determines it is an error (rather than code 101), and sends it as a WebSocket error response back into Kong through the original WebSocket passthrough.
  5. Kong relays the error response back to the client (because it's just a passthrough).

So the two big questions to answer are:

1) Is there a practical way for Pushpin to proxy outbound requests back through Kong without causing a loop?
2) Is it easy for Kong to route incoming WebSocket connections as a passthrough to the origin server target?

Oh and there is another big question:

3) If HTTP streaming is used, will this cause any buffering issues in Kong? Pushpin might service a response that never ends. We'd want to make sure Kong doesn't buffer an unbounded response and run the machine out of memory.

@jkarneges these are all valid questions and some of them are related to #218 - with a Pushpin plugin we can write any kind of logic and avoid loops. I guess at this point we should try to experiment with it and see what happens, since we don't know what we don't know.

I would say first thing would be investigating Kong's support for Websockets, and then introduce Pushpin into the equation.

We discussed this issue today and decided that Pushpin should always live in front of Kong, and that the Pushpin plugin would configure Pushpin how to behave as well as act as a publish relay so that published traffic can be captured. Kong will configure Pushpin via HTTP. It will be possible to set up the plugin per-API, with independent pubsub channel scopes.

Tasks:

  • Pushpin needs a way to have its HTTP server and route information configured via its control interface. To start out, we'll just need a way to tell Pushpin to route all traffic to a Kong target addr/port, and to allow the backend to assert its own route ID (see below). Adding the plugin will trigger a POST request to the /config/ endpoint of Pushpin's control URI (e.g. http://localhost:5561/config/), containing post fields.
  • Pushpin needs a way for the backend to specify its route ID on every HTTP response. Let's use Grip-Channel-Prefix. This header should also be stripped before relaying to clients. This header should only be included if the request included a Grip-Sig header with a JWT using Pushpin's secret key (that also needs to be added in the plugin configuration).
  • Kong needs a plugin that when configured can make a configuration request to Pushpin. Ideally this request should be synchronous so that if there is an error configuring Pushpin then the user will receive an error while making the Kong config request.
  • The plugin needs to expose a publish interface similar to Pushpin. Published data should be relayed to Pushpin's own publish interface (the /publish/ endpoint of Pushpin's control URI). There is an opportunity here for the published data to be inspected by Kong analytics. The endpoint could be POST /pushpin/publish, and only authorized clients can invoke it (we need some sort of security on this endpoint).
  • The plugin needs to modify HTTP responses to include Grip-Channel-Prefix based on the API ID. If the response already contained this header, prepend to it.
  • The plugin needs to prefix publish channels with the API ID.

Next steps:

  • Provide the specification for the HTTP API that the plugin will invoke when configuring the plugin for the first time
  • Provide the specification for the publishing HTTP API that will be invoked by the /pushpin/publish endpoint.

Configuration:

POST /config/ HTTP/1.1
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded

target_host=127.0.0.1&target_port=8000&target_ssl=false&target_over_http=true
HTTP/1.1 200 OK
Content-Type: text/plain

Updated

Publishing:

POST /publish/ HTTP/1.1
Host: 127.0.0.1
Content-Type: application/json

{
  "items": [
    {
      "channel": "foo",
      "id": "item-1",
      "formats": {
        "http-stream": {
          "content": "pushing a line\n"
        }
      }
    }
  ]
}
HTTP/1.1 200 OK
Content-Type: text/plain

Published

A publish request may contain multiple items to publish, and each item may contain a number of fields. Rather than have Kong be fully aware of all possible item fields, it should copy the whole JSON and modify it before relaying to Pushpin. The only modification needed is to prepend the channel with the route ID (which we will say is the API ID + hyphen). If channel is "foo" and API ID is "123", then the channel becomes "123-foo". If a publish request contains more than one item, Kong should be sure to rewrite the channel of all items.

The necessary Pushpin changes have been implemented in the kong-stuff branch of the pushpin git.

Hi guys, some update on this? it will be great!

Hi @jorgecuesta , no update on our end but thanks for the reminder about this. The branch is outdated and we'll try to find time to clean it up.

Was this page helpful?
0 / 5 - 0 ratings