get html page as response from url inside an extension - javascript

I am developing an extension in which whatever request is coming i want to change the request parameters and send a dummy request to server to get response.
for eg. if original request loaded is www.abc.com/eg.php?user="some code", then i want to change it into www.abc.com/eg.php?user="ritubala" and get html page in the response for further processing inside my extension..
i used these codes given in following url
Return HTML content as a string, given URL. Javascript Function
but it is causing recursion...
so in short i want to get html code from a url inside my extension...plz do help

Use nsITraceableChannel, note that you get a copy of the content being loaded.
If you abort the request then it aborts giving you a copy.
Here's me using nsITraceableChannel: https://github.com/Noitidart/demo-nsITraceableChannel
What I think you want is this:
const { Ci, Cu, Cc, Cr } = require('chrome'); //const {interfaces: Ci, utils: Cu, classes: Cc, results: Cr } = Components;
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/devtools/Console.jsm');
var observers = {
'http-on-examine-response': {
observe: function (aSubject, aTopic, aData) {
console.info('http-on-modify-request: aSubject = ' + aSubject + ' | aTopic = ' + aTopic + ' | aData = ' + aData);
var httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
var requestUrl = httpChannel.URI.spec
if (requestUrl.indexOf('blah')) {
//httpChannel.cancel(Cr.NS_BINDING_ABORTED); //this is how you abort but if use redirectTo you don't need to abort the request
httpChannel.redirectTo(Services.io.newURI('http://www.anotherwebsite/', null, null));
}
},
reg: function () {
Services.obs.addObserver(observers['http-on-modify-request'], 'http-on-modify-request', false);
},
unreg: function () {
Services.obs.removeObserver(observers['http-on-modify-request'], 'http-on-modify-request');
}
}
};
//register all observers
for (var o in observers) {
observers[o].reg();
}
note the redirectTo function is for FF20+
https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsIHttpChannel#redirectTo%28%29
so combine this example with the nsITraceableChannel demo and you'll have what you want.
if you don't want to redirect you can abort the request, get the DOCUMENT of the request and then xmlhttprequest the new page which gives you the source FIRST and doesnt load it to tab, and then modify the source then load it back to the DOCUMENT.
OR instead of xmlhttprequesting it, just abort the request, redirectTo the new page and then modify the tab. to get the tab of the channel see solution here:
Security Error when trying to load content from resource in a Firefox Addon (SDK)
also to do http requests from an extension see this snippet: https://gist.github.com/Noitidart/9088113

Related

Capture REST calls with Selenium

