158

Is there a way without Javascript / server-side scripting to link to a different port number on the same box, if I don't know the hostname?

e.g.:

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

(This example does't work as it'll just treat :8080 as a string I want to navigate to)

Ciaran McNulty
  • 18,698
  • 6
  • 32
  • 40
  • http://stackoverflow.com/questions/8317059/relative-path-but-for-port Check this out... it worked for me –  Jul 05 '16 at 03:47
  • Because a lot of people below piled on with server-side solutions, the NGINX `$http_host` var works, e.g.: `return 200 '` i.e. in a `/etc/nginx/conf.d/strange.conf` file. – MarkHu May 27 '17 at 01:18

13 Answers13

104

How about these:

Modify the port number on click:

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

However, if you hover your mouse over the link, it doesn't show the link with new port number included. It's not until you click on it that it adds the port number. Also, if the user right-clicks on the link and does "Copy Link Location", they get the unmodified URL without the port number. So this isn't ideal.

Here is a method to change the URL just after the page loads, so hovering over the link or doing "Copy Link Location" will get the updated URL with the port number:

<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>
Craig McQueen
  • 41,871
  • 30
  • 130
  • 181
  • 1
    Thanks for pointing out the caveats, which I was aware of. In my situation the caveats are not very important, and I prefer the simplicity of your first solution. I was almost certain that I had already upvoted your answer, but the software seems to think not, and probably the software's memory is more reliable than mine. I've upvoted it (again??). – Kevin Walker Nov 26 '12 at 23:24
  • I've solved the mystery: I accidentally upvoted one of the other answers instead. Oops. I don't have enough reputation to reverse my accidental upvote. – Kevin Walker Nov 26 '12 at 23:28
  • `port 8888` should technically not work, according to [w3 specifications](http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event-target). `event.target` is supposed to be `readonly`. But it seems to work for me in Chrome and Firefox! – JamesThomasMoon Jan 26 '14 at 01:52
  • 1
    One liner solution is great! +1 – Piotr Kula Apr 16 '15 at 22:16
  • Thanks. I like your second solution because I can set the href of the element in the HTML as a fallback to the most likely URI. – Dessa Simpson Mar 12 '16 at 01:39
  • I was able to use the `body onload="setHref()"` method to dynamically update a `iframe src=` on my page. Thanks! – MarkHu May 27 '17 at 01:16
64

You can do it easily using document.write and the URL will display correctly when you hover over it. You also do not need a unique ID using this method and it works with Chrome, FireFox and IE. Since we are only referencing variables and not loading any external scripts, using document.write here will not impact the page load performance.

<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>
Kurt Schultz
  • 781
  • 5
  • 7
56

It would be nice if this could work, and I don't see why not because : is a reserved character for port separation inside the URI component, so the browser could realistically interpret this as a port relative to this URL, but unfortunately it doesn't and there's no way for it to do that.

You'll therefore need Javascript to do this;

// 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);

Tested in Firefox 4

Fiddle: http://jsfiddle.net/JtF39/79/


Update: Bug fixed for appending port to end of url and also added support for relative and absolute urls to be appended to the end:

<a href=":8080/test/blah">Test absolute</a>
<a href=":7051./test/blah">Test relative</a>
Community
  • 1
  • 1
Gary Green
  • 22,045
  • 6
  • 49
  • 75
  • 1
    so without javascript there is no true solution –  May 16 '11 at 11:13
  • 2
    There is no way to do this without Javascript. – Gary Green May 16 '11 at 11:53
  • 7
    This didn't work in Safari 6. The problem is that you're not removing the port from the relative url, so you end up with something like `http://myhost:8080/:8080` for `href=":8080"`. You can add this line under ` target.port = port[1];` to fix this. `target.href = target.href.replace("/:"+target.port, "");` (It's not a perfect solution, since it's a find/replace, but it's good for simple cases where you're not worried about the port-string being in the URL.) – zekel Sep 26 '12 at 14:35
  • 1
    It would be nicer to do it at page load-time, so the URL displays properly when you hover over the link. – Craig McQueen Nov 23 '12 at 01:52
  • this doesn't appear to work with bttons. DO you know how I could make it work? I'm using – ghostbust555 Apr 29 '13 at 17:47
  • If you remove the $ from the regexp you can get to a specific page within a port. I.e: `link` – Erpheus May 05 '13 at 12:00
  • 1
    My solution was to make an ASP.NET class that generates the URL. It is essentially the same solution as above, just server-side. – rookie1024 Jun 20 '14 at 16:44
  • 7
    Please __do not use this solution__. It will completely *break* on clients without Javascript, likely including many accessibility devices like screen readers. Generate the URLs on the server side instead. – Sven Slootweg Jul 12 '15 at 17:39
  • For an SSR app, you should indeed generate it on the backend. For an SPA, if your app needs javascript to work (Angular, React, Vue...), generate it in your javascript on page load, so the url displayed in the link is correct. I personnaly used this solution for API calls, so on javascript side, and works like a charm if you take care of removing the previous port (`.replace(/:[0-9]+/,'')`). – Random May 28 '21 at 12:26
