超链接中不同端口号的相对 URL?

如果我不知道主机名,有没有一种没有 Javascript/服务器端脚本的方法来链接到同一框中的不同端口号?

例如:

<a href=":8080">Look at the other port</a>

(这个示例不起作用,因为它将8080视为我想导航到的字符串)

111886 次浏览

如果可以的话,那就太好了,我不明白为什么不可以,因为 :是 URI 组件中端口分离的保留字符,所以浏览器可以现实地将其解释为相对于这个 URL 的端口,但不幸的是它没有,也没有办法做到这一点。

因此,需要使用 Javascript 来完成这项工作;

// delegate event for performance, and save attaching a million events to each anchor
document.addEventListener('click', function(event) {
var target = event.target;
if (target.tagName.toLowerCase() == 'a')
{
var port = target.getAttribute('href').match(/^:(\d+)(.*)/);
if (port)
{
target.href = window.location.origin;
target.port = port[1];
}
}
}, false);

在 Firefox 4中测试

Http://jsfiddle.net/jtf39/79/


更新 : 修复了将端口附加到 url 末尾的 Bug,还增加了对将相对和绝对 url 附加到末尾的支持:

<a href=":8080/test/blah">Test absolute</a>
<a href=":7051./test/blah">Test relative</a>

如果没有 JavaScript,你将不得不依赖于一些服务器端脚本。

<a href="<%=Request.ServerVariables("SERVER_NAME")%>:8080">Look at the other port</a>

然而,确切的格式将取决于您所使用的技术。

这些怎么样:

在单击时修改端口号:

<a href="/other/" onclick="javascript:event.target.port=8080">Look at another port</a>

但是,如果将鼠标悬停在链接上,它就不会显示包含新端口号的链接。直到您单击它,它才会添加端口号。此外,如果用户右键单击链接并执行“复制链接位置”,他们将获得没有端口号的未修改 URL。所以这并不理想。

这里有一个方法可以在页面加载后立即更改 URL,所以将鼠标悬停在链接上或执行“复制链接位置”操作将获得带端口号的更新 URL:

<html>
<head>
<script>
function setHref() {
document.getElementById('modify-me').href = window.location.protocol + "//" + window.location.hostname + ":8080/other/";
}
</script>
</head>


<body onload="setHref()">
<a href="/other/" id="modify-me">Look at another port</a>
</body>
</html>

不需要复杂的 javascript: 只需在锚后插入一个脚本节点,然后获取 javascript 中的节点,并使用 窗户,位置,来源方法修改其 Href属性。

 <a id="trans">Look at the other port</a>
<script>
document.getElementById('trans').href='http://'+window.location.origin+':8081';
</script>

Id 属性必须是唯一的页宽,因此可能需要使用其他方法来检索节点对象。

在 Linux 上使用 apache 和 Firefox 进行测试。

您可以使用 document.write 轻松地完成这项工作,当您将鼠标悬停在 URL 上时,URL 将正确显示。你也不需要一个唯一的 ID 使用这种方法,它与 Chrome,火狐和 IE 工作。 由于我们只引用变量而不加载任何外部脚本,因此在这里使用 document.write 不会影响页面加载性能。

<script language="JavaScript">
document.write('<a href="' + window.location.protocol + '//' + window.location.hostname + ':8080' + window.location.pathname + '" >Link to same page on port 8080:</a> ' );
</script>

基于 Gary Hole 的回答,但在页面加载时更改网址,而不是单击时更改网址。

我想用 css 显示网址:

a:after {
content: attr(href);
}

所以我需要将锚的 href 转换为包含将被访问的实际 URL。

function fixPortUrls(){
var nodeArray = document.querySelectorAll('a[href]');
for (var i = 0; i < nodeArray.length; i++) {
var a = nodeArray[i];
// a -> e.g.: <a href=":8080/test">Test</a>
var port = a.getAttribute('href').match(/^:(\d+)(.*)/);
//port -> ['8080','/test/blah']
if (port) {
a.href = port[2]; //a -> <a href="/test">Test</a>
a.port = port[1]; //a -> <a href="http://localhost:8080/test">Test</a>
}
}
}

