Detect whether a string isn't a URL in JavaScript? - javascript

For example:
You have this string: var x = "/windows/far/away/foo.jpg"
How I now if that string is a URL or no?
What I need to do is:
if (x.charAt(0) == '/') {
x = "http://www.example.com/" + x;
}
else {
x = "http://www.example.com/one/two/three" + x;
}
The problem here is: What will happens when x will be a URL? like:
x = "http://www.externalpage.com/foo.jpg";
As you can see, x.charAt(0) is 'h' and the result will be:
http://www.example.com/one/two/threehttp://www.externalpage.com/foo.jpg
Now, the solution "maybe" like this:
if (is_valid_url( x )) {
....
}
else {
....
}
I'm using this function for this:
function is_valid_url(str) {
var pattern = new RegExp('^(https?:\/\/)?'+ // protocol
'((([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|'+ // domain name
'((\d{1,3}\.){3}\d{1,3}))'+ // OR ip (v4) address
'(\:\d+)?(\/[-a-z\d%_.~+]*)*'+ // port and path
'(\?[;&a-z\d%_.~+=-]*)?'+ // query string
'(\#[-a-z\d_]*)?$','i'); // fragment locater
if(!pattern.test(str)) {
alert("Please enter a valid URL.");
return false;
} else {
return true;
}
}
But this function only works with http and https, this will not work with other schemes like ftp or another....
I hope you understand the problem and bring me a solution. Thanks.