22

Modify the port number on mouseover:

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

This is an improvement of https://stackoverflow.com/a/13522508/1497139 which doesn't have the draw back of not showing the link correctly.

Community
  • 1
  • 1
Wolfgang Fahl
  • 15,016
  • 11
  • 93
  • 186
7

This solution looks cleaner to me

<a href="#"  
    onclick="window.open(`${window.location.hostname}:8080/someMurghiPlease`)">
    Link to some other port on the same host
  </a>
a_rahmanshah
  • 1,636
  • 2
  • 22
  • 35
6

After wrestling with this I found actually that SERVER_NAME is a reserved variable. So, if you are on page (www.example.com:8080) you should be able to drop the 8080 and invoke another port. For instance this modified code just worked for me and moves me from any base port to port 8069 (replace your port as required)

<div>
    <a href="http://<?php print
    $_SERVER{'SERVER_NAME'}; ?>:8069"><img
    src="images/example.png"/>Example Base (http)</a>
</div>
shruti1810
  • 3,920
  • 2
  • 16
  • 28
Landis Arnold
  • 61
  • 1
  • 3
5

Without JavaScript, you'll have to rely on some server side scripting. For example, if you're using ASP, something like ...

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

should work. However, the exact format will depend on the technology you are using.

gdt
  • 1,822
  • 17
  • 19
4

It's better to get the url from the server variables:

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

// .net:
<a href='<%=Request.ServerVariables('SERVER_NAME')%>:8080/index.asp'>
T30
  • 11,422
  • 7
  • 53
  • 57
2

No need of complicated javascript : simply insert a script node after your anchor, then get the node in javascript, and modify its href property with the window.location.origin method.

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

The id property must be unique page wide, so you may want to use other method to retrieve node objects.

Tested with apache and Firefox on Linux.

MUY Belgium
  • 2,330
  • 4
  • 30
  • 46
  • For some reason this didn't quite work for me- it directed the browser to `http//localhost:8081`, note the missing colon. I just removed the protocol part altogether since Chrome assumed http anyway. – joerick Jan 09 '14 at 17:17
  • How did you tested it? – MUY Belgium Jan 10 '14 at 11:37
  • 1
    I think this should be `window.location.hostname` instead. See https://developer.mozilla.org/en-US/docs/Web/API/Location – mwfearnley Mar 23 '20 at 11:07
1

Based on Gary Hole's answer, but changes urls on page load instead of on click.

I wanted to show the url using css:

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

So I needed the anchor's href to be converted to contain the actual url that would be visited.

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

Call the above function on page load.

or on one line:

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];}}

(I'm using for instead of forEach so it works in IE7.)

Community
  • 1
  • 1
Sam Hasler
  • 12,344
  • 10
  • 72
  • 106
1

None of the answers I looked at (and I will say, I didn't read them all) adjust the URL such that a middle click or "open in new tab" would function properly -- only a regular click to follow the link. I borrowed from Gary Greene's answer, and instead of adjusting the URL on-the-fly, we can adjust it when the page loads:

...
<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()">
...
ddiepo
  • 121
  • 1
  • 2
0

I also needed the same functionality, but I wanted to also do protocol replacement.

My solution will look for data-samehost-port or data-samehost-protocol and regenerate the href attribute on the anchor tag to use the same current hostname with the specified port and/or protocol.

Here is what I'm using:

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

Nemesarial
  • 487
  • 5
  • 12
0

You can just write http://[IP of the server]:[port of the server] instead of just the port.
In this example: <a href="http://127.0.0.1:8080">Look at the other port</a>

André
  • 1,602
  • 2
  • 12
  • 26