Load Balancer module CORS header

Hello

We are writing a player in javascript and need to hit the load balancer to get the least loaded server to play from. However we get the CORS restriction No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

Is there a way to add this into the loadbalancer without having to add it in the source of the module ?

Ideally it would be great if we could enable it somewhere in a vanilla wowza install without having to write any custom module.

Thank you

Arpan

Hi Arpan,

How is this all setup? You are using the XMLHTTPRequest api?

Richard

Oh, sorry, don’t know how I missed this

Looks like what you need.

Richard

Does the solution offered in this post help?

Otherwise, I will have to ask around about this. It’s not come up before that I can remember, I would suppose that others are querying the load balancer this way, though I would think the usual way is in an application server (php load() for example) to avoid the clients with javascript turned off.

Richard

Hi Arpan,

I can replicate the problem, and am seeing what can be done to fix it. I don’t think there is a configurable way to add the Access-Control-Allow-Origin header, but there is a work-around. I will check further for configurable option and make a request if necessary to add that. Meanwhile, the work-around is a simple HTTPProvider (You have to import wms-plugin-loadbalancer.jar from the Load Balancer package):

package com.wowza.wms.example.module;
import com.wowza.wms.http.*;
import com.wowza.wms.vhost.*;
import com.wowza.wms.plugin.loadbalancer.HTTPLoadBalancerRedirector;
public class HTTPLeastLoaded extends HTTPLoadBalancerRedirector {
	public void onHTTPRequest(IVHost vhost, IHTTPRequest req, IHTTPResponse resp) {
		if (!doHTTPAuthentication(vhost, req, resp))
			return;
		resp.setHeader("Access-Control-Allow-Origin", "*");
		super.onHTTPRequest(vhost, req, resp);
	}
}

Add the project .jar file to your Wowza /lib folder, then change the BaseClass of the HTTPProvider of the Load Balancer Listener

<HTTPProvider>
        <BaseClass>com.wowza.wms.example.module.HTTPLeastLoaded</BaseClass>
        <RequestFilters>*loadbalancer</RequestFilters>
        <AuthenticationMethod>none</AuthenticationMethod>
        <Properties>
                <Property>
                        <Name>enableServerInfoXML</Name>
                        <Value>true</Value>
                        <Type>Boolean</Type>
                </Property>
        </Properties>
</HTTPProvider>

Then re-start Wowza.

I tested with this (from here):

<html>
<head><title>LB test</title></head>
<body>
<span id='leastloaded'>least loaded server</span>
<script>
function sendRequest(url,callback,postData) {
	var req = createXMLHTTPObject();
	if (!req) return;
	var method = (postData) ? 'POST' : 'GET';
	req.open(method,url,true);
	req.setRequestHeader('User-Agent','XMLHTTP/1.0');
	if (postData)
		req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
	req.onreadystatechange = function () {
		if (req.readyState != 4) return;
		if (req.status != 200 && req.status != 304) {
			alert('HTTP error ' + req.status);
			return;
		}
		callback(req);
	}
	if (req.readyState == 4) return;
	req.send(postData);
}
var XMLHttpFactories = [
	function () {return new XMLHttpRequest()},
	function () {return new ActiveXObject('Msxml2.XMLHTTP')},
	function () {return new ActiveXObject('Msxml3.XMLHTTP')},
	function () {return new ActiveXObject('Microsoft.XMLHTTP')}
];
function createXMLHTTPObject() {
	var xmlhttp = false;
	for (var i=0;i<XMLHttpFactories.length;i++) {
		try {
			xmlhttp = XMLHttpFactories[i]();
		}
		catch (e) {
			continue;
		}
		break;
	}
	return xmlhttp;
}
function handleRequest(req) {
	document.getElementById('leastloaded').innerHTML = req.responseText;
}
sendRequest('http://[wowza-address]:1935/loadbalancer',handleRequest);
</script>
</body>
</html>

Richard

Hi Richard

we are using a simple jquery $.get for it.

the setup is on aws. we are using the load balancer module in wowza to get the least loaded server - we have an app that needs to do logic before it starts playing HLS, so we are doing a $.get(‘loadbalancer’) to get the least loaded server and then create the path to the file based on that.

But hitting the load balancer is what is throwing the access control origin issue - this is what we want to enable globally without doing a custom module or a proxy.

Is that possible ?

                       $.ajax({
					url: "http://wowzaip/loadbalancer",
					dataType: "text",
					type: "GET",
					success: function(data) { 
						var ip = data.split('=')[1];
						console.log('playing from: ' + ip);
					}
				});
			}

Hi Richard

I saw that one, thats for the playlist though, we dont have a problem with the m3u8 files, the initial hit to the loadbalancer before we get the m3u8 is the problem.

So I dont really have an application to put that in since the loadbalancer module is in teh server.xml

is there a property just like that for the loadbalancer module ?

Hi Richard

That won’t work as its related to htaccess and we are hitting wowza directly via javascript. Its basically the code below

$.ajax({
					url: "http://wowzaloadbalancerip/loadbalancer",
					dataType: "text",
					type: "GET",
					success: function(data) { 
						var ip = data.split('=')[1];
						console.log('playing from: ' + ip);
					}
				});