To make it work with other protocols, just replace https? in the pattern with an expression that matches any protocols you want, like:
var pattern = new RegExp('^((http|https|ftp|gopher|ssh|telnet):\/\/)?'+ // protocol

It looks like you actually want to normalise an image's URL, i.e. whatever string you are given, you want to convert to an absolute URL. I'd do this:
var x = /* insert arbitrary string here */;
var img = document.createElement('img');
img.src = x;
var absoluteUrl = img.src;
Let the browser do the grunt work.
If this is specific to images, you can also use the img.onload and img.onerror events to detect whether the URL references an image.

Similar to the answer of Lee Kowalkowski, I'd suggest using an <a> element to "make the browser do the work for you". This means that no GET request is fired, protecting you and your users from possible malicious entries during any verify step. It does, however, mean you don't know if the URL points to a real place.
function fixURL(str) {
var a = document.createElement('a');
a.href = str;
return a.href;
}
fixURL('foo/bar'); // "https://stackoverflow.com/questions/16295050/foo/bar"
fixURL('/foo/bar'); // "https://stackoverflow.com/foo/bar"
fixURL('ftp://foo/bar'); // "ftp://foo/bar"
After this step you might also want to check against known "bad" URLs (possibly do that server-side).

Replaced the protocol with ((news|(ht|f)tp(s?)):\/\/) that will match news://, http://, https://, ftp://
function is_valid_url(str) {
var pattern = new RegExp('^((news|(ht|f)tp(s?)):\\/\\/)'+ // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string
'(\\#[-a-z\\d_]*)?$','i'); // fragment locater
if(!pattern.test(str)) {
alert("Please enter a valid URL.");
return false;
} else {
return true;
}
}

Related

How to generate hash512 in pre-request from request that has {{variables}} in uri

So I m working on API when i need to set x-auth header for every request in PRE-REQUEST script.
I have variables in my request url i.e {{baseUrl}}{{basePath}}{{businessID}}/users?name={{userName}}......etc
I need to take whole address and add secretKey variable to the end of address, then get hash512 from it.
I was able to achieve that if i have no variables in my address i.e.: dummy.com/12321-e213-21-3e?name=John
I did this by :
var secret = "1234qwerHr2";
var url = request.url.slice(9); //sliced because I don't need to include baseUrl to hash
var hashedPayload = CryptoJS.enc.Hex.stringify(CryptoJS.SHA512(url+secret));
This will return the desired result.
Here is what I logged when trying the same code with variables
console.log(url); =>>>>>>> asePath}}{{businessID}}/users?name={{userName}}......etc
All variables defined , that`s for sure
Basically question is : how to get url with values of variables using var url = request.url; I need not {{businessID}}/users?name={{userName}} but 12321-e213-21-3e?name=John
I lost source where i found it. Somewhere on postman github issue thread
var secret = pm.globals.get("devSecretKey");
pm.myUtility = {
interpolateVariable: function (str) {
return str.replace(/\{\{([^}]+)\}\}/g, function (match, $1) {
// console.log(match)
let result = match; //default to return the exactly the same matchd variable string
if ($1) {
let realone = pm.variables.get($1);
if (realone) {
result = realone
}
}
return result;
});
},
getUrl: function () {
let url = pm.request.url.getRaw();
url = this.interpolateVariable(url)
let {
Url
} = require('postman-collection')
return new Url(url);
},
getUrlTest: function () {
let url = pm.request.url.getRaw();
url = this.interpolateVariable(url)
// let {
// Url
// } = require('postman-collection')
//return new Url(url);
return pm.request.url.parse(url);
}
}
var requestPath = pm.myUtility.getUrl().getPath();
var requestQuery =pm.myUtility.getUrl().getQueryString();
var hashedPayload = CryptoJS.enc.Hex.stringify(CryptoJS.SHA512(requestPath+"?"+requestQuery+secret)); //I added '?' because when you use getQueryString() i does not have '?' before query
pm.environment.set("tempAuthHash", hashedPayload);// use this in your header
This function he wrote is converting your {{variable}} to 'variableValue'
No need to change anything in his functions if you are not good with coding. Guy who created it has golden hands. Just place in your pre request

In vanilla JavaScript, turn relative path + base URL into absolute URL

In Ruby, it’s simple to do this, but in JavaScript, I’m not sure.
Given a starting page, such as http://example.org/foo/bar, I want to be able to take any link on the page, which can have any sort of href such as /x.php, ?p=3, y.html, etc., and turn it into a fully qualified absolute URL, such as (in the last example) http://example.org/foo/y.html.
Is there any sort of simple way to do this? If it helps, we can assume these paths do live in an actual web page as actual <a href> elements.
The URL constructor takes a second, base argument, which does exactly what you want:
const base = 'http://example.org/foo/bar';
[ '/x.php',
'?p=3',
'y.html'
].forEach(urlPart => {
const url = new URL(urlPart, base);
console.log(url.href);
});
.as-console-wrapper{min-height:100%}
<script src="//rawgit.com/github/url-polyfill/0.5.6/url.js"></script>
The URL API works in all major browsers except IE. If you need to support IE, there are polyfills available. Node.js also has it built in (const { URL } = require('url');).
If your baseURL is equal to the current page, try this:
var getAbsoluteUrl = (function() {
var a;
return function(url) {
if(!a) a = document.createElement('a');
a.href = url;
return a.href;
};
})();
Found here: https://davidwalsh.name/get-absolute-url
Tried it and it worked well for relative as well as absolute URLs (it makes them all absolute) - assuming your basePath is actually your own page.
Use this script (but test it first for the various cases, I just wrote it and wouldn't guarantee I haven't overlooked any case). Note that if the path of the URL specifies a directory and not a file, it always ends in a /, even though the browser might not show that.
var getAbsoluteURL = function (url, href) {
var path = url.split(/[#?]/)[0];
var basePath = path.slice(0, path.lastIndexOf('/'));
var domain = url.split('/').slice(0,3).join('/');
var protocol = url.split('/')[0];
switch (href.charAt(0)) {
case '/':
{
if (href.length > 1 && href.charAt(1) == '/')
return protocol + href;
else
return domain + href;
}
case '#':
case '?':
return path + href;
default:
return basePath + '/' + href;
}
}

URL draft specification validate method

I've been looking at the new URL specification which is now implemented in Chrome Canary, and it looks very useful.
Is there any way to validate a URI before it is passed into the URL object?
For example
var urlToCheck = "http//www.google.com";
if(URL.isValid(urlToCheck)) {
var u = new URL(urlToCheck, baseUrl);
console.log(u.hostname);
}
I can't see anything in the linked specification doc. I would really not like to have to process the thrown Exception just to check the URI is valid.
Actually the 2-parameter version of the URL constructor accepts anything as its first parameter:
try{
new URL(null, 'http://www.example.com');
new URL({ob:'jects',even:{nested:'ones'}}, 'http://www.example.com');
new URL(['arrays'], 'http://www.example.com');
new URL(/regexes/, 'http://www.example.com');
new URL(false, 'http://www.example.com');
new URL(undefined, 'http://www.example.com');
console.log('new URL() takes any value as its first parameter!');
}catch(e){}
This means you don't have to validate both URLs; you only have to validate the base URL. Therefore a simple solution like this should suffice:
URL.isValid = function(url) {
try{
new URL(url);
} catch(e) {
return false;
}
return true;
};
You said in your comment that you can't tell if it's the base URL or the URL that's invalid so you'd rather check them both separately. If so, why not just do that? For example, something like this:
URL.isValid = function(url, base) {
if(base !== undefined) {
try {
new URL(base);
}
catch(e) {
return false;
}
}
try {
new URL(url, base);
return true;
}
catch(e) {
return false;
}
});
Lets you check both at the same time if preferred, or as you said you wanted, separately by first checking URL.isValid(base) and then checking URL.isValid(url, base). If the first check fails you know base is invalid, if the second does, you know url is invalid. If you really wanted, you could return separate error codes from .isValid based on which url was invalid.
You can use this function to validate url:
function isValidUrl(url) {
return url.match(/^(ht|f)tps?:\/\/[a-z0-9-\.]+\.[a-z]{2,4}\/?([^\s<>\#%"\,\{\}\\|\\\^\[\]`]+)?$/);
}

