- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我在 Kotlin 中使用 Vertx 3,有时我需要从公共(public) URL 的角度返回一个特定的 URI,这与 Vertx-web 请求认为我的 URL 不同。这可能是因为我的负载均衡器或代理接收到一个 URL,然后通过内部 URL 转发到我的应用程序。
如果我这样做:
val publicUrl = context.request().absoluteURI()
我最终得到一个类似 http://10.10.103.22:8080/some/page
的 URL,而不是 https://app.mydomain.com/some/page
。该 URL 的一切都错了!
我发现了一个 header ,据说可以告诉我更多关于原始请求的信息,例如 X-Forwarded-Host
但它只包含 app.mydomain.com
或者有时它包含端口 app.mydomain:80
但这还不足以找出 URL 的所有部分,我最终得到类似 http://app.mydomain.com:8080/some/page
仍然不是正确的公共(public) URL。
我不仅需要处理我当前的 URL,还需要处理对等 URL,例如在页面“something/page1”上转到同一服务器上的“something/page2”。当我尝试解析到另一个 URL 时提到了同样的问题,因为公共(public) URL 的重要部分无法获得。
我缺少 Vertx-web 中的方法来确定这个公共(public) URL,还是一些惯用的方法来解决这个问题?
我正在使用 Kotlin 进行编码,因此该语言的任何示例都很棒!
注意: 这个问题是作者特意写的和回答的(Self-Answered Questions),所以有趣的问题的解决方案在SO中共享。
最佳答案
这是一个比较复杂的问题,如果大多数App服务器还没有提供URL外化功能,逻辑是一样的。
要正确执行此操作,您需要处理所有这些 header :
X-Forwarded-Proto
(或 X-Forwarded-Scheme: https
,也许还有像 X-Forwarded-Ssl: on
这样的怪人, Front-End-Https: on
)X-Forwarded-Host
(如“myhost.com”或“myhost.com:port”)X-Forwarded-Port
如果你想解析并返回一个不是当前的 URL,你还需要考虑:
这是 RoutingContext
的一对扩展函数,它们将处理所有这些情况,并在负载平衡器/代理 header 不存在时回退,因此在直接连接到服务器的两种情况下都可以使用和那些通过中介的人。您传入绝对或相对 URL(到当前页面),它将返回相同的公共(public)版本。
// return current URL as public URL
fun RoutingContext.externalizeUrl(): String {
return externalizeUrl(URI(request().absoluteURI()).pathPlusParmsOfUrl())
}
// resolve a related URL as a public URL
fun RoutingContext.externalizeUrl(resolveUrl: String): String {
val cleanHeaders = request().headers().filterNot { it.value.isNullOrBlank() }
.map { it.key to it.value }.toMap()
return externalizeURI(URI(request().absoluteURI()), resolveUrl, cleanHeaders).toString()
}
调用一个内部函数来做真正的工作(并且更易于测试,因为不需要模拟 RoutingContext
):
internal fun externalizeURI(requestUri: URI, resolveUrl: String, headers: Map<String, String>): URI {
// special case of not touching fully qualified resolve URL's
if (resolveUrl.startsWith("http://") || resolveUrl.startsWith("https://")) return URI(resolveUrl)
val forwardedScheme = headers.get("X-Forwarded-Proto")
?: headers.get("X-Forwarded-Scheme")
?: requestUri.getScheme()
// special case of //host/something URL's
if (resolveUrl.startsWith("//")) return URI("$forwardedScheme:$resolveUrl")
val (forwardedHost, forwardedHostOptionalPort) =
dividePort(headers.get("X-Forwarded-Host") ?: requestUri.getHost())
val fallbackPort = requestUri.getPort().let { explicitPort ->
if (explicitPort <= 0) {
if ("https" == forwardedScheme) 443 else 80
} else {
explicitPort
}
}
val requestPort: Int = headers.get("X-Forwarded-Port")?.toInt()
?: forwardedHostOptionalPort
?: fallbackPort
val finalPort = when {
forwardedScheme == "https" && requestPort == 443 -> ""
forwardedScheme == "http" && requestPort == 80 -> ""
else -> ":$requestPort"
}
val restOfUrl = requestUri.pathPlusParmsOfUrl()
return URI("$forwardedScheme://$forwardedHost$finalPort$restOfUrl").resolve(resolveUrl)
}
以及一些相关的辅助函数:
internal fun URI.pathPlusParmsOfUrl(): String {
val path = this.getRawPath().let { if (it.isNullOrBlank()) "" else it.mustStartWith('/') }
val query = this.getRawQuery().let { if (it.isNullOrBlank()) "" else it.mustStartWith('?') }
val fragment = this.getRawFragment().let { if (it.isNullOrBlank()) "" else it.mustStartWith('#') }
return "$path$query$fragment"
}
internal fun dividePort(hostWithOptionalPort: String): Pair<String, Int?> {
val parts = if (hostWithOptionalPort.startsWith('[')) { // ipv6
Pair(hostWithOptionalPort.substringBefore(']') + ']', hostWithOptionalPort.substringAfter("]:", ""))
} else { // ipv4
Pair(hostWithOptionalPort.substringBefore(':'), hostWithOptionalPort.substringAfter(':', ""))
}
return Pair(parts.first, if (parts.second.isNullOrBlank()) null else parts.second.toInt())
}
fun String.mustStartWith(prefix: Char): String {
return if (this.startsWith(prefix)) { this } else { prefix + this }
}
关于kotlin - 我有一个 Vertx 请求,我需要计算一个外部可见(公共(public))URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39564199/
假设我拥有域 mydomain.com,并且我在服务器上有一个 Web 应用程序,网址为 http://99.99.99.99:1234/MyApplication/startpage.somethi
我正在尝试通过以下方式更新已解析的 URL: u, _ := url.Parse(s) if u.Scheme == "" { u.Scheme = "https" } if u.Path =
如何将 www.somesite.com/api(.*) 映射到 www.somesite.com/$1:9000? (我需要将/api 映射到运行 @ 端口 9000 的 Play 框架应用程序)
我有一个资源结构,如航类 > 座位 > 预订,所以预订属于某个航类的某个座位: http://example.com/jdf_3prGPS4/1/jMBDy46PbNc
我想知道以下网址是否有效。 路径中的点,在主机之后: http://www.example.com/v.b.w..com 主机中的点,作为子域的一部分: http://v.b.w..co.manufa
我有两个域 - crmpicco.co.uk 和 ayrshireminis.com - 如果我浏览到: www.crmpicco.co.uk/mini/new我希望能够重定向到 www.ayrshi
我正在尝试使用 URL 重写和应用程序请求路由来重写到外部 URL。我设置了以下规则: 在规则中,“patternToMatch”是我试
我已经安装了带有 SharePoint 和 Url Rewrite 模块的 IIS 7.0。 是以下句子还是我配置错误才能看到这个结果? Url Redirect 可以将 url 重定向到任何内部(在
我想知道,为了获得良好的 SEO,您必须在 URL 中使用自然语言。您知道字符中单词或短语的最大大小吗?例如: www.me.com/this-is-a-really-long-url.htm 我问这
有人知道在 SEO 友好 URL 中使用逗号有什么问题吗?我正在使用一些在其 SEO 友好 URL 中使用大量逗号的软件;但我 100% 肯定我见过一些程序/平台无法正确识别 URL 并在第一个逗号后
我有一个网站,我正在为所有链接使用干净的 URL。我想知道对于简短的基本 URL 与较长的描述性 URL 有何看法。 例如,如果我的网站是关于 Georgia Bulldog 足球新闻的,那么哪个网站
我正在编写一个类似于 tinyurl 的 URL 缩短器,我想知道如何跟踪已经使用我的服务缩短的 URL?例如,tinyurl 为相同的长 URL 生成相同的小 URL,而不管是谁创建的。如
我是 magento 的新手。我正在开发一个模块。为此,我有一些要显示链接的 css 和 js 文件。我目前有类似 的链接 getSkinUrl('module_tryouts/css/jquery.
我想基于 HTTP_URL 重写 URL 以重定向到不同的端口,同时保留其余的 URL 和查询字符串(如果指定)。例如, http://host/john/page.aspx 应该重定向到 http:
我遇到了以下问题: 我的 Grails (2.2.0) 应用程序具有以下 URL 映射: "/api/clientQuote/$labcode/$cliCode/$quoCode"(controlle
我有一个很长的 URL,它不适合 URL 字段。它一直在修剪。该怎么办?有没有办法增加 SharePoint 2010 中的 URL 字段字符限制? 或者解决方法来容纳长 URL。例如,以下 URL
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 9年前关闭。 Improve this que
我们从客户以前的开发人员那里继承了相当多的 Google Apps 脚本项目。 Apps 脚本通过嵌入式小部件部署在 Google 网站 (sites.google.com) 的各个页面上。每当我们需
我正在编写一些文档,但遇到了一些词汇问题: http://www.example.com/en/public/img/logo.gif 被称为“绝对”网址,对吗? ../../public/img/l
我们从客户以前的开发人员那里继承了相当多的 Google Apps 脚本项目。 Apps 脚本通过嵌入式小部件部署在 Google 网站 (sites.google.com) 的各个页面上。每当我们需
我是一名优秀的程序员,十分优秀!