this generates a CORS error. to circumvent this we can do a proxy through another script that calls the load balancer script directly but that means we have to maintain an application stack, we are trying to avoid this just for a proxy

Thank you

Arpan

ill try this out thanks richard

Hi Jack.

Can you please provide as much info on your server setup as possible? Explain your workflow and what issues you are seeing in the logs.

Regards,

Salvadore

Hello Jack,

Adding CORS headers was integrated into the the Load Balancer v4.0 and can be can be configured as follows:

You’ll need to add the following property to the Properties container at the end of the file [install-dir]/conf/Server.xml

<Property> 
<Name>httpUserHTTPHeaders</Name> 
<Value>Access-Control-Allow-Origin:*|Access-Control-Allow-Credentials:true|Access-Control-Expose-Headers:Date|Access-Control-Allow-Methods:HEAD, GET, POST|Access-Control-Allow-Headers:Overwrite, Destination, Content-Type, Depth, User-Agent, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control, Range</Value> 
<Type>String</Type> 
</Property>

You can change the value in the above to what you need the headers to be.

Please give the update a try and let us know how it goes.

Regards,

Jason Hatchett

Hi Arpan,

I can replicate the problem, and am seeing what can be done to fix it. I don’t think there is a configurable way to add the Access-Control-Allow-Origin header, but there is a work-around. I will check further for configurable option and make a request if necessary to add that. Meanwhile, the work-around is a simple HTTPProvider (You have to import wms-plugin-loadbalancer.jar from the Load Balancer package):

package com.wowza.wms.example.module;
import com.wowza.wms.http.*;
import com.wowza.wms.vhost.*;
import com.wowza.wms.plugin.loadbalancer.HTTPLoadBalancerRedirector;
public class HTTPLeastLoaded extends HTTPLoadBalancerRedirector {
	public void onHTTPRequest(IVHost vhost, IHTTPRequest req, IHTTPResponse resp) {
		if (!doHTTPAuthentication(vhost, req, resp))
			return;
		resp.setHeader("Access-Control-Allow-Origin", "*");
		super.onHTTPRequest(vhost, req, resp);
	}
}

Add the project .jar file to your Wowza /lib folder, then change the BaseClass of the HTTPProvider of the Load Balancer Listener

<HTTPProvider>
        <BaseClass>com.wowza.wms.example.module.HTTPLeastLoaded</BaseClass>
        <RequestFilters>*loadbalancer</RequestFilters>
        <AuthenticationMethod>none</AuthenticationMethod>
        <Properties>
                <Property>
                        <Name>enableServerInfoXML</Name>
                        <Value>true</Value>
                        <Type>Boolean</Type>
                </Property>
        </Properties>
</HTTPProvider>

Then re-start Wowza.

I tested with this (from here):

<html>
<head><title>LB test</title></head>
<body>
<span id='leastloaded'>least loaded server</span>
<script>
function sendRequest(url,callback,postData) {
	var req = createXMLHTTPObject();
	if (!req) return;
	var method = (postData) ? 'POST' : 'GET';
	req.open(method,url,true);
	req.setRequestHeader('User-Agent','XMLHTTP/1.0');
	if (postData)
		req.setRequestHeader('Content-type','application/x-www-form-urlencoded');
	req.onreadystatechange = function () {
		if (req.readyState != 4) return;
		if (req.status != 200 && req.status != 304) {
			alert('HTTP error ' + req.status);
			return;
		}
		callback(req);
	}
	if (req.readyState == 4) return;
	req.send(postData);
}
var XMLHttpFactories = [
	function () {return new XMLHttpRequest()},
	function () {return new ActiveXObject('Msxml2.XMLHTTP')},
	function () {return new ActiveXObject('Msxml3.XMLHTTP')},
	function () {return new ActiveXObject('Microsoft.XMLHTTP')}
];
function createXMLHTTPObject() {
	var xmlhttp = false;
	for (var i=0;i<XMLHttpFactories.length;i++) {
		try {
			xmlhttp = XMLHttpFactories[i]();
		}
		catch (e) {
			continue;
		}
		break;
	}
	return xmlhttp;
}
function handleRequest(req) {
	document.getElementById('leastloaded').innerHTML = req.responseText;
}
sendRequest('http://[wowza-address]:1935/loadbalancer',handleRequest);
</script>
</body>
</html>

Richard

I am running into this same issue, and it appears that this solution no longer works with the updated WowzaLoadBalancer 4.0 Module. Is there any way to achieve this same result with the new library?

Hi Jack.

Can you please provide as much info on your server setup as possible? Explain your workflow and what issues you are seeing in the logs.

Regards,

Salvadore

Hey Salvadore!

I haven’t been able to implement anything yet. The example custom module provided as a solution is no longer a viable option as the API of the Load Balancer module has changed with v 4.0. The classes in the module are named differently, therefore it doesn’t appear that there is a way to extend the same services as in the previous example. Is there an updated solution for how to do this using the Load balancer 4.0 module.

Best,

Jack