Using XMLHttpRequest to get words from another website

As of current I am learning to use JavaScript to create web applications. I have just finished developing a hangman game (code will be provided later on). I have used an array of words to get a random word to play with. But as a next step I want to use an XMLHttpRequest to get a random word from a separate website, I was wondering if someone could point me towards a tutorial or give me some information on how to start!
Thanks in advance!
<script type="text/javascript">
var myWords = new Array("first", "hello", "goodbye", "random", "word", "last");
var item = myWords[Math.floor(Math.random() * myWords.length)];
var length = item.length;
var guessedLetters = "";
var error = 0;
function partialWords(item, letters) {
var returnLetter = "";
for (i = 0; i < item.length; i++) {
if (letters.indexOf(item[i]) !== -1) {
returnLetter = returnLetter + item[i];
} else {
returnLetter = returnLetter + '_';
}
}
return returnLetter;
}
function load() {
var input = document.getElementById("hangmanID").value;
var myWords2 = (item.indexOf(input) >= 0);
if (myWords2 === false) {
console.log("That letter is not in the word");
document.getElementById("hangmanID").value = "";
document.getElementById("error").innerHTML = "That letter was wrong!";
document.getElementById("success").innerHTML = "";
error++;
if (error > 0) {
document.getElementById('hangmanImg').innerHTML = "<img src='assets/" + error + ".png'>";
} else {
document.getElementById('hangmanImg').innerHTML = "No Errors yet!";
}
} else {
console.log("That letter is correct");
var string = item.indexOf(input, 0);
console.log(string);
document.getElementById("hangmanID").value = "";
document.getElementById("success").innerHTML = "That letter was right!";
document.getElementById("error").innerHTML = "";
}
guessedLetters = guessedLetters + input;
document.getElementById('hangman').innerHTML = partialWords(item, guessedLetters);
document.getElementById("lettersUsed").innerHTML = guessedLetters;
}
</script>
UPDATE:
PLEASE NOTE THAT I AM ALLOWED TO USE JSONP
Due to same-origin-policy, XMLHttpRequest is not normally allowed to fetch data from other domains. There are work-arounds such as CORS or using a proxy on your domain or using an embedded flash or java applets.
However, JSONP is a different story. That's because JSONP does not technically return data. JSONP returns a javascript file. As such, getting data using JSONP simply requires you to add a script tag to your page:
<script src="http://other.server.com/path/to/jsonp/data"></script>
To do it programmatically:
var jsonp = document.createElement('script');
jsonp.src = "http://other.server.com/path/to/jsonp/data";
document.body.appendChild(jsonp);
The problem with this is that script tags don't return anything. To solve this, the JSONP protocol passes a function name to the server so that the server will wrap that function around the JSON data.
For example, if your regular JSON data looks like this:
{"result":"something"}
The JSONP equivalent would look something like this:
callback({"result":"something"})
So, to take the original example, our new code would now be:
function processResult (obj) {
console.log(obj);
}
var jsonp = document.createElement('script');
jsonp.src = "http://other.server.com/path/to/jsonp/data?jsonp=processResult";
document.body.appendChild(jsonp);
Notice how we're passing the name of the function to handle the return value in the query param of the URL.
Note that while in this example the parameter is "jsonp" the server may implement it using some other name. Another common one is "callback", as in callback=processResult. Read the API documentation of the server you're connecting to.

