How to replace Javascript of production website with local Javascript? - javascript

On my production website, I have compiled Javascript.
<script src="/js/mycode.min.js"></script>
It would be very convient for debugging if I could make my browser replace that with
<script src="http://localhost/js/mycode1.js"></script>
<script src="http://localhost/js/mycode2.js"></script>
...
I know I could manipulate the DOM using something like Greasemonkey userscripts, but I couldn't come up with a solution which would prevent the execution of "mycode.min.js".
Any ideas?

The way I do it:
Download and install Fiddler if you are on windows.
Enable it to catch http traffic [IE/Chrome does it by default, Firefox - enable it through the add on it installs]
Load up the page in question.
Find the file you want to replace in the http traffic list on the left and click on it.
On the right there is an AutoResponder tab. click on it.
Click on the checkbox to "enable automatic responses"
Click Add.. button
The 2nd dropdown on right, choose the option that says "find a file"
Locate the file in the dialog and click save
Repeat steps 4-9 until you replace all the files you want to replace
Refresh the browser window and your new js files are running
Instead of replacing the js file, you can replace the html file and change the js links on the page.
You can install Charles if you are on a mac/linux. (not free, has trial) Steps are similar, but not the same.
If you are using Google Closure to compress files, you can install their plug-in to do the source mapping.

What about using a subdomain like http://static.example.comfor static files (e.g. .js files), and changing the hostfile?
<script type="text/javascript" src="http://static.example.com/js/mycode.min.js"></script>
Add the following line to the hostfile (/etc/hosts for Linux, C:\WINDOWS\System32\drivers\etc\host):
static.example.com 127.0.0.1
Of course you've to run a server with the files from http://static.example.com/ on 127.0.0.1.
Another solution is using a (local) proxy server like Privoxy for redirecting http://example.com/js/ to http://localhost/js/.

To add a NEW file you can use something like one of the other post:
document.body.appendChild(document.createElement("script").src = "http://example.com/addThisJSFile.js");
This tampermonkey script can replace any JS file on a webpage with your custom one from a domain:
// ==UserScript==
// #name ReplaceJS
// #namespace http://example.com/
// #version 1.0.0
// #description Replace javascript files on any webpage!
// #author Mr.Sonic Master
// #match *
// #run-at document-start
// ==/UserScript==
var newJSFile = "http://example.com/newJSFile.js"; //The JS file to load in replacment od old JS file
var oldJSFile = "oldJSFile.replaceThis.js"; //The old JS file as it is named in inspect element (make sure its spelled EXACTLY the same)
var pattern = new RegExp(oldJSFile, "i"); //Create the RegExp pattern with the /i switch to make it case-insensitive
function injectScript(originalPage) { //Function injectScript replaces the file
console.log('Replace stage 2: Replace text matching', oldJSFile, 'with', newJSFile);
var moddedPage = originalPage.replace(pattern, newJSFile); //Modify the HTML code that we got, replacing the old JS file with the new one
document.open();
console.log('Replace stage 3: Write new HTML to page...');
document.write(moddedPage); //Write to the page the new HTML code
document.close();
}
setTimeout(function() { //Wait a bit for the page's HTML to load...
console.log('Replace stage 1: target HTML');
injectScript(document.documentElement.outerHTML); //Run function injectScript with the page's HTML as oldPage in the function
}, 1111);

Without using any web proxy below chrome feature can be used to apply local overrides for js and css files
https://developer.chrome.com/blog/new-in-devtools-65/#overrides

Assuming your scripts are simply the raw version of the production file, you can just crack open your favorite debugger or JS console and import your scripts:
document.body.appendChild(document.createElement("script")).src =
"http://localhost/js/mycode1.js";
Doing so will overwrite the originally defined functions and variables. You'll have to manually re-run window.onload. If you have script that runs immediately or on load that changes much on the page, you may have some work to do to get it back to the original state.
Good luck!

Though the epascarello's solution works, there is a quicker solution for the minified files debugging. Consider using JavaScript source maps. Modern Firefox and Chrome supports them.
The idea of source map is to say browser where to find the unminified version. When you start the debugging in your browser developer tools - browser loads unminified version of the script and shows you the easy-to-read JavaScript (or whatever code you compiled to JavaScript) code in the debugger.

