Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolving Digest Auth challenge in middleware using events? #1648

Open
esbenvb opened this issue Sep 18, 2023 · 1 comment
Open

Resolving Digest Auth challenge in middleware using events? #1648

esbenvb opened this issue Sep 18, 2023 · 1 comment

Comments

@esbenvb
Copy link

esbenvb commented Sep 18, 2023

I'm using http-proxy to make the MJPEG streams from some internal systems (IP cameras) available on a web portal, which only has port 80 available to access the backend. This works pretty well with this code.

  const generalProxy = httpProxy.createProxyServer()

  app.use('/proxy/:url', (req, res) => {
    // Example URL: http://localhost:8000/proxy/http%3A%2F%2F192.168.140.21%2Fmjpg%2Fvideo.mjpg%3Fresolution%3D80x80
    const { url } = req.params
    if (!url || typeof url !== 'string') {
      res.status(406).send('Missing URL')
      return
    }
    generalProxy.web(req, res, { target: url })
  }

However, now I need to target a service that requires Digest Auth, using a client which does not support Digest Auth. Disabling Digest Auth or using Basic Auth on the IP cameras is not an option, unfortunately.

I have been looking at the proxyRes and proxyReq middleware events, and think that I might be able to do something like this:

if target responds with 401:
  get Digest Auth header from response
  use a Digest Auth module to resolve the Digest challenge, with credentials from environment.
  repeat the original request, but with the Digest resolution added to the header
  proxy the response back to the client. 

However, I'm uncertain on how to proceed from here.

I tried to make a generalProxy.on('proxyRes', (proxyRes, req, res) => {....} where I check for (proxyRes.statusCode === 401) which indicates that a digest challenge might be received. However, I can't find the original target URL in an obvious way, since the proxyRequest object is not provided an argument here.

Also, I'm a little in doubt here, about how I should proceed with forwarding the MJPEG response back to the client, I was thinking something like `stream.on('data', (data)=>res.write(data) but I'm not sure if this is the way to go, and how to obtain the connection to the stream on the middle of a proxy event handler.

Any help will be appreciated

@esbenvb
Copy link
Author

esbenvb commented Sep 18, 2023

I went with this solution instead:

import { request } from 'urllib'


  app.use('/proxy/:url', async (req, res) => {
    const { url } = req.params
    if (!url || typeof url !== 'string') {
      res.status(406).send('Missing URL')
      return
    }
    const { res: targetResult } = await request(url, { digestAuth: 'viewer:viewer', dataType: 'stream' })
    res.writeHead(targetResult.statusCode, targetResult.statusText, targetResult.headers)
    targetResult.pipe(res, { end: true })
    console.log('Starting proxy to', url)
    res.on('close', () => console.log('Ended proxy to', url))
  })

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant