http-party / node-http-proxy

A full-featured http proxy for node.js
https://github.com/http-party/node-http-proxy
Other
13.95k stars 1.98k forks source link

Example for koa with websockets #1156

Open naturalethic opened 7 years ago

naturalethic commented 7 years ago

It took me a couple hours this morning to figure this all out, so I'd like to document it here, and with some guidance from the maintainer I am willing to provide a PR for either the documentation or examples directory of this.

This code snippet provides the basic setup for getting node-http-proxy to work with koa@2 including websockets.

import Koa from 'koa'
import httpProxy from 'http-proxy'

const koa = new Koa()
const proxy = httpProxy.createProxyServer()

koa.use(ctx => {
  ctx.respond = false # Required to prevent koa from sending out headers
  proxy.web(ctx.req, ctx.res, { target: 'http://localhost:8080' })
})

const server = koa.listen(8000)

server.on('upgrade', (req, socket, head) => {
  proxy.ws(req, socket, head, { target: 'http://localhost:8080' })
})
zweifisch commented 7 years ago

good to know that http-proxy works with koa

linus-amg commented 6 years ago

Any idea how to use a koa-middleware instead of server.on('upgrade')? Because I'd like to forward something from my koa context.

naturalethic commented 6 years ago

Take a look at this project: https://github.com/VanCoding/koa-upgrade -- it looks like that will allow you to check in the regular middleware chain for an upgrade request. Let me know how it goes.

linus-amg commented 6 years ago

Hi, I tried koa-upgrade when I read this issue, but it is not doing what I expected, I found another workaround for my problem so I don't need koa-context. Thank you very much though for your response.

naturalethic commented 6 years ago

No problem!

patdaman commented 6 years ago

@componentDidMount : if you don't mind, what did you do for the workaround?
I can find multiple ways to proxy, but I have not been successful with the middleware chain proxying websockets to one port, and http to another. As a standalone proxy server I can use http-proxy-rules. Thanks!

linus-amg commented 6 years ago

@patdaman the http context in our case contains an already resolved session object (from a jwt) and we wanted to use that resolved session before proxying with proxy.ws to log parts of the session (like user id). Since we got no access to that koa-middleware context, we now resolve the session again when proxying WebSocket requests, we can only do that because it does not depend on database access, otherwise we would find it too round-trippy. I guess that won't help you much, sorry.

patdaman commented 6 years ago

Thanks for the feedback! I am now processing the entire request in the middleware, then sending a new Client websocket directly from the server containing the received message. This is how I was handling specific requests that required manipulation, but obviously not as efficient for the proxy only piece, especially having to keep two tunnels open for one connection.
I will have to come up with a solution to this before we scale the app, likely in another month or two. I'll post here if I can figure it out!

Disorrder commented 5 years ago

Thank you! How did you figured out ctx.respond = false? This is actually what I missed and almost give up.

naturalethic commented 5 years ago

@Disorrder You'd have to go back in time and ask me then :)

tangdaohai commented 5 years ago

you can do this:

// typescript
import { Context, Next } from 'koa'
import httpProxy from 'http-proxy'

const app = new Koa()

function webProxy (ctx: Context, option: httpProxy.ServerOptions): Promise<void | Error> {
  return new Promise((resolve, reject) => {
    ctx.res.on('finish', resolve)
    Proxy.web(ctx.req, ctx.res, option, reject)
  })
}
// ...

app.use(async (ctx: Context, next: Next) => {
  try {
      await webProxy(ctx, { target: 'http://xxxxx:xxx' })
    } catch (e) {
       // do something...
    } finally {
      next()
    }
})
allenlongbaobao commented 3 years ago

i found post method can't be proxyed, anyone have idea?