Add something to your URL to distinguish between your dev and prod context ;
example :
http://url_of_prod.com
http://url_of_dev.com?debug=true
and then, use some javascript to check if the GET variable debug is ON or NOT or check the URL with
if (window.location.host.indexOf(‘url_of_dev’) > -1) ...
THEN USE a load function to load or not your file, as in this example :
http://www.softpeople.fr/replaceswitch-dev-local-production-website-javascript-during-debug/

Related

Chrome edit 3rd party script [duplicate]

I would like to override a javascript file with my own version of the similar javascript file in chrome.
Let me explain:
Lets say a site 'http://example.com' calls 'http://example.com/script/somescript.js'.
What I would like to do is override the file 'http://example.com/script/somescript.js' with my own version located at 'http://localhost/script/somescript.js'.
I need to effectively modify a function in the original Javascript file.
With Chrome 65 this has become trivial.
Using local overrides – Chrome 65
What is it?
It is a new feature that allows us to override a websites code/css with a local copy that is persisted across sessions. Once you override a file it shall remain until you remove the override.
How to set it up?
Open the Sources panel.
Open the Overrides tab.
Open overrides tab
Click Setup Overrides.
Select which directory you want to save your changes to.
At the top of your viewport, click Allow to give DevTools read and write access to the directory.
Make your changes.
After you add a folder you can switch to the network tab and right click on any file and select “Save for overrides”. I have already overridden scripts.js so it shows with a “blue dot”.
There are plugins and tools in Chrome for these purposes:
Chrome's DevTools, tab Local Overrides (supported from Chrome 65)
Requestly
Resource Override
You might also want to use Tamper, which is a mitmproxy based devtools extension that lets you edit remote files locally and serve them directly to Chrome. (but it's more headache to install and use it)
Choose the one which is easier to use for you.
You can create a chrome extension yourself. It is surprisingly easy and takes only a few minutes if you use a tool like yeoman chrome extension. Create a new directory and run the generator
yo chrome-extension
Enter a name for your extension and a short description. Select Page Action and that you want to use Content Scripts. You can ignore other options - follow this excellent guide if you come in doubt, but it is really straight forward.
? What would you like to call this extension? insert-script
? How would you like to describe this extension? replace a function with another function
? Would you like to use UI Action? Page Action
? Would you like more UI Features? Content Scripts
? Would you like to set permissions?
..etc. Now you have a directory structure like this
app
bower_components
images
_locales
scripts.babel
background.js
chromereload.js
contentscript.js
You cannot replace an existing loaded remote script with another script, since the script already is loaded into the DOM. But you can insert a new script at the end of body which overrides the function you want to replace. Functions is variables, if you add a new function to the document with the same name as an existing function, the new function will be executed instead of the old, exactly as if you declared a new variable with the same name as an existing variable. Now open and edit contentscript.js :
'use strict';
console.log('\'Allo \'Allo! Content script');
The code could look like this
'use strict';
var code = `
function foo() {
alert('foo');
}
`;
var script = document.createElement('script');
script.textContent = code;
document.body.appendChild(script);
Notice the template literal. We need to insert the code as a string, but with backticks it is more readable. Replace foo() with the function you want to override.
There is no need for deployment or bundling. You can install your extension right away from the path where you runned the generator
go to chrome://extensions
check developer mode
click upload unpacked extension
select manifest.json from your path
after that you just have to hit reload on the extensions page when you have made changes to contentscript.js.
you can load your file into the page by adding (or executing in the console) this script.
window.onload = function () {
var script = document.createElement('script');
script.src = '//localhost/your/script';
script.onload = function() {
console.log('your script have been loaded');
}
document.body.appendChild(script);
}
If the file that you want to override contains global functions/variables will be override with the new version in your file or if the elements that you want to override are namespaced just follow the path (e.g My.namespace.method = myNewMethod)
According to dharam's answer above,Resource Override works.
For people who doesn't have access to Chrome store,you can download the source here:
https://github.com/kylepaulsen/ResourceOverride
in Chrome,get into chrome://extensions/ ,enable developer mode,then load the extracted source root directory(which contains the file manifest.json) into Chrome.
tested for Chrome 73.0.3683.86 on Windows 10 .I can't post anything on StackOverflow before because https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js is blocked.Then in the settings of ResourceOverride,I map it to https://localhost/jquery-1.12.4.min.js and it finally works.
I run an ASP.NET Core 2.1 project with SSL enabled and localhost certificate enabled to serve jquery-1.12.4.min.js from local disk.
In the launchSettings.json,there is
"applicationUrl": "https://localhost:443;http://localhost:80",
in the Kestral profile(not IIS profile).

Force browser to refresh javascript code while developing an MVC View?

Pretty straight-forward, I'm developing an MVC5 application and have noticed (lately) that my Browser appears to be caching the JavaScript code I have on the view within #section Scripts { }.
Currently I am developing with Chrome and I have tried CTRL+F5 & CTRL+SHFT+R which reloads the page, but the alert() I uncommented within the javascript code is still rendering as commented. I also tried going to my localhost through Incognito Mode as well as other Browsers (Firefox, IE) and am getting the same behavior. This is my /Home/Index.cshtml View, which is the default View which loads when the application starts. I have also tried adding some extra HTML text into the page and again the new code is not taking effect/showing.
My current Chrome version is Version 41.0.2272.118 m if anyone has any ideas what might be going on?
UPDATE:
I have gone under the Developer Tools => General Settings in Chrome and checked [X] Disable cache (while DevTools is open) and then repeatedly (with DevTools still open) tried CTRL+SHFT+R and CTRL+F5 with the same results of before where my changes are not taking effect.
UPDATE 2:
With DevTools open I have also held the Refresh button down and tried Normal/Hard/and Empty Cache & Hard Reload options all with the same result. For simplicity of testing I added an alert in the below to dispaly as soon as the page loads (and currently no alert comes up):
$(document).ready(function () {
alert("Test");
// Other Code/Functions -- No Error showing in Console
});
If you are using Bundling from MVC, you have two options to disable caching:
Use BundleTable.EnableOptimizations. This instructs the bundling to minify and optimize your bundle even while debugging. It generates a hash in the process, based on the content of the script, so your customers browsers can cache this file for a long time. It will generate a whole different hash the next time your file changes, so your customers can see your changes. The downside is that your script will become unreadable and you won't be able to debug it, so this might not be your best option.
Use System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("url", true) to resolve your script's URL, the second parameter (true) is requiring a hash to be generated with the URL, thus, preventing caching from your browser when you change the file. This is exactly the same hash generated in the first option, but without minifying.
I created a small demo showing that the second option prevents caching from happening, the trick is getting the hash generated from your script's content without minifying your script.
I created a script file called myscript.js with this content:
$(document).ready(function () {
alert('a');
});
Then I added this to my BundleConfig.cs:
// PLEASE NOTE this is **NOT** a ScriptBundle
bundles.Add(new Bundle("~/bundles/myscripts").Include(
"~/Scripts/myscript*"));
If you add a ScriptBundle, you will get a minified response again, since ScriptBundle is just a Bundle using JsMinify transformation (source). That's why we just use Bundle.
Now you can just add your script using this method to resolve the script URL with the hash appendend. You can use the Script.Render
#Scripts.Render(System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/bundles/myscripts", true))
Or the script tag:
<script src="#System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/bundles/myscripts", true)"></script>
Either way will generate a URL with a hash to prevent caching:
After editing my file:
You might want to add a no_cache variable after your script url like:
<script src="js/stg/Stg.js?nocache=#random_number"></script>
If you manage to put a random number to the place i indicated, the browser will automatically download the latest version of the script after an F5
A quick trick that solves this problem consists of opening the script file in a new tab, then refresh it on this page.
If you happen to have Chrome dev tools open it will even refresh it there.
From dev tool you can even easily right click-open in new tab the script.

