【问题标题】:Relative URL to a different port number in a hyperlink?超链接中不同端口号的相对 URL?
【发布时间】:2022-01-25 08:40:53
【问题描述】:

如果我不知道主机名,有没有办法在没有 Javascript/服务器端脚本的情况下链接到同一个盒子上的不同端口号?

例如:

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

(此示例不起作用,因为它只会将 :8080 视为我要导航到的字符串)

【问题讨论】:

  • 因为下面的很多人都在使用服务器端解决方案,所以 NGINX $http_host var 可以工作,例如:return 200 '&lt;html&gt;&lt;body&gt;&lt;iframe id="ic" src="http://$http_host:2812/"&gt;&lt;/iframe&gt;&lt;/body&gt;&lt;/html&gt; 即在 /etc/nginx/conf.d/strange.conf 文件中。

标签: html


【解决方案1】:

这些怎么样:

点击修改端口号:

<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>

【讨论】:

  • 感谢您指出我知道的警告。在我的情况下,警告不是很重要,我更喜欢您的第一个解决方案的简单性。我几乎可以肯定我已经对您的答案投了赞成票,但是该软件似乎不这么认为,并且该软件的内存可能比我的更可靠。我已经投票了(再次??)。
  • 我已经解开了这个谜团:我不小心对其他答案之一投了赞成票。哎呀。我没有足够的声誉来扭转我意外的赞成票。
  • 根据w3 specifications&lt;a href="#" onclick="javascript:event.target.port=8888"&gt;port 8888&lt;/a&gt; 在技术上应该不起作用。 event.target 应该是 readonly。但它似乎在 Chrome 和 Firefox 中对我有用!
  • 一个班轮解决方案很棒! +1
  • 谢谢。我喜欢您的第二个解决方案,因为我可以将 HTML 中元素的 href 设置为最可能的 URI 的后备。
【解决方案2】:

您可以使用 document.write 轻松完成此操作,当您将鼠标悬停在它上面时,URL 将正确显示。您也不需要使用此方法的唯一 ID,它适用于 Chrome、FireFox 和 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>

【讨论】:

  • 简洁优雅!我不知道为什么这没有更多的赞成票——也许它只是一个后来者。
  • 另请注意,您不需要包含window.location.protocol 部分,只需以'//' 开头即可。
  • 似乎合法。优雅。
  • 真正的方便和优雅。
  • 只是说document.write 在当今几乎是普遍不推荐的。最好做类似myElement.innerHTML = '...'
【解决方案3】:

如果这可行就好了,我不明白为什么不这样做,因为: 是 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 末尾的错误,并添加了对要附加到末尾的相对和绝对 url 的支持:

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

【讨论】:

  • 所以没有javascript就没有真正的解决方案
  • 没有 Javascript 就无法做到这一点。
  • 这在 Safari 6 中不起作用。问题是您没有从相对 url 中删除端口,因此您最终会得到类似 http://myhost:8080/:8080href=":8080"。您可以在 `target.port = port[1];` 下添加此行来解决此问题。 target.href = target.href.replace("/:"+target.port, "");(这不是一个完美的解决方案,因为它是一个查找/替换,但它适用于您不担心 URL 中的端口字符串的简单情况。)
  • 在页面加载时这样做会更好,因此当您将鼠标悬停在链接上时,URL 会正确显示。
  • 不要使用此解决方案。它会在没有 Javascript 的客户端上完全中断,可能包括许多无障碍设备,如屏幕阅读器。而是在服务器端生成 URL。
【解决方案4】:

鼠标悬停时修改端口号:

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

这是对https://stackoverflow.com/a/13522508/1497139 的改进,它没有无法正确显示链接的缺点。

【讨论】:

  • 这是我的最佳答案,谢谢。
  • 至少在firefox 91中测试,这仍然显示链接不正确。但它确实将用户带到了正确的位置
【解决方案5】:

如果没有 JavaScript,您将不得不依赖一些服务器端脚本。例如,如果您使用的是 ASP,则类似于 ...

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

应该可以。但是,具体格式取决于您使用的技术。

【讨论】:

    【解决方案6】:

    在与这个搏斗之后,我发现 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>
    

    【讨论】:

    • 不错的 PHP 解决方案!您可以省略协议以便自动检测:&lt;a href="//&lt;?php print $_SERVER{'SERVER_NAME'}; ?&gt;:8069"&gt;
    【解决方案7】:

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

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

    【讨论】:

      【解决方案8】:

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

      // PHP:
      <a href="<?=$_SERVER['SERVER_NAME']?>:8080/index.php">
      
      // .net:
      <a href='<%=Request.ServerVariables('SERVER_NAME')%>:8080/index.asp'>
      

      【讨论】:

      • 这可行,但我必须在 SERVER_NAME 变量前面添加“https”。
      【解决方案9】:

      无需复杂的javascript:只需在锚点后插入一个脚本节点,然后在javascript中获取该节点,并使用window.location.origin修改其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 测试。

      【讨论】:

      • 由于某种原因,这对我来说不太奏效-它将浏览器定向到http//localhost:8081,请注意缺少的冒号。我只是完全删除了协议部分,因为 Chrome 无论如何都假定 http。
      • 你是如何测试它的?
      • 我认为这应该是window.location.hostname。见developer.mozilla.org/en-US/docs/Web/API/Location
      【解决方案10】:

      基于Gary Hole's answer,但在页面加载而不是点击时更改网址。

      我想用 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。)

      【讨论】:

        【解决方案11】:

        我查看的所有答案都没有(我会说,我没有全部阅读)调整 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()">
        ...
        

        【讨论】:

          【解决方案12】:

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

          我的解决方案将查找 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>
          ...
          
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-07-23
            • 1970-01-01
            • 2019-03-08
            • 2014-02-21
            • 1970-01-01
            • 2019-04-06
            相关资源
            最近更新 更多