Compare commits

..

7 Commits

Author SHA1 Message Date
Carson
cc13ba80cc Handle a user-supplied NULL/NA for port 2019-09-12 11:00:05 -05:00
Carson
bb3f324b56 findPort() instead of randomPort() 2019-09-12 10:47:05 -05:00
Carson
84d53e57e4 staticdocs entry 2019-09-11 16:46:05 -05:00
Carson
f8d048a742 Resolve the host before finding the port 2019-09-11 14:34:06 -05:00
Carson
0697dc2b72 more cleanup 2019-09-11 14:26:35 -05:00
Carson
55349d7770 clean-up docs 2019-09-11 14:24:16 -05:00
Carson
2c753fae8f Export randomPort(). Closes #2562 2019-09-11 14:20:21 -05:00
10 changed files with 100 additions and 68 deletions

View File

@@ -84,6 +84,7 @@ export(fileInput)
export(fillCol)
export(fillPage)
export(fillRow)
export(findPort)
export(fixedPage)
export(fixedPanel)
export(fixedRow)

View File

@@ -121,10 +121,8 @@ shinyAppDir <- function(appDir, options=list()) {
appDir <- normalizePath(appDir, mustWork = TRUE)
if (file.exists.ci(appDir, "server.R")) {
shinyOptions(appFile = "server.R")
shinyAppDir_serverR(appDir, options = options)
} else if (file.exists.ci(appDir, "app.R")) {
shinyOptions(appFile = "app.R")
shinyAppDir_appR("app.R", appDir, options = options)
} else {
stop("App dir must contain either app.R or server.R.")
@@ -138,7 +136,6 @@ shinyAppFile <- function(appFile, options=list()) {
appFile <- normalizePath(appFile, mustWork = TRUE)
appDir <- dirname(appFile)
shinyOptions(appFile = basename(appFile))
shinyAppDir_appR(basename(appFile), appDir, options = options)
}

View File

@@ -724,7 +724,7 @@ isRunning <- function() {
#' }
#' @export
runApp <- function(appDir=getwd(),
port=getOption('shiny.port'),
port=getOption('shiny.port', findPort(host = host)),
launch.browser=getOption('shiny.launch.browser',
interactive()),
host=getOption('shiny.host', '127.0.0.1'),
@@ -794,12 +794,12 @@ runApp <- function(appDir=getwd(),
if (arg %in% names(appOps)) appOps[[arg]] else default
}
if (missing(host))
host <- findVal("host", host %OR% '0.0.0.0')
if (missing(port))
port <- findVal("port", port)
port <- findVal("port", port %OR% findPort(host = host))
if (missing(launch.browser))
launch.browser <- findVal("launch.browser", launch.browser)
if (missing(host))
host <- findVal("host", host)
if (missing(quiet))
quiet <- findVal("quiet", quiet)
if (missing(display.mode))
@@ -807,8 +807,6 @@ runApp <- function(appDir=getwd(),
if (missing(test.mode))
test.mode <- findVal("test.mode", test.mode)
if (is.null(host) || is.na(host)) host <- '0.0.0.0'
workerId(workerId)
if (inShinyServer()) {
@@ -883,44 +881,6 @@ runApp <- function(appDir=getwd(),
require(shiny)
# determine port if we need to
if (is.null(port)) {
# Try up to 20 random ports. If we don't succeed just plow ahead
# with the final value we tried, and let the "real" startServer
# somewhere down the line fail and throw the error to the user.
#
# If we (think we) succeed, save the value as .globals$lastPort,
# and try that first next time the user wants a random port.
for (i in 1:20) {
if (!is.null(.globals$lastPort)) {
port <- .globals$lastPort
.globals$lastPort <- NULL
}
else {
# Try up to 20 random ports
while (TRUE) {
port <- p_randomInt(3000, 8000)
# Reject ports in this range that are considered unsafe by Chrome
# http://superuser.com/questions/188058/which-ports-are-considered-unsafe-on-chrome
# https://github.com/rstudio/shiny/issues/1784
if (!port %in% c(3659, 4045, 6000, 6665:6669, 6697)) {
break
}
}
}
# Test port to see if we can use it
tmp <- try(startServer(host, port, list()), silent=TRUE)
if (!inherits(tmp, 'try-error')) {
stopServer(tmp)
.globals$lastPort <- port
break
}
}
}
# Invoke user-defined onStop callbacks, before the application's internal
# onStop callbacks.
on.exit({
@@ -1062,7 +1022,7 @@ stopApp <- function(returnValue = invisible()) {
#' }
#' @export
runExample <- function(example=NA,
port=NULL,
port=getOption('shiny.port', findPort(host = host)),
launch.browser=getOption('shiny.launch.browser',
interactive()),
host=getOption('shiny.host', '127.0.0.1'),
@@ -1126,7 +1086,7 @@ runExample <- function(example=NA,
#' runGadget(shinyApp(ui, server))
#' }
#' @export
runGadget <- function(app, server = NULL, port = getOption("shiny.port"),
runGadget <- function(app, server = NULL, port = getOption("shiny.port", findPort()),
viewer = paneViewer(), stopOnCancel = TRUE) {
if (!is.shiny.appobj(app)) {
@@ -1221,6 +1181,41 @@ browserViewer <- function(browser = getOption("browser")) {
}
}
#' Find an open TCP port
#'
#' Finds a random available TCP port for listening on.
#'
#' @param min Minimum port number.
#' @param max Maximum port number.
#' @param host see [httpuv::randomPort()].
#' @param n Number of ports to try before giving up.
#' @param cache if `TRUE`, use the last random port if it's available.
#'
#' @details This function automatically excludes some ports
#' which are considered unsafe by web browsers.
#'
#' @seealso [httpuv::randomPort()]
#' @export
#' @examples
#'
#' findPort()
#' findPort()
#' findPort(cache = FALSE)
findPort <- function(min = 3000L, max = 8000L,
host = getOption("shiny.host", "127.0.0.1"),
n = 20, cache = TRUE) {
if (cache && !is.null(.globals$lastPort)) {
tmp <- try(startServer(host, .globals$lastPort, list()), silent = TRUE)
if (!inherits(tmp, 'try-error')) {
stopServer(tmp)
return(.globals$lastPort)
}
}
.globals$lastPort <- withPrivateSeed(httpuv::randomPort(min, max, host, n))
.globals$lastPort
}
# Returns TRUE if we're running in Shiny Server or other hosting environment,
# otherwise returns FALSE.
inShinyServer <- function() {

View File

@@ -81,8 +81,8 @@ appMetadata <- function(desc) {
navTabsHelper <- function(files, prefix = "") {
lapply(files, function(file) {
with(tags,
li(class=if (identical(file, getShinyOption("appFile"))) "active" else "",
a(href=paste0("#", gsub("\\.|\\s+", "_", file), "_code"),
li(class=if (tolower(file) %in% c("app.r", "server.r")) "active" else "",
a(href=paste("#", gsub(".", "_", file, fixed=TRUE), "_code", sep=""),
"data-toggle"="tab", paste0(prefix, file)))
)
})
@@ -105,10 +105,12 @@ navTabsDropdown <- function(files) {
tabContentHelper <- function(files, path, language) {
lapply(files, function(file) {
with(tags,
div(class=paste0("tab-pane",
if (identical(file, getShinyOption("appFile"))) " active"
else ""),
id=paste0(gsub("\\.|\\s+", "_", file), "_code"),
div(class=paste("tab-pane",
if (tolower(file) %in% c("app.r", "server.r")) " active"
else "",
sep=""),
id=paste(gsub(".", "_", file, fixed=TRUE),
"_code", sep=""),
pre(class="shiny-code",
# we need to prevent the indentation of <code> ... </code>
HTML(format(tags$code(

View File

@@ -204,7 +204,8 @@ sd_section("Utility functions",
"onStop",
"diskCache",
"memoryCache",
"reexports"
"reexports",
"findPort"
)
)
sd_section("Plot interaction",

View File

@@ -82,7 +82,7 @@
el = document.createElement("span");
el.id = "srcref_" + srcref;
var ref = srcref;
var code = document.getElementById(srcfile.replace(/\.|\s+/g, "_") + "_code");
var code = document.getElementById(srcfile.replace(/\./g, "_") + "_code");
// if there is no code file (might be a shiny file), quit early
if (!code) return;
var start = findTextPoint(code, ref[0], ref[4]);

36
man/findPort.Rd Normal file
View File

@@ -0,0 +1,36 @@
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/server.R
\name{findPort}
\alias{findPort}
\title{Find an open TCP port}
\usage{
findPort(min = 3000L, max = 8000L, host = getOption("shiny.host",
"127.0.0.1"), n = 20, cache = TRUE)
}
\arguments{
\item{min}{Minimum port number.}
\item{max}{Maximum port number.}
\item{host}{see \code{\link[httpuv:randomPort]{httpuv::randomPort()}}.}
\item{n}{Number of ports to try before giving up.}
\item{cache}{if \code{TRUE}, use the last random port if it's available.}
}
\description{
Finds a random available TCP port for listening on.
}
\details{
This function automatically excludes some ports
which are considered unsafe by web browsers.
}
\examples{
findPort()
findPort()
findPort(cache = FALSE)
}
\seealso{
\code{\link[httpuv:randomPort]{httpuv::randomPort()}}
}

View File

@@ -4,11 +4,11 @@
\alias{runApp}
\title{Run Shiny Application}
\usage{
runApp(appDir = getwd(), port = getOption("shiny.port"),
launch.browser = getOption("shiny.launch.browser", interactive()),
host = getOption("shiny.host", "127.0.0.1"), workerId = "",
quiet = FALSE, display.mode = c("auto", "normal", "showcase"),
test.mode = getOption("shiny.testmode", FALSE))
runApp(appDir = getwd(), port = getOption("shiny.port", findPort(host =
host)), launch.browser = getOption("shiny.launch.browser",
interactive()), host = getOption("shiny.host", "127.0.0.1"),
workerId = "", quiet = FALSE, display.mode = c("auto", "normal",
"showcase"), test.mode = getOption("shiny.testmode", FALSE))
}
\arguments{
\item{appDir}{The application to run. Should be one of the following:

View File

@@ -4,10 +4,10 @@
\alias{runExample}
\title{Run Shiny Example Applications}
\usage{
runExample(example = NA, port = NULL,
launch.browser = getOption("shiny.launch.browser", interactive()),
host = getOption("shiny.host", "127.0.0.1"), display.mode = c("auto",
"normal", "showcase"))
runExample(example = NA, port = getOption("shiny.port", findPort(host =
host)), launch.browser = getOption("shiny.launch.browser",
interactive()), host = getOption("shiny.host", "127.0.0.1"),
display.mode = c("auto", "normal", "showcase"))
}
\arguments{
\item{example}{The name of the example to run, or \code{NA} (the default) to

View File

@@ -4,8 +4,8 @@
\alias{runGadget}
\title{Run a gadget}
\usage{
runGadget(app, server = NULL, port = getOption("shiny.port"),
viewer = paneViewer(), stopOnCancel = TRUE)
runGadget(app, server = NULL, port = getOption("shiny.port",
findPort()), viewer = paneViewer(), stopOnCancel = TRUE)
}
\arguments{
\item{app}{Either a Shiny app object as created by