gladkia / igvR

An R Bioconductor package providing interactive connections to igv.js (the Integrative Genomics Viewer) in a web browser
MIT License
42 stars 4 forks source link

Support HTTPS #9

Closed nathanweeks closed 1 year ago

nathanweeks commented 5 years ago

I'm unable access an igvR instance that is running from RStudio Server behind a reverse proxy that uses HTTPS. The new (Chrome) browser window that opens has the following error in the JavaScript console

Uncaught DOMException: Failed to construct 'WebSocket': The URL's scheme must be either 'ws' or 'wss'. 'https' is not allowed.

while the R console hangs with this output, apparently indicating that a connection is not established:

> igv <- igvR(portRange=7000:11000)
attempting to open websocket connection on port 7000

It seems that igvR (and BrowserViz) only considers http:

https://github.com/paul-shannon/igvR/blob/d3f36a063a59c7ef124c9e7c2bf7f42391570de1/inst/browserCode/lib/browserviz.js#L311

https://github.com/PriceLab/igvR/blob/43f18b826959b2d0df21ae6568118ad62d8d8430/inst/browserCode/testImmediate/browserviz.js#L311

Would something like this handle https as well (I'm not having luck building a fork of igvR with this change, and haven't been able to test)

   this.socketURI = (window.location.protocol == "https:"
                     ? window.location.href.replace("https://", "wss://")
                     : window.location.href.replace("http://", "ws://"));
paul-shannon commented 5 years ago

@nathanweeks Sorry I did not reply sooner - and thanks for the suggestion. I will pursue this by the end of the day tomorrow.

paul-shannon commented 5 years ago

@nathanweeks

I just pushed BrowserViz 2.17.10. It includes your code verbatim. Are you able to pull and build from the paul-shannon repo?

You mentioned encountering difficulty building igvR. Could you provide details? Perhaps I could help with that, learn from your difficulties, maybe for BrowserViz too if it is not a straightforward pull and

make -f build.makefile all
nathanweeks commented 5 years ago

Hi @paul-shannon , I did a devtools::install_github("paul-shannon/BrowserViz") and verified that the following code snippet resulted in a successful websocket connection when run from an RStudio Server instance that is behind a TLS terminating reverse proxy for Open OnDemand

B <- BrowserViz(portRange=7005:7007, browserFile="R/rocker/3.6/BrowserViz/browserCode/dist/bvDemoApp.html")

(it seems that dist/bvDemoApp.html was not updated with the new browserviz.js code---is that file still used?)

I was able to get igvR to build/install using make -f build.makefile all (from within a well-equipped docker image, bioconductor/bioconductor_full). However, the installed igvR/browserCode/dist/igvApp.html does not have the new BrowserViz code (I assume this needs to be committed to igvR repo at inst/browserCode/lib/browserviz.js as well?)

paul-shannon commented 5 years ago

Hi @nathanweeks, You got it right, and thank you. I had forgotten to copy the browserviz.js into the igvR package and update the repo.

I think everything required is now there:

Let me know how it goes.

nathanweeks commented 5 years ago

Yes, those updates did the trick! At least, following the igvR vignette, this code chunk opens a browser tab that renders MEF2C:

igv <- igvR(portRange=7000:8000)
setBrowserWindowTitle(igv, "MEF2C")
setGenome(igv, "hg19")
Sys.sleep(5) 
showGenomicRegion(igv, "MEF2C")

However, when I attempted to run the subsequent code chunk that called displayTrack(), the following error displayed in the igv.js window:

Error accessing resource: http://localhost:7002?/tmp/RtmpTSF5s5/file1d01f17aa7975.bed Status: 0

I've tried setting the igvR(host="...") parameter to match that of the reverse proxy, but no effect.

After looking at the igvR.R code:https://github.com/paul-shannon/igvR/blob/eeed7687ed59114e71e964e2a9b982d427943d77/R/igvR.R#L20 I tried setting the igv@uri attribute manually to match the URL of the RStudio Server session as seen in my browser window; e.g.:

igv <- igvR(portRange=7000:8000)
igv@uri <- "https://proxy.example.edu/rnode/compute-node-1/8668/"

This allowed a subsequent displayTrack(...) to display an empty track. The browser javascript console contains a message of the form:

{"format":"bedGraph","name":"IGAP.gwas.scored","url":"https://proxy.example.edu/rnode/compute-node-1/8668/?/tmp/RtmpTSF5s5/file1d01fa1eeec9.bedGraph","indexed":false,"sourceType":"file","color":"blue","order":1.7976931348623157e+308,"height":50,"autoscale":true,"min":"NA","max":"NA","type":"wig"}

If I plug https://proxy.example.edu/rnode/compute-node-1/8668/?/tmp/RtmpTSF5s5/file1d01fa1eeec9.bedGraph into a browser window, I simply get the RStudio Server session.

Any ideas?

paul-shannon commented 5 years ago

If I plug https://proxy.example.edu/rnode/compute-node-1/8668/?/tmp/RtmpTSF5s5/file1d01fa1eeec9.bedGraph into a browser window, I simply get the RStudio Server session.

This rings a bell - I encountered something like this in igvShiny https://github.com/paul-shannon/igvShiny. I can refresh my memory later today, but in case you want to forge ahead, I think the trick is (something like) this: tell the RStudio web server to treat a specific directory as a legitimate place to use in http GET requests. Then write your temporary track files there.

