JS - baseURLString when sending pathnames only - javascript

I am trying to create a new URL in JS so it can be manipulated for an async request. As nothing is cross-origin (I think this is the correct usage of that term), the URLs I send for async request look like /MyLoginUrl or /MyUpdateDataUrl, etc. (i.e. I am only sending the pathname).
My attempt to create a new URL from an existing url looked basically like this:
// Actually I set the url as an arguement in a function,
// but for demonstration it will be a variable
var url = '/myPathname';
// Much later...
url = new URL (url);
However, this was returning a syntax error. Once I looked a docs, I found out why.
Per the docs, the syntax for a new URL looks like this:
url = new URL(urlString, [baseURLstring])
url = new URL(urlString, baseURLobject)
The docs also say:
baseURLstring: is a DOMString representing the base URL to use in case urlString is a relative URL. If not specified, and no baseURLobject is passed in parameters, it default to 'about:blank'. If it is an invalid absolute URL, the constructor will raise a DOMException of type SYNTAX_ERROR
A couple of examples in the docs for a baseURLstring is:
var a = new URL("/", "https://developer.mozilla.org"); // Creates a URL pointing to 'https://developer.mozilla.org/'
var b = new URL("https://developer.mozilla.org"); // Creates a URL pointing to 'https://developer.mozilla.org/'
var c = new URL('en-US/docs', b); // Creates a URL pointing to 'https://developer.mozilla.org/en-US/docs'
Thus, I am trying to figure out how to emulate a baseURLstring for, currently, localhost and eventually when this gets hosted by the main server I will use for my network, the baseURLstring for that. I'm guessing it would involve in some way getting the IP address of the computer I have/of the server on the network, or maybe not...

you can test this
var base_url = location.protocol + '//' + location.host + '/';

baseURLstring will the url of your website, lets take the example of Google:
base url of google is https://www.google.com similarly your baseurlstring will be something like this https://www.yourwebsiteaddress.com and the first parameter in url = new URL(urlString, [baseURLstring]) is the path of the files placed on your server (root folder, where your default index file is placed)

Related

Getting the proper URL in an angular project

I have a working Js plugin thats written in jQuery. For my plugin to work, I need to get the URL, but without the anchor tag that references an element by id. That is, only getting http://example.com/content/1/ instead of say http://example.com/content/1/#comments.
I am doing this with the following function :
var getProperURL = function() {
return window.location.protocol + '//' + window.location.hostname + window.location.pathname;
}
This works most of the time. However, I ran this on an angular project, and I only get the protocol and the hostname. How do I do this for AngularJs?
To retrieve only the path without the hash, you can use $location.path().
See the official documentation: location.path()
This method is getter / setter.
Return path of current url when called without any parameter.
Change path when called with parameter and return $location.
Note: Path should always begin with forward slash (/), this method will add the forward slash if it is missing.
Return full url representation with all segments encoded according to rules specified in RFC 3986.
Inject location and retrieve all datas you need. In the guide is plenty of examples:
// given url http://example.com/#/some/path?foo=bar&baz=xoxo
var path = $location.path();
// => "/some/path"
and in your website:
// given url http://example.com/content/1/#comments
var path = $location.path();
// => "/content/1"

How to deal with a friendly url with parameters in a static webpage?

