Dynamically get web socket URL - javascript

I have a Play 2.5 application that uses a web socket. In my Controller I establish it as
def socket = WebSocket.accept[JsValue, JsValue] { request =>
ActorFlow.actorRef(out => TroiWebSocket.props(db, out, comm.communicator, system))
}
And, it's accessed in my routes as
GET /push-notifications controllers.Application.socket
As, currently, my application is running locally, I can reference the socket in a javascript file using
var socket = new WebSocket("ws://localhost:9000/push-notifications");
However, I'm starting to move my stuff away from the localhost, and need a way to reference the url in my javascript file. This URL might change (and could be different depending on the development environment). So, how can I reference this URL dynamically? That is, how do I say
var socket = new Websocket(URL_OF_WEBSOCKET)
I thought of breaking it up in my config files and trying to do it that way, but I'm not so sure that would work.
Any and all help would be appreciated.

If you are using plain javascript. Declare a File config.js and define some global Object with some config data.
<html>
<head>
<script>
var config = {
"localWSUrl" : "ws://localhost:9000/socket",
"wsUrl" : "ws://serverurl.com:443/socket"
}
</script>
<script>
console.log(config.wsUrl);
</script>
</head>
<body>
</body>
</html>
For simplicity sake I wrote everything in one file. You would exclude the config part and import the file via the script tag's src attribute. And then you can reuse it where you need it.

If the URL to get main page of your application is the same or partially same to connect websocket, suppose:
Url app: myapp.com
Websocket url: myapp.com/push-notification
So you could do in your js file using window.location of js standard api
var tcp = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
var host = window.location.host;
var path = '/push-notification';
var ws = new WebSocket(tcp+host+path);
Something like that..
I hope It helps.

Related

Accessing file with JS when files are a folder deeper than domain

We have a MVC site which uses subdomains. Not in the traditional sub.domain.com but instead we are using domain.com/sub. The source files all exist in the sub folders of each sub domain because each might have some slightly different things. This causes the Dev team to have to place JS directly into the razor pages so the razor code was able to update URLs like below.
var temp = $('div').load('#Url.Content("~/Images/Excel.png")');
Unfortunately using a code like below in a separate JS file tries loading from domain.com and not domain.com/sub
var temp = $('div').load('/Content/Templates/warning.html');
Theses add on to the domains and can change with clients. Is there a way to get the domain plus sub when the files are loaded like that in the JS without needing to place the code into the razor? I'd prefer a separation of concerns because we are loading scripts sometimes which aren't even used because of it.
what I always do when in similar situations is that I create a function in the main.js or whatever name your using for your shared js file, modify the URL in the function and use the function as the initiator:
in the main.js:
var loadFile = function(selector,path){
$(selector).load('/sub'+path);
}
and then whenever and wherever you wanna load a file:
var temp = loadFile('div','/Content/Templates/warning.html');
UPDATE
you can upgrade your loadFile function to let it know if it has to load from the root of the website if needed:
var loadFile = function(selector,path,loadFromRoot){
var root=(loadFromRoot) ? '' : '/sub';
$(selector).load(root+path);
}

How to create file(.apk) from URL in Jaggery?

I have application store and applications have their url. I want to download apks from those urls to my jaggery server. Although below code(my first solution) create myApp.apk successfully, its not work properly.
First i tried to below code,
var url = "http://img.xxx.com/006/someApp.apk";
var data = get(url, {});
var file = new File("myApp.apk");
file.open("w");
file.write(data.data);
file.close();
when i print data.data value, its look like
i also tried,
var file = new File("http://img.xxx.com/006/someApp.apk");
file.saveAs("myApp.txt");
Can anyone help me?
.apk files are Android application files, and they are expected to start with PK, because they are actually zip archives!
They're not meant to be unzipped, although you can do it to see some of the application resources (but there are better ways for reverse engineering .apk files such as Apktool, if that's what you're looking for).
According to jaggery documentations, file.write is writing the String representation of the object to the file. So that's why you are getting an apk file which cannot be installed.
However you can make it work using copyURLToFile in apache commons-io java library as follows since jaggery supports java itself and all of WSO2 products have apache commons-io library in their class path.
<%
var JFileUtils = Packages.org.apache.commons.io.FileUtils;
var JUrl = Packages.java.net.URL;
var JFile = Packages.java.io.File;
var url = new JUrl("http://img.xxx.com/006/someApp.apk");
JFileUtils.copyURLToFile(url, new JFile("myApp.apk"));
print("done");
%>
Your file will be stored on $CARBON_HOME directory by default, unless you specified relative or absolute path to the file.

My relative URL path to my View breaks on Deployment

