URL transformation in Chrome javascript bookmarklet showing "undefined" - javascript

I'm trying to create a Chrome bookmarklet that will take a part of the pathname from one URL and navigate to a new URL using that variable as a parameter (the variable is 1234567 in the example below).
From: 'https://example.com/reporting-dashboard/#/dashboard/1234567?pageId=Page_3a7c73c6-34c9-4ab3-8d1f-5bd437c07115'
To: 'https://example.com/tool/permissions/resources?namespace=1234567'
The hostname differs depending on the environment I'm working in but will always stay the same when I transform it with the bookmarklet so I'm trying to pull that info when I compose the new URL. This is what I've got so far, but I keep getting "undefined" in the transformed URL (below) when I run the code. Any ideas on what I've got wrong here?
'https://example.com/tool/permissions/resources?namespace=undefined'
My code:
//Sample URL: https://example.com/reporting-dashboard/#/dashboard/1234567?pageId=Page_3a7c73c6-34c9-4ab3-8d1f-5bd437c07115
var pathArray = location.pathname.split('/');
let secondLevelLocation = pathArray[3];
var newUrl = location.protocol + '//' + location.hostname + '/tool/permissions/resources?namespace=' + secondLevelLocation;
var w=window.open();w.location=newUrl;w.document.close();

In the code you've shown, there is an assumption that the URL hash (fragment identifier) will be included when accessing the pathname:
//Sample URL: https://example.com/reporting-dashboard/#/dashboard/1234567?pageId=Page_3a7c73c6-34c9-4ab3-8d1f-5bd437c07115
var pathArray = location.pathname.split('/');
let secondLevelLocation = pathArray[3];
This is where the problem occurs. In a URL, the pathname ends when one of the following characters are first encountered:
? (which begins the query string), or
# (which begins the fragment identifier)
The format of the hash / fragment identifier portion of the URL in your example is that of a fully-resolved URL without the origin (starting at the pathname).
Using this knowledge, you can use the native URL class to help you select the desired part of the input URL, then use it again to construct the target URL, as shown in the code below. Once you have the target URL, you can use it to navigate, etc.
function parseNamespace (url) {
const fragment = url.hash.slice(1);
if (!fragment.startsWith('/')) throw new Error('Path fragment not found');
url = new URL(fragment, url);
const namespace = url.pathname.split('/').at(-1);
return namespace;
}
function createUrl (address = window.location.href) {
let url = new URL(address);
const namespace = parseNamespace(url);
const pathname = '/tool/permissions/resources';
url = new URL(pathname, url.origin);
url.searchParams.set('namespace', namespace);
return url;
}
const url = createUrl('https://example.com/reporting-dashboard/#/dashboard/1234567?pageId=Page_3a7c73c6-34c9-4ab3-8d1f-5bd437c07115');
// You can omit the argument when you want to get the address from the current document:
// const url = createUrl();
console.log(url.href); // "https://example.com/tool/permissions/resources?namespace=1234567"

Related

Best way to add query param to all navigations

I am looking for a solution to add query param on each URL after navigation using WebDriverIO.
For example:
Base URL: https://www.google.com/?block=true
When I click a button on the page loaded from the above URL, new URL that loads is https://www.google.com/search-page.
I would like to append ?block=true to all the navigations.
For the base URL, I can use the method browser.url("https://www.google.com/?block=true"). Not sure how I can add to other pages that are navigated using click actions.
You can use URLSearchParams to generate complex search params. Check out the below example.
const baseUrl = "https://www.google.com/?block=true"; // window.location.href
const searchUrl = "https://www.google.com/search?test=testparam";
function getRedirectUrl(baseUrl, newUrl) {
let oldParms = new URL(baseUrl).searchParams;
const newUrlParams = new URL(newUrl).searchParams;
for(let [value, key] of oldParms.entries()){
newUrlParams.append(key, value);
}
const newSearch = new URL(newUrl).search;
return `${newUrl.slice(0, -1 * newSearch.length)}?${newUrlParams.toString()}`;
}
console.log(getRedirectUrl(baseUrl, searchUrl));

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

javascript: MIME type ('text/html') is not executable, and strict MIME type checking is enabled