I run integration test with Selenium as a test runner and webdriver.io javascript library for Selenium API.
My test goes as follows:
I load an html page and click on a button. I want to check if a Get REST call was invoked.
I found a plugin for webdriver.io called webdriverajax that intend to fit to my requirements but it just doesn't work.
Any ideas how do capture rest calls?
You can achieve this by using custom HttpClient class that is out side from selenium code.As far as i know selenium doesn't support this feature.
Assume when you clicked the button it will called a REST service , the URL can be grab from the HTML DOM element.Then you can use your custom code to verify if URL is accessible or not.Then you can decide if your test is pass or failed based on the status code or some other your mechanism.
FileDownloader.java(Sample code snippet)
private String downloader(WebElement element, String attribute) throws IOException, NullPointerException, URISyntaxException {
String fileToDownloadLocation = element.getAttribute(attribute);
if (fileToDownloadLocation.trim().equals("")) throw new NullPointerException("The element you have specified does not link to anything!");
URL fileToDownload = new URL(fileToDownloadLocation);
File downloadedFile = new File(this.localDownloadPath + fileToDownload.getFile().replaceFirst("/|\\\\", ""));
if (downloadedFile.canWrite() == false) downloadedFile.setWritable(true);
HttpClient client = new DefaultHttpClient();
BasicHttpContext localContext = new BasicHttpContext();
LOG.info("Mimic WebDriver cookie state: " + this.mimicWebDriverCookieState);
if (this.mimicWebDriverCookieState) {
localContext.setAttribute(ClientContext.COOKIE_STORE, mimicCookieState(this.driver.manage().getCookies()));
}
HttpGet httpget = new HttpGet(fileToDownload.toURI());
HttpParams httpRequestParameters = httpget.getParams();
httpRequestParameters.setParameter(ClientPNames.HANDLE_REDIRECTS, this.followRedirects);
httpget.setParams(httpRequestParameters);
LOG.info("Sending GET request for: " + httpget.getURI());
HttpResponse response = client.execute(httpget, localContext);
this.httpStatusOfLastDownloadAttempt = response.getStatusLine().getStatusCode();
LOG.info("HTTP GET request status: " + this.httpStatusOfLastDownloadAttempt);
LOG.info("Downloading file: " + downloadedFile.getName());
FileUtils.copyInputStreamToFile(response.getEntity().getContent(), downloadedFile);
response.getEntity().getContent().close();
String downloadedFileAbsolutePath = downloadedFile.getAbsolutePath();
LOG.info("File downloaded to '" + downloadedFileAbsolutePath + "'");
return downloadedFileAbsolutePath;
}
TestClass.java
#Test
public void downloadAFile() throws Exception {
FileDownloader downloadTestFile = new FileDownloader(driver);
driver.get("http://www.localhost.com/downloadTest.html");
WebElement downloadLink = driver.findElement(By.id("fileToDownload"));
String downloadedFileAbsoluteLocation = downloadTestFile.downloadFile(downloadLink);
assertThat(new File(downloadedFileAbsoluteLocation).exists(), is(equalTo(true)));
assertThat(downloadTestFile.getHTTPStatusOfLastDownloadAttempt(), is(equalTo(200)));
// you can use status code to valid the REST URL
}
Here is the reference.
Note: This may not exactly fit into your requirement but you can get some idea and modify it accordingly to fit into your requirement.
Also refer the BrowserMob Proxy using this you can also achieve what you want.
The problem was the webdriver.io version. Apparently, webdriverajax works fine just with webdriver.io v3.x but not with v4.x. I use v4.5.2.
I decide not using a plugin and implement a mock for window.XMLHttpRequest
open and send methods, as follows:
proxyXHR() {
this.browser.execute(() => {
const namespace = '__scriptTests';
window[namespace] = { open: [], send: [] };
const originalOpen = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function (...args) {
window[namespace].open.push({
method: args[0],
url: args[1],
async: args[2],
user: args[3],
password: args[4]
});
originalOpen.apply(this, [].slice.call(args));
};
window.XMLHttpRequest.prototype.send = function (...args) {
window[namespace].send.push(JSON.parse(args[0]));
};
});
}
getXHRsInfo() {
const result = this.browser.execute(() => {
const namespace = '__scriptTests';
return window[namespace];
});
return result.value;
}

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

nodejs: node-http-proxy and harmon: rewriting the html response from the end point instead of the 302 redirected response.

I'm using nodejs with node-http-proxy along with harmon. I am using harmon to rewrite the proxied response to include a javascript file and a css file. When I set the target of the proxy to be http://nodejs.org or anything other than localhost, I receive a 301 or 302 redirect. The script is rewriting the 301 response instead of the fully proxied response. How can I use harmon to rewrite the end response instead of the 302 response?
Here is the example of the script I am running from the harmon example folder:
var http = require('http');
var connect = require('connect');
var httpProxy = require('http-proxy');
var selects = [];
var simpleselect = {};
//<img id="logo" src="/images/logo.svg" alt="node.js">
simpleselect.query = 'img';
simpleselect.func = function (node) {
//Create a read/write stream wit the outer option
//so we get the full tag and we can replace it
var stm = node.createStream({ "outer" : true });
//variable to hold all the info from the data events
var tag = '';
//collect all the data in the stream
stm.on('data', function(data) {
tag += data;
});
//When the read side of the stream has ended..
stm.on('end', function() {
//Print out the tag you can also parse it or regex if you want
process.stdout.write('tag: ' + tag + '\n');
process.stdout.write('end: ' + node.name + '\n');
//Now on the write side of the stream write some data using .end()
//N.B. if end isn't called it will just hang.
stm.end('<img id="logo" src="http://i.imgur.com/LKShxfc.gif" alt="node.js">');
});
}
selects.push(simpleselect);
//
// Basic Connect App
//
var app = connect();
var proxy = httpProxy.createProxyServer({
target: 'http://nodejs.org'
})
app.use(require('../')([], selects, true));
app.use(
function (req, res) {
proxy.web(req, res);
}
);
The problem is that a lot of sites are now redirecting HTTP to HTTPS.
nodejs.org is one of those.
I have updated the sample https://github.com/No9/harmon/blob/master/examples/doge.js to show how the http-proxy needs to be configured to deal with HTTPS.
If you still have problems with other arbitrary redirects please log an issue on harmon.
Thanks

nodejs : get url in OutgoingMessage

