Polite Master
Polite Master

Reputation: 125

Cross-origin JSON request

I am writing HTML/CSS/JS for a Twitch.tv application. I request (public, non-sensitive) data through their main API endpoint (api.twitch.tv), but one piece of data has not been integrated. This data, however, is viewable at another sub-domain (tmi.twitch.tv). Unfortunately, when I make a $.getJSON call (or $.AJAX with dataType: JSON), I receive the following in Firefox 44.0.2:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://tmi.twitch.tv/{rest of URL}. (Reason: CORS header 'Access-Control-Allow-Origin' missing).

I've known of this security mechanism as a user, but not as a (novice) programmer. I read a lot in attempt to manage, but I am still lost.

What I've gathered: A common workaround is requesting JSONP. Unlike JSON, the browser does not enforce cross-origin policy on JSONP. I know that the main Twitch API is JSONP-friendly and probably has CORS enabled. In contrast, I imagine tmi.twitch.tv does not have CORS enabled.

What I've tried: I've appended my request URL with ?callback=, ?callback=differentStrings, and ?otherQuery=value&callback=differentStrings. These did not work. I changed my dataType to jsonp, and without additional query strings (just changing dataType appended two query strings: callback=jQuery{long number}_{long number} & _={long number}, I did not receive an x-origin block. However, I did get the following:

SyntaxError: missing ; before statement | Line 1: Character 8

for this object I requested:

{"hosts":[{"host_id":118084843,"target_id":41981587,"host_login":"politecpu","target_login":"politemaster"},{"host_id":118082906,"target_id":41981587,"host_login":"politerobot","target_login":"politemaster"}]}

I am stuck. I do not know if this is a problem with the format of the data/JSONP nor if I found a workaround for x-origin, as my success(-ful receipt of data) function did not work. What should I consider next?

I'd like to emphasize that I am an absolute novice (I only recently completed Codecademy lessons for JS and jQuery). Thank you kindly in advance for thoughts and comments.

(Edit) My function:

var allHosts = [];  // To be compared against new JSON periodically called via checkHosts()
var getHosts = function() {
	allHosts = [];
	$.ajax({
		url: 'https://tmi.twitch.tv/hosts?include_logins=1&target=' + myID,
		dataType: 'jsonp',
		success: function(data) {
			data.hosts.forEach(function(element) {
				allHosts.push(element.host_id);
			});
			debug('getHosts():', 'data =', data, 'allHosts =', allHosts, 'queue =', queue, 'busy =', busy); // Not relevant
		},
	});
}

Upvotes: 0

Views: 2845

Answers (3)

Satyajit Paul
Satyajit Paul

Reputation: 345

Try this - https://api.allowallorigin.com/restapi?url=https://tmi.twitch.tv/hosts?include_logins=1&target=007

I have created this solution after trying multiple options. The other solution on the same line does the job but changes the JSON Data locations until one pays for it. Above service is free and will continue to remain free. If people find it useful, then I may put a home page and few google ads but otherwise it should continue to remain free for foreseeable future.

Here is an example code:

jPath.prototype.loadJSONDataFromUrl = function(_url, callback) {
    $.getJSON(_url, function(data) {
        $.fn.jsonData = JSON.stringify(data);
    }).done(function(json){
        if( callback != null) {
            callback();
        }
    }).fail(function(){
        $.getJSON('https://api.allowallorigin.com/allorigin/restapi?url='+_url, function(data) {
            console.log(data);
            console.log(JSON.stringify(data));
            $.fn.jsonData = JSON.stringify(data);
        }).done(function(json){
            if( callback != null) {
                callback();
            }
        });
    });
}

Upvotes: 0

Webdev
Webdev

Reputation: 647

You can accomplish this by adding a header to your request

    var allHosts = [];
    // To be compared against new JSON periodically called via checkHosts()
    var getHosts = function() {
    allHosts = [];
    $.ajax({
        url: 'https://tmi.twitch.tv/hosts?include_logins=1&target=' + myID,
        dataType: 'jsonp',
        headers: {
'Access-Control-Allow-Origin':URLofOrigin
}, success: function(data) { data.hosts.forEach(function(element) { allHosts.push(element.host_id); }); debug('getHosts():', 'data =', data, 'allHosts =', allHosts, 'queue =', queue, 'busy =', busy); // Not relevant }, }); }

Upvotes: 0

caszi
caszi

Reputation: 135

As seen here and here it looks like you are trying to access a JSON resource using JSONP. The domain does not support JSONP.

You might be able to accomplish what you want using a server side language which will fetch the resource on behalf of the user.

Upvotes: 1

Related Questions