How do I prevent Javascript from mutating a page in Selenium? How do I download the original page source? [duplicate]

This question already has answers here:
getting the raw source from Firefox with javascript
(3 answers)
Closed 8 years ago.
I'm not using Selenium to automate testing, but to automate saving AJAX pages that inject content, even if they require prior authentication to access.
I tried
tl;dr: I tried multiple tools for downloading sites with AJAX and gave up because they were hard to work with or simply didn't work. I'm resorting to using Selenium after trying out WebHTTrack (whose GUI wasn't able to start up on my Ubuntu machine + was a headache to provide authentication with in interactive-terminal mode), wget (which didn't download any of the scripts of stylesheets included on my page, see the bottom for what I tried with wget)... and then I finally gave up after a promising post on using a Mozilla XULRunner AJAX scraper called Crowbar simply seg-faulted on me. So...
ended up making my own broken thing in NodeJS and Selenium-WebdriverJS
My NodeJS script uses selenium-webdriver npm module which is "officially supported by the main project" to:
provide login information + do necessary button-clicking & typing for authentication
download all JS and CSS referenced on target page
download target page with original JS/CSS file links change to local file paths
Now when I view my test page locally I see double of many page elements because the target site loads HTML snippets into the page each time it's loaded. I use this to download my target page right now:
var $;
var getTarget = function () {
driver.getPageSource().then(function (source) {
$ = cheerio.load(source.toString());
});
};
var targetHtmlDest = 'test.html';
var writeTarget = function () {
fs.writeFile(targetHtmlDest, $.html());
}
driver.get(targetSite)
.then(authenticate)
.then(getRoot)
.then(downloadResources)
.then(writeRoot);
driver.quit();
The problem is that the page source I get is the already modified page source, instead of the original one. Trying to run alert("x");window.stop(); within driver.executeAsyncScript() and driver.executeScript() does nothing.
Perhaps using Curl to get the page (you can pass authentication in the command) will get you the bare source?
Otherwise you may be able to turn off JavaScript on your test browsers to prevent JS actions from firing.