My goal is to intercept every outgoing message from my server in a meteor project and add some stuff (meta datas and additional contents)
I have this simple code :
var http = Npm.require( 'http' ),
originalWrite = http.OutgoingMessage.prototype.write;
http.OutgoingMessage.prototype.write = function ( chunk, encoding ) {
console.log( this, arguments );
chunk = chunk.replace( 'some code', 'elements to add' );
originalWrite.call( this, chunk, encoding );
}
It works but I cannot find the url of the current call. This is a problem because I need to add different elements according to the called url.
(nota : I have a condition to make sure the request is an html file)
The full URL isn't directly available but host and path are through the request header Host and a property path on the OutgoingMessage object.
To obtain the full URL:
var url = this.getHeader('host') + this.path; //or this._headers.host;
--
var originalWrite = http.OutgoingMessage.prototype.write;
http.OutgoingMessage.prototype.write = function () {
var url = this.getHeader('host') + this.path;
//...
return originalWrite.apply(this, arguments);
};
The reason path isn't available in the header is because the request path is part of the Request-Line. The OutgoingMessage implementation first establishes a TCP connection to the host and then issues a request on the path.
GET /path HTTP/1.1
Host: hostname

Accessing JSON data when PhantomJS onResourceReceived is triggered (ESPN fantasy football draft app)

So I'm trying to write a hook into ESPN fantasy football's HTML lite draft page to cross-reference player ranking lists (from a CSV file) to eliminate already-drafted players from the available pool. I've done this by hand in the past: but with a 16-team draft by the late rounds, it's nearly impossible to keep up since by then no one really knows who the players are.
I'm very much a Javascript and PhantomJS newbie, so please don't laugh.
At this point, I can see the page.onResourceReceived metadata in my console as the AJAX polls the PhantomJS instance. But I can't figure out how to access the data actually being received by the "browser". According to Chrome's inspector, the "Preview" tab under the Network Inspector tab -- either a time sync signal or the data of the actual player who was drafted is being sent to the browser in JSON format.
Long story short, how do I get the actual JSON data when I receive the page.onResourceReceived metadata?
(P.S. I know I commented out phantom.exit(); that's to keep the script from terminating after the redirect and onLoad is complete--I need to keep it running to listen for the draft updates)
var draft = 'http://games.espn.go.com/ffl/htmldraft?leagueId=1246633&teamId=8&fromTeamId=8';
var draftURL = encodeURIComponent(draft);
var page = require('webpage').create(),
server = 'https://r.espn.go.com/espn/memberservices/pc/login',
data = 'SUBMIT=1&failedLocation=&aff_code=espn_fantgames&appRedirect=' + draftURL + '&cookieDomain=.go.com&multipleDomains=true&username=[redacted]&password=[redacted]&submit=Sign+In';
page.onResourceReceived = function (response) {
console.log('Response (#' + response.id + ', stage "' + response.stage + '"): ' + JSON.stringify(response));
};
page.open(server, 'post', data, function (status) {
if (status !== 'success') {
console.log('Unable to post!');
} else {
page.render('example.png');
//console.log(page.content)
}
//phantom.exit();
});
The following version of your script will just grab and return the entire contents of the URL you are accessing. You are not really going to get useful json data, I don't think, just an html page, unless I'm missing something. In my tests, all I get is html:
var draft = 'http://games.espn.go.com/ffl/htmldraft?leagueId=1246633&teamId=8&fromTeamId=8';
var draftURL = encodeURIComponent(draft);
var page = require('webpage').create(),
server = 'https://r.espn.go.com/espn/memberservices/pc/login',
data = 'SUBMIT=1&failedLocation=&aff_code=espn_fantgames&appRedirect=' + draftURL + '&cookieDomain=.go.com&multipleDomains=true&username=[redacted]&password=[redacted]&submit=Sign+In';
page.open(server, 'post', data, function (status) {
if (status == 'success') {
var delay, checker = (function() {
var html = page.evaluate(function () {
var body = document.getElementsByTagName('body')[0];
return document.getElementsByTagName('html')[0].outerHTML;
});
if (html) {
clearTimeout(delay);
console.log(html);
phantom.exit();
}
});
delay = setInterval(checker, 100);
}
else {
phantom.exit();
}
});
Currently, phantomjs doesn't include the response body in the onResponseReceived events.
You could instead slimerjs, which mirrors the phantomjs, but does allow you to access response.body (which should have the JSON data). Example here:
http://darrendev.blogspot.jp/2013/11/saving-downloaded-files-in-slimerjs-and.html
Alternatively, you could write a chrome extension and create a content script that grabs the data.

Categories

Resources