I am trying to make a simple get authorization request to the Spotify Api. If i make a GET HTTPRequest then i get a cross-domain error. Hence I making a JSONP request using a callback, but this leads to a MIME type error as shown above, whose workaround i have found is to again make an HTTPRequest JSON request to match the MIME type. Quite a deadlock I am in here ! Please help! Thanks
This is my js code block:
(function(){
var script = document.createElement('script');
script.src = 'https://accounts.spotify.com/authorize?client_id=CLIENT_ID&response_type=code&redirect_uri=https://samcasm.github.io/moodsetNow/moodset.html&scope=user-read-private%20user-read-email&state=34fFs29kd09?callback=mySpotify';
document.getElementsByTagName('body')[0].appendChild(script);
})();
function mySpotify(){
console.log(response);
}
Your problem seems to be that you’re using a <script> tag to load something that’s an HTML page. This is my suggested solution:
When the user needs to authenticate, redirect them:
location.href = "https://accounts.spotify.com/authorize" +
"?client_id=" + CLIENT_ID +
"&response_type=token" +
"&redirect_uri=" + encodeURIComponent(THE_URI_TO_REDIRECT_TO) +
"&state=" + STATE + // optional
"&scope=" + SCOPES.join(" ") + // optional
"";
Note that if you’re going to redirect on page load, use location.replace(...) instead of location.href = .... This way, the user will not have the immediately-redirecting page in their back button history.
Then, at the URL in THE_URI_TO_REDIRECT_TO, parse the hash:
Spotify makes a hash like this: #access_token=...&expiry=.... location.hash returns that hash, including the leading #. First, we set up our object that will hold the options:
var hash = {};
then, we remove the #:
var h = location.hash.slice(1)
… and split on the &s.
h = h.split('&')
Next, we iterate over all of the pairs (forEach) and put the two pieces in the hash object (i. e. hash['access_token'] = '...';
h.forEach(function(pair) {
pair = pair.split('=');
hash[pair.shift()] = pair.join('=');
});
After that, you can read the data.
if (hash.error) {
console.log(hash.error);
} else {
var token = hash.access_token;
hash.token_type === "Bearer";
var expiry = new Date();
expiry.setSeconds(expiry.getSeconds() + (+hash.expires_in));
}
var state = hash.state; // optional

Relative uri for node.js request library

I have the following code, and node.js can't resolve the url:
const request = require('request')
const teamURL = `/users/${user._id}/teams`;
const req = request({
url: teamURL,
json: true
},
function(error, response, body) {
if (!error && response.statusCode == '200') {
res.render('userHome.html', {
user: user,
teams: body
});
}
else {
console.error(error);
next(error);
}
});
is there a good way to use relative paths/urls with the request library on a server-side node.js Express app?
Giving just a relative url only works if it is clear from context what the root part of the url should be. For instance, if you are on stackoverflow.com and find a link /questions, it's clear from context the full url should be stackoverflow.com/questions.
The request library doesn't have this kind of context information available, so it needs the full url from you to do be able to make the request. You can build the full url yourself of course, for instance by using url.resolve():
var url = require('url');
var fullUrl = url.resolve('http://somesite.com', '/users/15/teams');
console.log(fullUrl); //=> 'http://somesite.com/users/15/teams');
But of course this will still require you to know the root part of the url.
Jasper 's answer is correct -- the request module needs full URL. if you are in a situation where you have a single page application, with lots of requests to an API with the same base URL, you can save a lot of typing by creating a module like this:
var url = require('url');
var requestParser = (function() {
var href = document.location.href;
var urlObj = url.parse(href, true);
return {
href,
urlObj,
getQueryStringValue: (key) => {
let value = ((urlObj && urlObj.query) && urlObj.query[key]) || null;
return value;
},
uriMinusPath: urlObj.protocol + '//' + urlObj.hostname
};
})();
then, to grab the base URL anytime you need it: requestParser.uriMinusPath
and grab the value of an arbitrary query parameter: RequestParser.getQueryStringValue('partner_key');

Pass parameter to BLOB object URL

Say I've got a reference to a html file as a Blob b and I create a URL for it, url = URL.createObjectURL(b);.
This gives me something that looks like blob:http%3A//example.com/a0440b61-4850-4568-b6d1-329bae4a3276
I then tried opening this in an <iframe> with a GET parameter ?foo=bar, but it didn't work. How can I pass the parameter?
var html ='<html><head><title>Foo</title></head><body><script>document.body.textContent = window.location.search<\/script></body></html>',
b = new Blob([html], {type: 'text/html'}),
url = URL.createObjectURL(b),
ifrm = document.createElement('iframe');
ifrm.src = url + '?foo=bar';
document.body.appendChild(ifrm);
// expect to see ?foo=bar in <iframe>
DEMO
I don't think adding a query string to the url will work as it essentially changes it to a different url.
However if you simply want to pass parameters you can use the hash to add a fragment to the url
ifrm.src = url + '#foo=bar';
http://jsfiddle.net/thpf584n/1/
For completeness sake, if you want to be able to reference a blob that has as question mark "query string" indicator in it, you can do so in Firefox any way you choose, such as: blob:lalalal?thisworksinfirefox
For Chrome, the above will not work, but this will: blob:lalalla#?thisworksinchromeandfirefox
And for Safari and Microsaft, nothing really works, so do a pre test like so, then plan accordingly:
function initScriptMode() {
var file = new Blob(["test"], {type: "text/javascript"});
var url = URL.createObjectURL(file) + "#test?test";
var request = new XMLHttpRequest();
request.responseType = responseType || "text";
request.open('GET', url);
request.onload = function() {
alert("you can use query strings")
};
try {
request.send();
}
catch(e) {
alert("you can not use query strings")
}
}
If you are doing this with a Javascript Blob for say a WebWorker then you can just to add the parameters into the Blob constructor as a global variable:
const parameters = 'parameters = ' + JSON.stringify({foo:'bar'});
const body = response.body; // From some previous HTTP request
const blob = new Blob([parameters, body], { type: 'application/javascript' });
new Worker(URL.createObjectURL(blob));
Or more general case just store the original URL on the location object
const location = 'location.originalHref = "' + url + '";';
const body = response.body; // From some previous HTTP request
const blob = new Blob([location, body], { type: 'application/javascript' });
new Worker(URL.createObjectURL(blob));
You could also do this with HTML if you can add them say to the root <HTML> tag as attributes or use the <BASE> element for the url or insert them as a script tag but this would require you to modify the response HTML rather then just prepend some extra data

Categories

Resources