I have a very standard ASP MVC app that I use a little javascript to show a Partial View. In order to make that Javascript work I needed to hard code a path to the Partial which is different between Dev and Production.
Mainly, in Dev there is no App specification where as in Production there is. See here:
Production=var URL = '/WetWashRequest/wetWashRequests/GetDetails?WONumber=' + wo;
Dev = var URL = '/wetWashRequests/GetDetails?WONumber=' + wo;
What this means is that as I work on it locally I delete the first part and when I want to deploy I have to remember to re add it.
This seems so ridiculously flawed that I can only assume I am being ignorant and doing something wrong...
You can take advantage of UrlHelper to get the URLs, as long as you do it in view:
var URL = '#Url.Action("GetDetails")';
Obviously, it doesn't make sense to put all your JavaScript in view, so what I will normal do is set just this in my view, in a namespace var, and then reference it in my external JavaScript:
View
<script>
var MyApplication = MyApplication || {};
MyApplication.GetDetailsUrl = '#Url.Action("GetDetails")';
</script>
External JS
$.get(MyApplication.GetDetailsUrl, { WONumber: wo }, function (result) {
...
});

Javascript Get Hostname of File Host

Although this question is similar, it is not what I am looking for.
Let's say on HostA.com I include a script from HostB.com:
<script type="text/javascript" src="http://www.hostb.com/script.js">
When script.js runs, I need to get the name of HostB (let's assume it can change). If I use:
var hostName = window.location.hostname;
It will return HostA.com rather than HostB.com obviously because that is where the the window object is scoped.
How can I get the name of HostB from within the script? Do I have to locate the <script> element in the DOM and parse the src attribute or is there a better way?
EDIT
Yes, it is on my server, but may be on other servers as well. I am developing a javascript plugin and am trying to make absolute paths so it doesn't try to reference files on the server including the plugin.
Here is how: first off, include this as the first line of your script. I know it is a comment. Do it anyways
//BLAHBLAHBLAHBLAHAAABBBCCCDDDEEEFFFGGGILIKEPI
next, use this function inside of that script to determine the host
function findHost(){
var scripts=document.getElementsByTagName('script');
var thisScript=null;
for(var i=0;i<scripts.length;i++){
if(scripts[i].innerHTML.indexOf('//BLAHBLAHBLAHBLAHAAABBBCCCDDDEEEFFFGGGILIKEPI')!==-1)
var thisScript=scripts[i];
}
var urlParser=document.createElement('a');
urlParser.href=thisScript.getAttribute('src');
return urlParser.hostname;
}
I am loading the script with RequireJS which looks something like this:
<script data-main="http://hostb.com/js/app/main.js" src="http://hostb.com/js/vendor/require.js" type="text/javascript"></script>
I figured out, with help from #adeneo that I can do something like this:
$('script[data-main*="/js/app/main.js"]').attr('data-main')
Which returns:
http://hostb.com/js/app/main.js
And I can parse it for the hostname.
var url = $('script[data-main*="/main.js"]').attr('data-main');
parser = document.createElement('a');
parser.href = url;
host = parser.hostname;
Thanks for the suggestions and nudge in the right direction!
BREAKING NEWS
Turns out their is an easier way for anyone using RequireJS (who finds this question in search) and needs to be able to load absolute URL's with the script host:
var myCssPath = require.toUrl('css/mystyles.css');
That builds an absolute path using the hostname of the server running!
To omit using the hostname twice (as you described in your 'accepted answer') I implemented the solution this as follows:
HTML on HostA.com:
<script data-main="my_embed_id" src="http://hostb.com/js/vendor/require.js" type="text/javascript"></script>
require.js on HostB.com:
// get host where this javascript runs
var url = $('script[data-main="my_embed_id"]').attr('src');
var hostb = url.replace(/(\/\/.*?\/).*/g, '$1');
Which returns:
http://hostb.com
Inspired by: How to make an external javascript file knows its own host?

How to customize public js files in Node.js by environment?

I'm trying to customize public javascript files based upon the environment. Specifically, for socket.io, I'm trying to customize the location the client will connect to:
development:
var socket = io.connect('http://localhost/chat');
production:
var socket = io.connect('http://xxx.xxx.xxx.xxx/chat');
I know all about environment variables within the app itself (and I do use node environment variables through express), but from what I can tell these variables won't touch the public static js files I'm serving to the client.
What's the best way to go about achieving this contextual switch based upon development/production environments?
If you're writing unobtrusive JavaScript and using a proper bundling system, then each HTML page you deliver should reference only a single "loader" script, which is then responsible for bringing in all the rest of the scripts. Create two versions of that script, one for development and one for production, and give them different names. When rendering HTML, make the name of the script a template variable which you'll have set based on your environment. Your loader script can then set appropriate variables to be used by the scripts it brings in.
The way I approached it was to load the socket.io in the layout page:
<script src='<%= socketIoUrl %>/socket.io/socket.io.js'></script>
<script type="text/javascript">
var socket = io.connect('<%= socketIoUrl %>');
</script>
Then I added a dynamic helper to expose the socketIoUrl:
var helpers = function(app) {
app.dynamicHelpers({
socketIoUrl: function(req, res) {
return app.settings.socketIoUrl;
}
});
};
module.exports = helpers;
And so in my server.js file I set the appropriate value based on the environment and loaded the helper file:
app.configure('development', function(){
app.set('socketIoUrl', 'http://localhost:3003');
});
app.configure('test', function(){
app.set('socketIoUrl', 'http://...');
});
app.configure('production', function(){
app.set('socketIoUrl', 'http://...');
});
require('./apps/helpers')(app);
So now you can use the socket variable created in your layout page in any other js file you have.

Categories

Resources