在页面加载时调用上述函数。

或者一行:

function fixPortUrls(){var na=document.querySelectorAll('a[href]');for(var i=0;i<na.length;i++){var a=na[i];var u=a.getAttribute('href').match(/^:(\d+)(.*)/);u&&a.href=u[2]&&a.port=u[1];}}

(我使用的是 for而不是 forEach,所以它可以在 IE7中工作。)

经过纠结,我发现 SERVER _ NAME 实际上是一个保留变量。因此,如果您在页面(www.example.com: 8080)上,应该能够删除8080并调用另一个端口。例如,这个修改过的代码只是为我工作,并将我从任何基本端口移动到端口8069(根据需要替换您的端口)

<div>
<a href="http://<?php print
$_SERVER{'SERVER_NAME'}; ?>:8069"><img
src="images/example.png"/>Example Base (http)</a>
</div>

最好从服务器变量中获取 URL:

// PHP:
<a href="<?=$_SERVER['SERVER_NAME']?>:8080/index.php">


// .net:
<a href='<%=Request.ServerVariables('SERVER_NAME')%>:8080/index.asp'>

修改 mouseover 上的端口号:

<a href="/other/" onmouseover="javascript:event.target.port=8080">Look at another port</a>

这是 https://stackoverflow.com/a/13522508/1497139的一个改进,它没有不能正确显示链接的缺点。

这个解决方案对我来说看起来更干净

<a href="#"
onclick="window.open(`${window.location.hostname}:8080/someMurghiPlease`)">
Link to some other port on the same host
</a>

我看过的所有答案(我会说,我没有全部读过)都没有调整 URL,以便中间的点击或“打开新标签”可以正常工作——只有一个常规的点击才能跟踪链接。我借用了 Gary Greene 的回答,我们可以在页面加载时调整 URL,而不是动态调整 URL:

...
<script>
function rewriteRelativePortUrls() {
var links = document.getElementsByTagName("a");
for (var i=0,max=links.length; i<max; i++)
{
var port = links[i].getAttribute("href").match(/^:(\d+)(.*)/);
if (port)
{
newURL = window.location.origin + port[0]
links[i].setAttribute("href",newURL)
}
}
}


</script>
<body onload="rewriteRelativePortUrls()">
...

我也需要相同的功能,但我也想做协议替换。

我的解决方案将查找 data-samehost-portdata-samehost-protocol,并在锚标记上重新生成 href 属性,以使用具有指定端口和/或协议的相同当前主机名。

以下是我正在使用的方法:

...
<script type="text/JavaScript">
/**
In http you cannot make a relative link to the same domain but different port.
This script will take urls that look like this:
[given current url: 'http://some-domain.com:3000/a/path/file.html']
1. <a data-samehost-port="8080" href="/some/path">some link</a>
2. <a data-samehost-protocol="https" href="/some/path">some link</a>
3. <a data-samehost-protocol="https" data-samehost-port="8080" href="/some/path">some link</a>
and make them look like this:
1. <a href="http://some-domain.com:8080/some/path">some link</a>
2. <a href="https://some-domain.com/some/path">some link</a>
3. <a href="https://some-domain.com:8080/some/path">some link</a>
**/
document.addEventListener('DOMContentLoaded', function() {
[... new Set([].concat(
Array.from(document.querySelectorAll('[data-samehost-port]')),
Array.from(document.querySelectorAll('[data-samehost-protocol]'))
))]


Array.from(document.querySelectorAll('[data-samehost-port]')).forEach(e=>{
let port = '80'
let path = e.getAttribute('href')
const {hostname,protocol} = document.location
if(e.hasAttribute('data-samehost-protocol')){
protocol = e.getAttribute('data-samehost-protocol')
e.removeAttribute('data-samehost-protocol')
}
if(e.hasAttribute('data-samehost-port')){
port = e.getAttribute('data-samehost-port')
e.removeAttribute('data-samehost-port')
}
if(port==='80') port=''
e.href = `${protocol}//${hostname}${port?`:${port}`:''}${path}`
})
})
</script>
...