Getting "spc message cannot be null" as response every time while providing implementation of Shaka player to play fairplay content on safari browser.Tried many ways to provide spc message in body and header also and we are actually sending it that i can see in network tab nut still cant find a solution. Here is the code below.
if (this.platform.getBrowserPlatform() === Constants.PLATFORMS.SAFARI_WEB) {
this.shakaPlayer.configure({
drm: {
servers: {
'com.apple.fps.1_0': `${this.config.baseUrl}${Constants.DRM_FAIRPLAY_LICENSE}`,
},
advanced: {
'com.apple.fps.1_0': {
serverCertificate: cert,
},
},
},
});
let that = this //,licenseUri;
this.shakaPlayer.configure('drm.initDataTransform', (initData) => {
const skdUri = shaka.util.StringUtils.fromBytesAutoDetect(initData);
var contentId = skdUri.substring(skdUri.indexOf('skd://') + 6);
// licenseUri = skdUri.replace('skd://', 'https://');
const url = new URL(contentId);
const urlParams = new URLSearchParams(url.search);
const cert = that.shakaPlayer.drmInfo().serverCertificate;
let id = urlParams.get('contentId');
that.id = id;
return shaka.util.FairPlayUtils.initDataTransform(initData, id, cert);
// let skdUrl = shaka.util.StringUtils.fromBytesAutoDetect(initData);
// licenseUri = skdUrl.replace('skd://', 'https://');
// const cert = that.shakaPlayer.drmInfo().serverCertificate;
// return shaka.util.FairPlayUtils.initDataTransform(initData, licenseUri, cert);
});
this.shakaPlayer.getNetworkingEngine().registerRequestFilter((type, request) => {
if (type != shaka.net.NetworkingEngine.RequestType.LICENSE) {
return;
}
let token = localStorage.getItem('auth');
let testToken = JSON.parse(token);
const originalPayload = new Uint8Array(request.body);
const base64Payload = shaka.util.Uint8ArrayUtils.toBase64(originalPayload);
const params = `{ "spc": "${base64Payload}", "assetId":"${that.id}"}`;
request.body = shaka.util.StringUtils.toUTF8(params);
request.headers['Content-Type'] = 'application/json';
request.headers['Authorization'] = `JWT ${testToken.access_token}`
console.log("request.body", request.body)
});
this.shakaPlayer.getNetworkingEngine().registerResponseFilter((type, response) => {
if (type != shaka.net.NetworkingEngine.RequestType.LICENSE) {
return;
}
console.log("license passed")
let responseText = shaka.util.StringUtils.fromUTF8(response.data);
responseText = responseText.trim();
if (responseText.substr(0, 5) === '<ckc>' &&
responseText.substr(-6) === '</ckc>') {
responseText = responseText.slice(5, -6);
}
response.data = shaka.util.Uint8ArrayUtils.fromBase64(responseText).buffer;
});
this.shakaPlayer.load(this.getProgramUrl(channel, program, restart)).then(() => {
console.log('1', this.shakaPlayer.isTextTrackVisible());
console.log('2', this.shakaPlayer.getTextTracks());
console.log('3', this.shakaPlayer.getTextLanguages());
}).catch((error) => {
console.log(error);
});
Smooth play of fairplay content on safari or some advise what can i do in this case
var ajaxResponse = $.ajaxQueue({
type: "POST",
url: "/Upload/Upload",
enctype: 'multipart/form-data',
contentType: false,
processData: false,
async: true,
beforeSend: function(request) {
request.setRequestHeader("serviceUrl", getToLocalStorage("serviceUrl"));
request.setRequestHeader("token", getToLocalStorage("token"));
connection.on("lastprogress", function (itemId, progresbar) {
$(".progress-bar").each(function (index, element) {
var fileid = $(this).data("fileid");
if (fileid === itemId) {
$(this).width(progresbar + "%");
}
var obj = CancelUploadFileList.find(el => el == object.itemId);
if (obj) {
$(".progress-bar").each(function (index, element) {
var fileid = $(this).data("fileid");
if (fileid === object.itemId) {
$(this).removeClass("progress-bar");
$(this).parent().removeClass("progress-custom");
$(this).html("<div style='font-weight:normal;'>Canceled</div>");
ajaxResponse.abort();
// $(this).innerHTML("Canceled");
}
});
}
});
// var progressBarValue = $(".progress-custom").find("[data-fileid='" + uploadFileCollectionList[i].itemId + "']").val();
// $('.progress-bar').eq(count - 1).width(progresbar + "%");
//if (progresbar == 100) {
// connection.on("uploadcontrol", function (isboolean, itemId) {
// if (isboolean) {
// $('.remove-from-list').each(function (index, element) {
// if ($(this).data("fileid") === itemId) {
// $(this).removeClass("red").removeClass("stop").addClass("green").addClass("check");
// }
// });
// }
// });
//}
}
);
try {
connection.start().catch(err => console.log(err.toString())).then(response => console.log("connected"));//unutma
} catch (e) {
}
},
headers: { 'serviceUrl': getToLocalStorage("serviceUrl"), 'token': getToLocalStorage("token") },
data: formData,
success: function (data) {
if (data.success) {
UploadControl(newItemId, object.overWrite);
}
else {
$(function () {
new PNotify({
//
text: data.message == null ? object.itemName+" file is empty": data.message,
type: "error",
addClass: ".notifybg",
delay: 5000
});
});
}
},
error: function (data) {
var uploadedFile = uploadFileCollectionListData.findIndex(el => el.itemId == newItemId);
uploadFileCollectionListData.splice(uploadedFile, 1);
}
});
while (bytesToRead > 0)
{
int n = stream.Read(buffer, 0, chunkSize);
if (n == 0) break;
if (n != buffer.Length)
Array.Resize(ref buffer, n);
var newToken= _progressHub.Clients.Client().In
uploadCloudItem = UploadCloudItem(token, new MemoryStream(buffer), u);
bytesRead += n;
bytesToRead -= n;
var progress = (int)((float)bytesRead / (float)uploadRequest.itemSize * 100.0);
_progressHub.Clients.All.SendAsync("lastprogress", u.itemId, progress);
Task.Delay(500);
}
How do I send token information to the server side with signalR?
How do I send token information to the server side with signalR?
I'm uploading files with jquery, but the token expires when the file size is large.
how do i send my current token
How do I send token information to the server side with signalR?
If a website needs to display in real time or so graph the up and down graphs of stocks. They will think of programming so that the browser regularly sends requests to get the latest stock prices from the web server -> Pooling mechanism. If the number of browsers simultaneously accessing thousands, the web server will have to work very hard even if only a few stocks change points, but still have to reply and send back all the stocks. . Instead of letting the client ask the server (pooling) continuously blindly. Why not let the server, if there are changes, will report back to the client, and will only send the necessary data for the client to process (notification)
I am using the below code to automate a web page. The web page has an XHR call which is triggered upon submitting the form. By using "onResourceRequest" and "onResponseReceived" I can look into the request body, but the response status code is always null.
PhantomJS version: 2.1.1
var page = require('webpage').create(), testindex = 0, loadInProgress = false;
var config = require('../../config/config.json');
var system = require('system');
console.log('Running Iteration 1 ...');
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 3000, //< Default Max Timout is 3s
start = new Date().getTime(),
condition = false,
interval = setInterval(function() {
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
} else {
if(!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout");
phantom.exit(1);
} else {
// Condition fulfilled (timeout and/or condition is 'true')
console.log("'waitFor()' finished in " + (new Date().getTime() - start) + "ms.");
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval); //< Stop this interval
}
}
}, 250); //< repeat check every 250ms
};
page.onError = function (msg, trace) {
console.log(msg);
trace.forEach(function(item) {
console.log(' ', item.file, ':', item.line);
});
};
page.onConsoleMessage = function(msg, lineNum, sourceId) {
console.log(colors.cyan('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")'));
};
page.onLoadStarted = function() {
loadInProgress = true;
console.log("load started ", page.url);
};
page.onResourceRequested = function(request) {
console.log('Request ' + request.url);
console.log('Request Header :', JSON.stringify(request.headers));
console.log('Request Body :', request.postData);
};
page.onResourceReceived = function(response) {
console.log('Receive ' + response.url, response.status);
if(response.status === null) {
console.log(JSON.stringify(response));
}
};
page.onLoadFinished = function() {
loadInProgress = false;
console.log("load finished ", page.url);
};
var steps = [
function () {
page.open(config.url, function (status) {
if (status !== 'success'){
console.log('Unable to access ', config.url); //This is a HTTPS endpoint
} else {
waitFor(function() {
// Check in the page if a specific element is now visible
return page.evaluate(function() {
return document.getElementById('code').value;
});
}, function() {
console.log("The page dialog should be visible now.");
// phantom.exit();
});
}
});
},
function () {
var isPostMessageSupported = page.evaluate(function() {
if(window.postMessage){
return true;
} else{
return false;
}
});
console.log('POST Message Support : ', isPostMessageSupported);
var guid = page.evaluate(function() {
return document.getElementById('guid').value;
});
console.log('GUID : ', guid);
page.evaluate( function () {
document.getElementById('userid').value = 'myusername';
document.getElementById('pass').value = 'mypassword';
});
},
function () {
page.evaluate(function () {
document.getElementById('myform').submit();
return;
});
},
function () {
page.render('iteration1.png');
},
];
function done(){
console.log('##completed');
}
setInterval(function() {
if (!loadInProgress && typeof steps[testindex] == "function") {
console.log("step " + (testindex + 1));
steps[testindex]();
testindex++;
}
if (typeof steps[testindex] != "function") {
console.log("test complete!");
done();
phantom.exit();
}
}, 50);
The response that I recieve for the XHR call is
{"contentType":null,"headers":[],"id":42,"redirectURL":null,"stage":"end","status":null,"statusText":null,"time":"2018-04-12T04:15:04.402Z","url":"https://example.com/p"}
I have tried all the phantomJS command line arguments
phantomjs --web-security=false --ssl-protocol=tlsv1 --ignore-ssl-errors=true phantomjs/iterations/iteration1.js
I have also tried adding header "Connection:keep-alive". But nothing solves my problem.
I am not sure what could be the problem here.
I'd like to send base64 image as an attachment to a trello card through the API
POST /1/cards/[card id or shortlink]/attachments
There's a file field but it does not specify how should look the data there.
Refs: https://developers.trello.com/advanced-reference/card#post-1-cards-card-id-or-shortlink-attachments
Any idea?
Short answer: Trello's API only works to attach binary data via multipart/form-data. Examples below.
Long answer:
The Trello API to add attachments and images is frustratingly under-documented. They do have a coffeescript Client.js for those of us using Javascript to simplify all the basic operations: https://trello.com/1/client.coffee
Using the vanilla Client.js file I have been able to attach links and text files. While the CURL example shows pulling a binary file in from a hard drive, that doesn't work for those of us completely on a server or client where we don't have permissions to create a file.
From a LOT of trial and error, I've determined all binary data (images, documents, etc.) must be attached using multipart/form-data. Here is a jQuery snippet that will take a URL to an item, get it into memory, and then send it to Trello.
var opts = {'key': 'YOUR TRELLO KEY', 'token': 'YOUR TRELLO TOKEN'};
var xhr = new XMLHttpRequest();
xhr.open('get', params); // params is a URL to a file to grab
xhr.responseType = 'blob'; // Use blob to get the file's mimetype
xhr.onload = function() {
var fileReader = new FileReader();
fileReader.onload = function() {
var filename = (params.split('/').pop().split('#')[0].split('?')[0]) || params || '?'; // Removes # or ? after filename
var file = new File([this.result], filename);
var form = new FormData(); // this is the formdata Trello needs
form.append("file", file);
$.each(['key', 'token'], function(iter, item) {
form.append(item, opts.data[item] || 'ERROR! Missing "' + item + '"');
});
$.extend(opts, {
method: "POST",
data: form,
cache: false,
contentType: false,
processData: false
});
return $.ajax(opts);
};
fileReader.readAsArrayBuffer(xhr.response); // Use filereader on blob to get content
};
xhr.send();
I have submitted a new coffeescript for Trello developer support to consider uploading to replace Client.js. It adds a "Trello.upload(url)" that does this work.
I've also attached here for convenience in JS form.
// Generated by CoffeeScript 1.12.4
(function() {
var opts={"version":1,"apiEndpoint":"https://api.trello.com","authEndpoint":"https://trello.com"};
var deferred, isFunction, isReady, ready, waitUntil, wrapper,
slice = [].slice;
wrapper = function(window, jQuery, opts) {
var $, Trello, apiEndpoint, authEndpoint, authorizeURL, baseURL, collection, fn, fn1, i, intentEndpoint, j, key, len, len1, localStorage, location, parseRestArgs, readStorage, ref, ref1, storagePrefix, token, type, version, writeStorage;
$ = jQuery;
key = opts.key, token = opts.token, apiEndpoint = opts.apiEndpoint, authEndpoint = opts.authEndpoint, intentEndpoint = opts.intentEndpoint, version = opts.version;
baseURL = apiEndpoint + "/" + version + "/";
location = window.location;
Trello = {
version: function() {
return version;
},
key: function() {
return key;
},
setKey: function(newKey) {
key = newKey;
},
token: function() {
return token;
},
setToken: function(newToken) {
token = newToken;
},
rest: function() {
var args, error, method, params, path, ref, success;
method = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
ref = parseRestArgs(args), path = ref[0], params = ref[1], success = ref[2], error = ref[3];
opts = {
url: "" + baseURL + path,
type: method,
data: {},
dataType: "json",
success: success,
error: error
};
if (!$.support.cors) {
opts.dataType = "jsonp";
if (method !== "GET") {
opts.type = "GET";
$.extend(opts.data, {
_method: method
});
}
}
if (key) {
opts.data.key = key;
}
if (token) {
opts.data.token = token;
}
if (params != null) {
$.extend(opts.data, params);
}
if (method === 'UPLOAD' && typeof (params) === "string" && params.length > 5) {
var xhr = new XMLHttpRequest();
xhr.open('get', params);
xhr.responseType = 'blob'; // Use blob to get the mimetype
xhr.onload = function() {
var fileReader = new FileReader();
fileReader.onload = function() {
var filename = (params.split('/').pop().split('#')[0].split('?')[0]) || params || '?'; // Removes # or ? after filename
var file = new File([this.result], filename);
var form = new FormData();
form.append("file", file);
$.each(['key', 'token'], function(iter, item) {
form.append(item, opts.data[item] || 'ERROR! Missing "' + item + '"');
});
$.extend(opts, {
method: "POST",
data: form,
cache: false,
contentType: false,
processData: false
});
return $.ajax(opts);
};
fileReader.readAsArrayBuffer(xhr.response); // Use filereader on blob to get content
};
xhr.send();
} else {
return $.ajax(opts);
}
},
authorized: function() {
return token != null;
},
deauthorize: function() {
token = null;
writeStorage("token", token);
},
authorize: function(userOpts) {
var k, persistToken, ref, regexToken, scope, v;
opts = $.extend(true, {
type: "redirect",
persist: true,
interactive: true,
scope: {
read: true,
write: false,
account: false
},
expiration: "30days"
}, userOpts);
regexToken = /[&#]?token=([0-9a-f]{64})/;
persistToken = function() {
if (opts.persist && (token != null)) {
return writeStorage("token", token);
}
};
if (opts.persist) {
if (token == null) {
token = readStorage("token");
}
}
if (token == null) {
token = (ref = regexToken.exec(location.hash)) != null ? ref[1] : void 0;
}
if (this.authorized()) {
persistToken();
location.hash = location.hash.replace(regexToken, "");
return typeof opts.success === "function" ? opts.success() : void 0;
}
if (!opts.interactive) {
return typeof opts.error === "function" ? opts.error() : void 0;
}
scope = ((function() {
var ref1, results;
ref1 = opts.scope;
results = [];
for (k in ref1) {
v = ref1[k];
if (v) {
results.push(k);
}
}
return results;
})()).join(",");
switch (opts.type) {
case "popup":
(function() {
var authWindow, height, left, origin, receiveMessage, ref1, top, width;
waitUntil("authorized", (function(_this) {
return function(isAuthorized) {
if (isAuthorized) {
persistToken();
return typeof opts.success === "function" ? opts.success() : void 0;
} else {
return typeof opts.error === "function" ? opts.error() : void 0;
}
};
})(this));
width = 420;
height = 470;
left = window.screenX + (window.innerWidth - width) / 2;
top = window.screenY + (window.innerHeight - height) / 2;
origin = (ref1 = /^[a-z]+:\/\/[^\/]*/.exec(location)) != null ? ref1[0] : void 0;
authWindow = window.open(authorizeURL({
return_url: origin,
callback_method: "postMessage",
scope: scope,
expiration: opts.expiration,
name: opts.name
}), "trello", "width=" + width + ",height=" + height + ",left=" + left + ",top=" + top);
receiveMessage = function(event) {
var ref2;
if (event.origin !== authEndpoint || event.source !== authWindow) {
return;
}
if ((ref2 = event.source) != null) {
ref2.close();
}
if ((event.data != null) && /[0-9a-f]{64}/.test(event.data)) {
token = event.data;
} else {
token = null;
}
if (typeof window.removeEventListener === "function") {
window.removeEventListener("message", receiveMessage, false);
}
isReady("authorized", Trello.authorized());
};
return typeof window.addEventListener === "function" ? window.addEventListener("message", receiveMessage, false) : void 0;
})();
break;
default:
window.location = authorizeURL({
redirect_uri: location.href,
callback_method: "fragment",
scope: scope,
expiration: opts.expiration,
name: opts.name
});
}
},
addCard: function(options, next) {
var baseArgs, getCard;
baseArgs = {
mode: 'popup',
source: key || window.location.host
};
getCard = function(callback) {
var height, left, returnUrl, top, width;
returnUrl = function(e) {
var data;
window.removeEventListener('message', returnUrl);
try {
data = JSON.parse(e.data);
if (data.success) {
return callback(null, data.card);
} else {
return callback(new Error(data.error));
}
} catch (error1) {}
};
if (typeof window.addEventListener === "function") {
window.addEventListener('message', returnUrl, false);
}
width = 500;
height = 600;
left = window.screenX + (window.outerWidth - width) / 2;
top = window.screenY + (window.outerHeight - height) / 2;
return window.open(intentEndpoint + "/add-card?" + $.param($.extend(baseArgs, options)), "trello", "width=" + width + ",height=" + height + ",left=" + left + ",top=" + top);
};
if (next != null) {
return getCard(next);
} else if (window.Promise) {
return new Promise(function(resolve, reject) {
return getCard(function(err, card) {
if (err) {
return reject(err);
} else {
return resolve(card);
}
});
});
} else {
return getCard(function() {});
}
}
};
ref = ["GET", "PUT", "POST", "DELETE", "UPLOAD"];
fn = function(type) {
return Trello[type.toLowerCase()] = function() {
return this.rest.apply(this, [type].concat(slice.call(arguments)));
};
};
for (i = 0, len = ref.length; i < len; i++) {
type = ref[i];
fn(type);
}
Trello.del = Trello["delete"];
ref1 = ["actions", "cards", "checklists", "boards", "lists", "members", "organizations", "lists"];
fn1 = function(collection) {
return Trello[collection] = {
get: function(id, params, success, error) {
return Trello.get(collection + "/" + id, params, success, error);
}
};
};
for (j = 0, len1 = ref1.length; j < len1; j++) {
collection = ref1[j];
fn1(collection);
}
window.Trello = Trello;
authorizeURL = function(args) {
var baseArgs;
baseArgs = {
response_type: "token",
key: key
};
return authEndpoint + "/" + version + "/authorize?" + $.param($.extend(baseArgs, args));
};
parseRestArgs = function(arg) {
var error, params, path, success;
path = arg[0], params = arg[1], success = arg[2], error = arg[3];
if (isFunction(params)) {
error = success;
success = params;
params = {};
}
path = path.replace(/^\/*/, "");
return [path, params, success, error];
};
localStorage = window.localStorage;
if (localStorage != null) {
storagePrefix = "trello_";
readStorage = function(key) {
return localStorage[storagePrefix + key];
};
writeStorage = function(key, value) {
if (value === null) {
return delete localStorage[storagePrefix + key];
} else {
return localStorage[storagePrefix + key] = value;
}
};
} else {
readStorage = writeStorage = function() {};
}
};
deferred = {};
ready = {};
waitUntil = function(name, fx) {
if (ready[name] != null) {
return fx(ready[name]);
} else {
return (deferred[name] != null ? deferred[name] : deferred[name] = []).push(fx);
}
};
isReady = function(name, value) {
var fx, fxs, i, len;
ready[name] = value;
if (deferred[name]) {
fxs = deferred[name];
delete deferred[name];
for (i = 0, len = fxs.length; i < len; i++) {
fx = fxs[i];
fx(value);
}
}
};
isFunction = function(val) {
return typeof val === "function";
};
wrapper(window, jQuery, opts);
}).call(this);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>