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

Run proxy from a subfolder #37

Closed
wimme opened this issue Nov 10, 2023 · 8 comments
Closed

Run proxy from a subfolder #37

wimme opened this issue Nov 10, 2023 · 8 comments

Comments

@wimme
Copy link

wimme commented Nov 10, 2023

I would like to use this proxy on an existing website. I'm not allowed to open additional ports. So I was thinking to proxy incoming requests via our webserver to this HLS proxy. This seems to be possible by specifying the host and port in the --host option (as said here).

As I want to offer the website and the HLS proxy on the same host:port, I would need to run this HLS proxy from a sub folder.

https://host:443/proxy/* --> webserver --> HLS proxy on port 8080
https://host:443/* --> webserver --> website

Is this possible?

@warren-bank
Copy link
Owner

warren-bank commented Nov 10, 2023

  1. if your current web server happens to use Node.js with Express.js
    • then HLS-Proxy can be used as standard middleware.. at any route you like
    • examples
  2. otherwise, what you suggest is perfectly doable
    • of course, your current web server will need the ability to intercept and conditionally reverse proxy requests
    • this functionality could either be:
      • directly supported by the web server
      • implemented by a plugin or module that the web server does support
      • implemented by a cgi-script in a language that the web server does support
        • for example: PHP, perl, ...

@wimme
Copy link
Author

wimme commented Nov 13, 2023

It's indeed possible to do conditionally reverse proxy requests on the web server (we have this already working on Windows IIS). But will HLS-Proxy be able to correctly rewrite the urls in the m3u8 file to include the sub folder? Is this configurable? Because internally it runs on port 8080 (for example) without a sub folder.
Additional question, can the web server also handle the HTTPS encryption? Will --host "mydomain.com:443" output the urls in the m3u8 as HTTPS?

@warren-bank
Copy link
Owner

warren-bank commented Nov 13, 2023

  1. start HLS Proxy behind the firewall on an unused/unprotected port (ex: 8080)
      hlsd -v 3 --host "serve.local:80" --port 8080
  2. configure the web server that hosts serve.local:80 to reverse proxy a particular custom route
      NO_UPDATE_CHECK='1'
    
      serve --config 'serve.json' --cors --listen 'tcp:0.0.0.0:80'
    • example: serve.json config file
        {
          "renderSingle":  false,
          "cleanUrls":     false,
          "trailingSlash": false,
          "etag":          false,
          "symlinks":      false,
          "logReq":        true,
          "logRes":        true,
      
          "redirects": [
            {
              "engine":        "regex",
              "source":        "^/(hls-proxy/.+)$",
              "destination":   "http://localhost:8080/$1",
              "flags":         "",
              "decode":        false,
              "terminal":      true,
              "preserveQuery": false,
              "preserveHash":  false,
              "proxy":         true
            }
          ]
        }
      
    • extra example: Apache .htaccess file
        RewriteEngine On
      
        RewriteRule "^/?(hls-proxy/.+)$" "http://localhost:8080/$1" [P,L]
      
  3. test:
      video_url='https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8'
      curl -s --insecure "$video_url"
    
      video_url=$(echo -n "$video_url" | base64 --wrap=0)'.m3u8'
      video_url="http://serve.local/hls-proxy/${video_url}"
      # http://serve.local/hls-proxy/aHR0cHM6Ly9kZW1vLnVuaWZpZWQtc3RyZWFtaW5nLmNvbS9rOHMvZmVhdHVyZXMvc3RhYmxlL3ZpZGVvL3RlYXJzLW9mLXN0ZWVsL3RlYXJzLW9mLXN0ZWVsLmlzbS8ubTN1OA==.m3u8
      curl -s "$video_url"
  4. watch video in browser

notes:

  • I just tested the above configs and it works perfectly
    • my hosts file includes the line:
      127.0.0.1 serve.local
    • the test video played in my browser
    • all requests were reverse proxied by serve and handled by HLS Proxy
  • at some point, I did major rewrites
    • presumably when I added better support for use with Express.js
    • in doing so, any leading path in the request is echoed into all proxied URLs in the modified manifest
      for example:
      • request: http://localhost:8080/hls-proxy/12345.m3u8
        • leading path = /hls-proxy/
        • base64 encoded video URL = 12345
        • file type: m3u8
    • relevant code: 1, 2, 3, 4, 5

@wimme
Copy link
Author

wimme commented Nov 13, 2023

Thanks for all the info. I created the following reverse proxy rule on the web server:

https://host/hls-proxy/(.*) --> webserver --> http://hlsproxy:8080/hls-proxy/{R:1}

What I was missing was that I had to put the subfolder in the HLS proxy URL.
I can confirm, the leading path in the request gets echoed back, so running it from a sub folder seems to work fine!

The remaining issue I have is to handle the HTTPS encryption on the front-end web server.

Requesting url: https://host/hls-proxy/aHR0cHM6Ly90ZXN0LXN0cmVhbXMubXV4LmRldi94MzZ4aHp6L3gzNnhoenoubTN1OA==.m3u8

This results in:

#EXTM3U
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2149280,CODECS="mp4a.40.2,avc1.64001f",RESOLUTION=1280x720,NAME="720"
http://host:80/hls-proxy/aHR0cHM6Ly90ZXN0LXN0cmVhbXMubXV4LmRldi94MzZ4aHp6L3VybF8wLzE5MzAzOTE5OV9tcDRfaDI2NF9hYWNfaGRfNy5tM3U4.m3u8
...

I can't auto-redirect it to HTTPS because the website uses HTTPS, so it gets blocked in the browser: "Mixed Content: The page at '<URL>' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint '<URL>'. This request has been blocked; the content must be served over HTTPS."

I can probably workaround this by configuring the certificates in the HLS proxy directly, although it's not ideal.

@warren-bank
Copy link
Owner

warren-bank commented Nov 13, 2023

hmm.. good point.

as you say, it isn't ideal.. but it would work to:

  1. run an instance of HLS Proxy to service public port 80:
      hlsd -v 3 --host "serve.local:80" --port 8080
  2. run another instance of HLS Proxy to service public port 443:
      hlsd -v 3 --tls --host "serve.local:443" --port 8081
  3. add a reverse proxy rule for each:
      http://host:80/hls-proxy/(.*)   --> webserver --> http://localhost:8080/hls-proxy/{R:1}
      https://host:443/hls-proxy/(.*) --> webserver --> https://localhost:8081/hls-proxy/{R:1}
    

alternatively, maybe I should:

  • set the public facing protocol to "https" when --host ends with ":443"
  • regardless of whether the hls-proxy is started with --tls

In which case:

  1. run an instance of HLS Proxy to service public port 443:
      hlsd -v 3 --host "serve.local:443" --port 8080
  2. add a single reverse proxy rule:
      https://host:443/hls-proxy/(.*) --> webserver --> http://localhost:8080/hls-proxy/{R:1}
    

I can't imagine this easter-egg of an exception biting anybody unexpectedly.
Thoughts?

@warren-bank
Copy link
Owner

note (to self)..

the touchpoint for making this change is here

for example:

  result.redirected_base_url = `${ (is_secure || (host && host.endsWith(':443'))) ? 'https' : 'http' }://${host || req.headers.host}${expressjs.get_base_req_url(req) || matches[1] || ''}`

@warren-bank
Copy link
Owner

v3.4.1 adds that change..
it's already available on npm

@wimme
Copy link
Author

wimme commented Nov 14, 2023

Awesome, this is great. Tested and deployed, works perfect. Thanks, very much appreciate your effort on this.

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

2 participants