Let me know if this, meager as it is, is any help.

nathanweeks commented 5 years ago

Thanks; I attempted to implement this suggestion by bind mounting the /tmp directory (which is writable in the Singularity container) to a tmp/ subdirectory the rserver www files path (--www-local-path option, which in the Rocker container image defaults to /usr/lib/rstudio-server/www).

Now I can point my browser to, e.g., https://proxy.example.edu/rnode/compute-node-1/8668/tmp/RtmpTSF5s5/file1d01fa1eeec9.bedGraph and download the bed file. However, the url generated by displayTrack() (e.g., https://proxy.example.edu/rnode/compute-node-1/8668/?/tmp/RtmpTSF5s5/file1d01fa1eeec9.bedGraph) attempts to pass the path to the bed file as a query string, which for some reason still causes redirection to the RStudio Sever session itself.

I might be going down the wrong path with this, but for this approach to work, it seems that it might be necessary to override where the track URLs are being generated (e.g., https://github.com/paul-shannon/igvR/blob/eeed7687ed59114e71e964e2a9b982d427943d77/R/igvR.R#L411 ) to use a "/" instead of a "?" (?) But I admittedly may be going about this the wrong way.

paul-shannon commented 5 years ago

@nathanweeks
Thanks for the sleuthing around. That embedded question mark in the url is the clue I use to parse out the path to the object of the http GET. You may have already figure that out.

I'd be glad to take a closer look at this after the bioc release, in a couple of weeks. At that time (or sooner) could you provide me with a reproducible example, distilled (where possible) to a minimum form?

Thanks for all the work you have done. Sorry it has not yet paid off.

nathanweeks commented 5 years ago

@paul-shannon : FWIW, if I bind mount /tmp to /usr/lib/rstudio-server/www/tmp, slightly modify igvR.R by changing all instances of

sprintf("%s?%s", igv@uri, temp.filename)

to

sprintf("%s%s", igv@uri, temp.filename)

and in the R script set, e.g.

igv@uri <- "https://proxy.example.edu/rnode/compute-node-1/8668"

(no trailing slash) Then I am able to load tracks (a definite payoff!). But it would be great if such workarounds weren't necessary. A small step might be auto-populating igv@uri , which I had set by copying & pasting the URL from the RStudio Server browser window (window.location.href in JavaScript). Is there a way to populate that via some library function?

paul-shannon commented 5 years ago

@nathanweeks

Good work, Nathan. Excellent sleuthing.

It would be easy for me to slip in an experimental method on the igvR class, something like:

setHostedFileUrlProtocol(igv, “%s%s”)

while the existing practice (“%s?%s”) stays on as the default. That could give you an immediate workaround, you could test on your end, my tests would all work as before.

Then, with the urgency passed, and after a few deadlines here are met, I could re-examine my practice and see if that “?” is really needed.

How’s that?

On Oct 18, 2019, at 9:32 AM, Nathan Weeks notifications@github.com wrote:

@paul-shannon : FWIW, if I bind mount /tmp to /usr/lib/rstudio-server/www/tmp, slightly modify igvR.R by changing all instances of

sprintf("%s?%s", igv@uri, temp.filename)

to

sprintf("%s%s", igv@uri, temp.filename)

and in the R script set, e.g.

igv@uri <- "https://proxy.example.edu/rnode/compute-node-1/8668"

(no trailing slash) Then I am able to load tracks (a definite payoff!). But it would be great if such workarounds weren't necessary. A small step might be auto-populating igv@uri , which I had set by copying & pasting the URL from the RStudio Server browser window (window.location.href in JavaScript). Is there a way to populate that via some library function?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

nathanweeks commented 5 years ago

Hi @paul-shannon , yes, that seems like it would for testing purposes. Thanks!

paul-shannon commented 2 years ago

@nathanweeks After an inexcusably long delay, 2 1/2 years! I just noticed this issue never closed. I am resolved to now provide better support. Please let me know if there is anything you need in igvR, on this issue or another. With apologies, Paul.

scheidp commented 9 months ago

@paul-shannon I'm trying to run igvR in RStudio Server running in docker container on an AWS ec2 instance, and like the issue above, I get a displayTrack() error:

Screenshot 2024-01-22 at 2 14 42 AM

FWIW, I do not get any such errors when running this in RStudio locally.

Here's the code I ran from RStudio Server:

options(width=120)
knitr::opts_chunk$set(
   collapse = TRUE,
   eval=interactive(),
   echo=TRUE,
   comment = "#>"
)
 library(igvR)
igv <- igvR()
setBrowserWindowTitle(igv, "simple igvR demo")
setGenome(igv, "hg38")
print(getSupportedGenomes(igv))
showGenomicRegion(igv, "MYC")
loc <- getGenomicRegion(igv)

tbl.bed <- data.frame(chrom=loc$chrom, start=loc$start + 2000, end=loc$end-2000,
                        name="simple.example", stringsAsFactors=FALSE)

track <- DataFrameAnnotationTrack("simple bed", tbl.bed, color="random")

displayTrack(igv, track)

I've tried these workarounds from the post above:

I'd appreciate any troubleshooting advice. :)