I have the following URL https://mywebsite/somepage/1234/5678 where somepage is a route to a page and the numbers are are parameters.
My page is a static page, just html and javascript. Ex.: https://mywebsite/somepage.html.
How could I open this page given the above url get the parameters inside the page?
The reason for this is that I have a mobile deeplink direct the user to a website so that it can download the app in case it isn't installed or to the app itself. I don't have the choice to use a dinamic page with a routing system like in Cake PHP or in Spring Framework.
If you want to load the normal page (https://mywebsite/somepage.html) then you could use hashes instead. They don't get seen by the server, so it would serve the regular html file.
// get the url
var url = window.location.href; // = "https://mywebsite/somepage.html#1234/5678"
// get the bit you want
var params = url.substring(32); // = "1234/5678"
// ^ the length of "https://mywebsite/somepage.html#"
// split it apart into individual parts
params = params.split("/"); // = ["1234", "5678"]
// then do whatever you like with the params
Create array from current pathname split on /
var urlPath = window.location.pathname.split('/');
Do something with the array...
urlPath.forEach(function(item) {
console.log(item);
});

Ensure URL is relative before navigating via JavaScript's location.replace()

I have a login page https://example.com/login#destination where destination is the target URL the user was trying to navigate to when they were required to log in.
(i.e. https://example.com/destination)
The JavaScript I was thinking about using was
function onSuccessfulLogin() {
location.replace(location.hash.substring(1) || 'default')
}
This would result in an XSS vulnerability, by an attacker providing the link
https://example.com/login#javascript:..
Also I need to prevent navigation to a lookalike site after login.
https://example.com/login#https://looks-like-example.com
or https://example.com/login#//looks-like-example.com
How can I adjust onSuccessfulLogin to ensure the URL provided in the hash # portion is a relative URL, and not starting with javascript:, https:, // or any other absolute navigation scheme?
One thought is to evaluate the URL, and see if location.origin remains unchanged before navigating. Can you suggest how to do this, or a better approach?
From OWASP recommendations on Preventing Unvalidated Redirects and Forwards:
It is recommended that any such destination input be mapped to a value, rather than the actual URL or portion of the URL, and that server side code translate this value to the target URL.
So a safe approach would be mapping some keys to actual URLs:
// https://example.com/login#destination
var keyToUrl = {
destination: 'https://example.com/destination',
defaults: 'https://example.com/default'
};
function onSuccessfulLogin() {
var hash = location.hash.substring(1);
var url = keyToUrl[hash] || keyToUrl.defaults;
location.replace(url);
}
You could also consider providing only path part of the URL and appending it with a hostname in the code:
// https://example.com/login#destination
function onSuccessfulLogin() {
var path = location.hash.substring(1);
var url = 'https://example.com/' + path;
location.replace(url);
}
I would stick to the mapping though.
That is a very good point about the XSS vulnerability.
I believe all protocols only use English alphabetic characters, so a regex like /^[a-z]+:/i would check for those. Alternately if we're feeling more inclusive, /^[^:\/?]+:/ allows anything but a / or ? followed by a :. Then we can combine that with /^\/\/ to test for a protocol-free URL, which gives us:
// Either
var rexIsProtocol = /(?:^[a-z]+:)|(?:^\/\/)/i;
// Or
var rexIsProtocol = /(?:^[^:\/?]+:)|(?:^\/\/)/i;
Then the test is like this:
var url = location.hash.substring(1).trim(); // trim to deal with whitespace
if (rexIsProtocol.test(url)) {
// It starts with a protocol
} else {
// It doesn't
}
That said, the only one I think you need to be particularly bothered by is the javascript: pseudo-protcol, so you might just test for that.

How to use location object to parse URL without redirecting the page in javascript?

The browser has a very efficient URL parser that let you get location.href, hash, query, etc from the current URL. I'd like to use it instead of coding something using regexes.
If you set location.href or do location.replace(url), the page gets redirected in Chrome. I tried to get the prototype of location in this browser, but I can't find location.prototype. There is a location.__proto__ which is described as the Location class in the js console, but I can't find a way to instantiate it. Plus, I need a cross browser solution and __proto__ is not available in IE.
If it's not possible, don't give me a regex alternative, just tell me the hard truth, provided you can back it up with evidences.
Yes, it's very much possible! If you create a new a object, you can use the location fields without redirecting the browser.
For instance:
var a = document.createElement('a');
a.href = "http://openid.neosmart.net/mqudsi#fake"
You can now access .hash, .pathname, .host, and all the other location goodies!
> console.log(a.host);
openid.neosmart.net
I wrote a generalized version of the wonderful Mahmoud solution:
var parseUrl = (function(){
var div = document.createElement('div');
div.innerHTML = "<a></a>";
return function(url){
div.firstChild.href = url;
div.innerHTML = div.innerHTML;
return div.firstChild;
};
})();
It works that way:
var url = parseUrl('http://google.com');
var url = zerobin.parseUrl('http://google.com');
console.log(url.protocol);
"http:"
console.log(url.host);
"google.com"
The parseUrl code is a bit complicated because IE requires the link HTML code to be processed by its HTML parser if you want it to parse the URL. So we create a closure in which we store a <div> with a <a> as child (avoid recreating it a each call), and when we need URL parsing, we just take the HTML of div, and inject it back to itself, forcing IE to parse it.

How should I create relative paths in javascript using MVC3?

I am having some difficulty aligning my paths without a hardcode in javascript. I am running an asp.net MVC3 web application.
If my path is of the form
var url = 'http://serverNameHardcode/websiteNameHardcode/service/service?param1=' + param;
Then things work fine when I do
$.get(url,
{},
function (data) {alert('callback success');},'json');
I would like to create a relative path. I tried
var url = 'service/service?param1=' + param;
And this works when I run locally and also in Firefox, but not in IE7. When I publish to the server without the hardcode the callback never fires. I know MVC-3 adds some complexity to routing, but I do not know if it applies to this situation; so, I marked this question as such.
How should I setup my path so I don't need hardcodes?
Just write out the app path as a global js variable from your master view, then compose links as
APPPATH + "path/whatever"
Just had to solve this for one of my jQuery plugins, where it is preferable not to modify anything global (i.e. outside the scope of the plugin use) so I had to disregard the marked answer.
I also found that because I host DEV locally in IIS I could not use a root-relative path (as localhost is not the root).
The solution I came up with extended what I had already started with: a data-controller attribute specifying which controller to use in the element I am applying my plugin to. I find it preferable to data-drive the controller names so the components can be more easily reused.
Previous:
<div data-controller="Section">
Solution:
<div data-controller="#Url.Content("~/Section")">
This injects the server root (e.g. /Test.WindowsAzure.Apr2014/ before the controller name so I wind up with /Test.WindowsAzure.Apr2014/Section which is perfect for then appending actions and other parameters as you have. It also avoids having an absolute path in the output (which takes up extra bytes for no good reason).
In your case use something like:
// Assuming $element points to the element your plugin/code is attached to...
var baseUrl = $element.data('controller');
var url = baseUrl + '/service?param1=' + param;
Update:
Another approach we now use, when we do not mind injecting a global value, is Razor-inject a single global JavaScript variable onto window in the layout file with:
<script>
window.SiteRoot = "#Url.Content("~/")";
</script>
and use it with
var url = window.SiteRoot + '/service?param1=' + param;
One option:
var editLink = '#Url.Action("_EditActivity", "Home")';
$('#activities').load(editLink + "?activityID=" + id);
another example:
var actionURL = '#Url.Action("_DeleteActivity", "Home")';
$('#activities').load(actionURL + "?goalID=" + gID + "&activityID=" + aID);
If you don't need to add to the string:
$('#activities').load('#Url.Action("_Activities", "Home", new { goalID = Model.goalID},null)');
I really need the path to get this to work, maybe its IE7. Who knows. But this worked for me.
Grab the URL and store it somewhere. I chose to implement the data attribute from HTML5.
<div id="websitePath" data-websitePath='#Request.Url.GetLeftPart(System.UriPartial.Authority)#Request.ApplicationPath'></div>
Then when you need to perform some AJAX or otherwise use a URL in javascript you simply refer to the stored value. Also, there are differences in the versions of IIS (not cool if your devbox is IIS5 and your server is IIS7). #Request.ApplicationPath may or may not come back with a '/' appended to the end. So, as a workaround I also trim the last character if it is /. Then include / as part of the url.
var urlprefix = $('#websitePath').data('websitepath');
urlprefix = urlprefix.replace(/\/$/, "");
var url = urlprefix + '/service/service?param1=' + param;
While the accepted answer is correct I would like to add a suggestion (i.e. how I do it).
I am using MVC, and any ajax request goes to a controller. My controllers have services so if a service call is required the controller will take of that.
So what's my point? So if ajax always communicates with a controller, then i would like to let the MVC routing resolve the path for me. So what I write in Javascript for url is something like this:
url: 'controller/action'
This way there is no need for the root path etc...
Also, you can put this in a separate Javascript file and it will also work whereas #Url.Content will need to be called on the view.

Categories

Resources