Javascript regular expression to add protocol to url string

I have an application to list some website details using JavaScript. There will be a link to website which is generated using JavaScript itself. Sometimes I will get my link as,
Website
But sometimes it will be,
Website
In the second time the link is not working, there is no protocol.
So I am looking for a JavaScript regular expression function to add http:// if there in no protocol.
My code looks like,
var website_link = document.createElement("a");
website_link.innerHTML = "Website";
website_link.href = my_JSON_object.website;
website_link.target = "_blank";
profile.appendChild(website_link);
And no local links will come.
See this link.
function setHttp(link) {
if (link.search(/^http[s]?\:\/\//) == -1) {
link = 'http://' + link;
}
return link;
}
alert(setHttp("www.google.com"));
alert(setHttp("http://www.google.com/"));
In your code it will be like:
var website_link = document.createElement("a");
website_link.innerHTML = "Website";
if (my_JSON_object.website.search(/^http[s]?\:\/\//) == -1) {
my_JSON_object.website = 'http://' + my_JSON_object.website;
}
website_link.href = my_JSON_object.website;
website_link.target = "_blank";
profile.appendChild(website_link);
For example, using negative lookahead:
your_string.replace(/href="(?!http)/, 'href="http://');
Example:
> 'Website'.replace(/href="(?!http)/, 'href="http://');
"Website"
> 'Website'.replace(/href="(?!http)/, 'href="http://');
"Website"
I've wrapped this functionality into the NPM module url-schemify:
var schemify = require('url-schemify');
var assert = require('assert');
// url-schemify adds default scheme (http) to the URLs that miss it
assert.equal(schemify('google.com'), 'http://google.com');
assert.equal(schemify('www.example.com'), 'http://www.example.com');
// default scheme could be configured through the options parameter
assert.equal(schemify('google.com', { scheme: 'https' }), 'https://google.com');
// { scheme: '' } will produce protocol-related URL
assert.equal(schemify('www.example.com', { scheme: '' }), '//www.example.com');
// url-schemify doesn't modify URLs that already have scheme or protocol-related ones:
assert.equal(schemify('http://google.com'), 'http://google.com');
assert.equal(schemify('https://www.example.com'), 'https://www.example.com');
assert.equal(schemify('ftp://example.com'), 'ftp://example.com');
assert.equal(schemify('//example.com'), '//example.com');

Categories

Resources