How do I check if firebug is installed with javascript?

Here it is described how to check if Firebug is installed by checking if an image of firebug exists: http://webdevwonders.com/detecting-firefox-add-ons/
But it seems to be a bit outdated, cause the images he uses there don't exist anymore in firebug.
the firebug chrome.manifest looks like:
content firebug content/firebug/ contentaccessible=yes
...
but in the whole addon I only find one png now, and that is placed in the rootfolder of the addon. But some other content is accessible, for example: chrome://firebug/content/trace.js
Ho
So, in gerneral:
How do I make an image accessible that resides inside a Firefox SDK Addon?
I program an Addon and I want to make an image ok.png available to all javascripts in Firefox.
I added the image in the data folder and added a chrome.manifest
content response-timeout-24-hours data/
content response-timeout-24-hours data/ contentaccessible=yes
But no way to call it via a URL like
chrome://response-timeout-24-hours/data/ok.png
How do the paths belong together? which is relative to which?
I created a Bug report here.
So if you want to make your add-on detectable you need another approach:
you can use a PageMod to attach a content script that would wait for a
message from your web-app and "respond" by sending another message
back to your app. you would know that if you don't receive the
response, your addon is not installed. check out the documentation for
more details:
https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/page-mod
I used this to make my add-on detectable.

injectJs with PhantomJs and CasperJs

I am trying to use CasperJS to scrape a website that has dynamic content and am failing so far. The website uses a couple of js libaries(e.g. Prototype) to use autocomplete to create content. I am therefore trying to insert some values and trigger events to set off the content creation. Inserting and triggering events works fine, but no content is created.
I am new to CasperJS and found that it has problems with relative paths to the libaries. I suspect that my problem arises from the libaries not loading properly in my page environment. I therefore tried to use injectJs to inject them like this
// ... create casper and do some other stuff
casper.then(function() {
this.echo(this.page.injectJs('http://www.my-website.com/path/to/js1'));
this.echo(this.page.injectJs('http://www.my-website.com/path/to/js2'));
});
Unfortunately this returns false for both of the functions. The path to the script is correct, where else could be the root of this problem?
Thank you very much for any help.
I do not believe CasperJS can handle HTTP requests to inject scripts. This is weird because they actually show this in their FAQ on including jQuery. However, that same FAQ says the following:
You can't inject scripts using the HTTP protocol, you actually have to
use a relative/absolute filesystem path to the script resource.
Just to double check, I tried it myself using Mac OS X and your above code. The results of echo were false when using a file over http and true when it was local.
this is how I Inject Jquery in Casperjs script
casper.options.clientScripts = ["jquery-3.2.1.min.js"]
Jquery file should be on same directory where casperjs script exisit

Categories