Why webRequest.onBeforeSendHeaders doesn't provide query string while browser.webNavigation.onBeforeNavigate does? - firefox-addon-webextensions

I am trying to implement a web extension which removes redirect intermediate from links. For example, when you click any link to foreign site from vk.com (a social network), you'll be navigated to https://vk.com/away.php?to=URL_GOES_HERE.
When you listen to onBeforeNavigate events like that:
browser.webNavigation.onBeforeNavigate.addListener(
(details) => {
console.log('before navigate', details);
}, {
url: [
{hostContains: "vk.com"}
]
}
);
you'll get full URL: before navigate Object { url: "https://vk.com/away.php?to=URL_GOES_HERE", timeStamp: 1488807415002, frameId: 0, parentFrameId: -1, tabId: 2 }
But you have no option to replace that navigation action with another URL. You have that ability only for webRequest API:
browser.webRequest.onBeforeSendHeaders.addListener(
(details) => {
console.log('before web request', details)
},
{urls: [
'*://vk.com/away.php'
]},
['blocking', 'requestHeaders']
);
but URL there doesn't contain query parameters: before web request Object { requestId: "1", url: "http://vk.com/away.php", originUrl: "https://vk.com/feed", method: "GET", type: "main_frame", timeStamp: 1488807415092, frameId: 0, parentFrameId: -1, tabId: 2, requestHeaders: Array[6] }
Why is it working so? Is it a bug or what?

Documentation doesn't clealy states that query string is implicitly treated as part of URL path. So asterisk at the end is required. The following code works and removes intermediate request:
browser.webRequest.onBeforeRequest.addListener(
(details) => {
let url = new URL(details.url), param;
switch (url.hostname) {
case 'vk.com':
param = 'to';
break;
default:
param = 'url';
}
let direct = new URLSearchParams(url.search).get(param);
console.log('DIRECT: ' + direct + ' (' + url + ')');
return {redirectUrl: direct}
},
{urls: [
'*://vk.com/away.php?*',
'*://www.google.ru/url?*',
'*://www.google.com/url?*',
]},
['blocking']
);

Related

RSocket error 0x201 (APPLICATION_ERROR): readerIndex(1) + length(102) exceeds writerIndex(8): UnpooledSlicedByteBu

setInterval(() => {
let that = this;
this.socket && this.socket.requestResponse({
data: '' + (++index),
metadata: 'org.mvnsearch.account.AccountService.findById',
}).subscribe({
onComplete(payload) {
let account = JSON.parse(payload.data);
that.setState({
nick: account.nick
})
},
onError: (e) => {
console.log('onError', e)
}
});
}, 2000)
trying to connect to spring rsocket using reactjs. getting an error before subscribe in the javascript code shown below.
**this.socket.requestResponse({
data: '' + (++index),
metadata: 'org.mvnsearch.account.AccountService.findById',
})**
How to resolve the above issue?
If you are using rsocket routing on the backend, it is length prefixed. See https://github.com/rsocket/rsocket-demo/blob/master/src/main/js/app.js#L22-L36
// Create an instance of a client
const client = new RSocketClient({
setup: {
keepAlive: 60000,
lifetime: 180000,
dataMimeType: 'application/json',
metadataMimeType: 'message/x.rsocket.routing.v0',
},
transport: new RSocketWebSocketClient({url: url}),
});
const stream = Flowable.just({
data: '{"join": {"name": "Web"}}',
metadata: String.fromCharCode('chat/web'.length) + 'chat/web',
});
The routing specification allows multiple routes, so the encoding of a single route is unfortunately complicated by this. https://github.com/rsocket/rsocket/blob/master/Extensions/Routing.md

How to use Angular Js ajax with dx-scheduler

I am using dx-scheduler calendar and i'm trying to use crud operations for the meetings. I wonder how can i use functions in DevExpress.data.AspNet.createStore instead of their own api methods - here is an example of their API :
DevExpress.data.AspNet.createStore({
key: "AppointmentId",
loadUrl: url + "/Get",
insertUrl: url + "/Post",
updateUrl: url + "/Put",
deleteUrl: url + "/Delete",
onBeforeSend: function(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
}
}),
I want to achieve this :
DevExpress.data.AspNet.createStore({
key: "AppointmentId",
loadUrl: function(){
$http.get("/getApi").then(function(){
// manipulate the fetched data
})
},
insertUrl: : function(values){
// manipulate the values before post
$http.post("/getApi", values).then(function(){
}),
onBeforeSend: function(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
}
}),
Example.
According to Documentation in this link
loadUrl - the URL used to load data. I assume that you should pass the URL string here for your get api.
if parameters is needed for your get request you can send them using LoadParams Option
loadParams - additional parameters that should be passed to loadUrl.
and handle the result by implementing the onLoaded ..
onLoaded - refer to CustomStore.onLoaded.
$scope.schedulerOptions = {
dataSource: DevExpress.data.AspNet.createStore({
key: "AppointmentId",
// loadUrl: 'https://jsonplaceholder.typicode.com/posts',
loadUrl: "https://jsonplaceholder.typicode.com/posts",
insertUrl: url + "/Post",
updateUrl: url + "/Put",
deleteUrl: url + "/Delete",
onBeforeSend: function(method, ajaxOptions) {
ajaxOptions.xhrFields = { withCredentials: true };
},
onLoaded:function(result){
console.log(result)
var data = result;
for (var i in data) {
data[i].StartDate = '2020-12-20T10:00:00Z';
data[i].EndDate = '2020-12-20T11:00:00Z';
}
return data;
}
}),
// remoteFiltering: true,
dateSerializationFormat: "yyyy-MM-ddTHH:mm:ssZ",
views: ["day", "workWeek", "month"],
currentView: "day",
currentDate: new Date(),
startDayHour: 9,
endDayHour: 19,
height: 600,
textExpr: "title",
startDateExpr: "StartDate",
endDateExpr: "EndDate",
allDayExpr: "AllDay"
};
The result from the get request is printed in the console in the onLoaded function
The data you are using in your example in this json
https://jsonplaceholder.typicode.com/posts
Does not contain EndDate , maybe if you modified it to include Start Date and EndDate with the same dateSerializationFormat it will work, I modified them manually and it worked, I also modified textExpr to display title.
your Example link modified
In order to use your own Ajax request , you can use the following work around, Initialize the schedulerOptions after you do your Ajax call using the result as data resource. Example link
Html :
<div class="dx-viewport demo-container" ng-app="DemoApp" ng-controller="DemoController">
<div dx-scheduler="schedulerOptions" ng-if=dataSet></div>
</div>
JS:
$scope.dataSet;
var loadFromUrl = function () {
$http.get('https://jsonplaceholder.typicode.com/posts')
.then(function(result){
$scope.dataSet = result.data;
for (var i in $scope.dataSet) {
$scope.dataSet[i].startDate = '2020-12-20T10:00:00Z';
$scope.dataSet[i].endDate = '2020-12-20T11:00:00Z';
}
$scope.schedulerOptions = {
dataSource: $scope.dataSet,
dateSerializationFormat: "yyyy-MM-ddTHH:mm:ssZ",
views: ["day", "workWeek", "month"],
currentView: "day",
currentDate: new Date(),
startDayHour: 9,
endDayHour: 19,
height: 600,
textExpr: "title",
startDateExpr: "startDate",
endDateExpr: "endDate",
allDayExpr: "AllDay"
};
})
};
loadFromUrl();

how to get value from response from Microsoft cogntive services

I am making a http request to "Microsoft cogntive services" ; and I am getting a proper answer, but I am failing to get the value out of the response.
Here is my script:
'use strict';
const request = require('request');
// Replace <Subscription Key> with your valid subscription key. const subscriptionKey = 'xyz'; // here my API key
// You must use the same location in your REST call as you used to get your // subscription keys. For example, if you got your subscription keys from // westus, replace "westcentralus" in the URL below with "westus". const uriBase = 'https://westeurope.api.cognitive.microsoft.com/face/v1.0/detect';
const imageUrl =
'https://images.unsplash.com/photo-1534559529872-1a83a6cbc03d?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=56820e7b0db7b8a7f10804cd157f61ef&w=1000&q=80'
// Request parameters. const params = {
'returnFaceId': 'true',
'returnFaceLandmarks': 'false',
'returnFaceAttributes': 'age,gender,headPose,smile,facialHair,glasses,' +
'emotion,hair,makeup,occlusion,accessories,blur,exposure,noise' };
const options = {
uri: uriBase,
qs: params, // json: true, // dies nachtäglich eingefügt ev. löschen
body: '{"url": ' + '"' + imageUrl + '"}',
headers: {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key' : subscriptionKey
} };
request.post(options, (error, response, body) => { if (error) {
console.log('Error: ', error);
return; } let jsonResponse = JSON.stringify(JSON.parse(body), null, ' '); console.log('JSON Response\n'); console.log(jsonResponse); });
and here the response that I get:
[ {
"faceId":"f469c0b3-fbb8-4238-a52a-54fd515a2bca",
"faceRectangle":{
"top":327,
"left":253,
"width":426,
"height":426
},
"faceAttributes":{
"smile":0.005,
"headPose":{
"pitch":0,
"roll":0.7,
"yaw":-4.4
},
"gender":"female",
"age":23,
"facialHair":{
"moustache":0,
"beard":0,
"sideburns":0
},
"glasses":"NoGlasses",
"emotion":{
"anger":0,
"contempt":0,
"disgust":0,
"fear":0,
"happiness":0.005,
"neutral":0.994,
"sadness":0.001,
"surprise":0
},
"blur":{
"blurLevel":"low",
"value":0
},
"exposure":{
"exposureLevel":"goodExposure",
"value":0.64
},
"noise":{
"noiseLevel":"low",
"value":0
},
"makeup":{
"eyeMakeup":true,
"lipMakeup":true
},
"accessories":[
],
"occlusion":{
"foreheadOccluded":false,
"eyeOccluded":false,
"mouthOccluded":false
},
"hair":{
"bald":0.02,
"invisible":false,
"hairColor":[
{
"color":"blond",
"confidence":0.99
},
{
"color":"gray",
"confidence":0.74
},
{
"color":"other",
"confidence":0.35
},
{
"color":"brown",
"confidence":0.31
},
{
"color":"red",
"confidence":0.15
},
{
"color":"black",
"confidence":0.06
}
]
}
} } ]
Now would I would like to do it to get the value for "faceID" or faceAttributes.gender or faceAttributes.age
I have tried that with the following commands, but I always get the following errors.
i.e.
console.log(jsonResponse.faceId);
log-message:
script.js.facedetect_node: undefined
i.e.
console.log(jsonResponse.faceId[0]);
log-message:
uncaught exception: Cannot read property '0' of undefined
i.e.
console.log(jsonResponse.faceAttributes[0]);
i.e.
console.log(jsonResponse.faceAttributes.age[0]);
log-message
TypeError: Cannot read property '0' of undefined
I guess you have already seen that I am quite a newbie - for this reason I would highly appreciate if you have an idea how I can get the mentioned values out of this json.
cu
schroedinger

Loopback many-to-many relation confusion

I tried to define many-to-many relation with my Lead and Tag models in my Loopback application
Lead.json
"relations": {
"tags": {
"type": "hasAndBelongsToMany",
"model": "Tag"
}
}
Tag.json
"relations": {
"leads": {
"type": "hasAndBelongsToMany",
"model": "Lead"
}
}
Now i would like to add a tag to my lead model, my angularService executes this method
this.addTag = function (id, tag) {
if (tag.id) {
return Lead.tags.link({
id: id,
fk: tag.id
}).$promise
} else {
return Lead.tags.create({
id: id
}, tag).$promise
}
};
First call works as expected, this adds new tag to my existing lead.
Lead.tags.create({id: 1}, {name: 'NewTag'}); //leadId = 1, tagId = 0 (new Tag) indeed there is no ID field, it's just for simplicity
Now i would like to add same tag to my new lead.
Lead.tags.link({id: 2, fk: 1}); //leadId = 2, tagId = 1 (existing Tag)
But this time loopback throws error: Duplicate entry for LeadTag.id
Don't know how to add existing tag to new lead. Indeed there is documentation, for example here and there is a method called
assembly.parts.add(part, function(err) {});
But my lead service doesn't have this Lead.tags.add method.
As per source code, Lead.tags.link looks like this
// INTERNAL. Use Lead.tags.link() instead.
"::link::Lead::tags": {
params: {
'fk': '#fk'
},
url: urlBase + "/leads/:id/tags/rel/:fk",
method: "PUT"
},
// INTERNAL. Use Lead.tags.unlink() instead.
"::unlink::Lead::tags": {
params: {
'fk': '#fk'
},
url: urlBase + "/leads/:id/tags/rel/:fk",
method: "DELETE"
}
Any ideas?
Thanks

Angular Resource update method with an array as a parameter

I have been googleing this for a few weeks with no real resolution.
I am sure someone will mark this a duplicate, but I am not sure it really is, maybe I am just being too specific, anyway here goes.
I am using angular in a node-webkit app that I am building. I have an api built in express and I am using MongoDB (#mongolab) with Mongoose for the DB.
I had this working fine as long as all of the data types were simple strings and numbers. but I had to restructure the data to use arrays and complex objects. After restructuring the data I was able to get post API calls to work fine, but I cannot get my PUT calls to work at all.
The data looks like this:
itemRoles was an array, but I thought it was throwing the error I am getting now, so I converted it back to a string.
itemStats is causing the problem. Angular is looking for an object, but itemStats is an array (I think anyway). itemStats used to be a string as well, but its easier to work with in my view if it is an array of objects with key:value pairs, which is why I altered it.
I should note I am new to MongoDB as well, first time using it.
{
"_id": {
"$oid": "55a10b9c7bb9ac5832d88bd8"
},
"itemRoles": "healer,dps",
"itemRating": 192,
"itemName": "Advanced Resolve Armoring 37",
"itemClass": "consular",
"itemLevel": 69,
"itemStats": [
{
"name": "Endurance",
"value": 104,
"_id": {
"$oid": "55a10b9c7bb9ac5832d88bda"
}
},
{
"name": "Willpower",
"value": 124,
"_id": {
"$oid": "55a10b9c7bb9ac5832d88bd9"
}
}
],
"__v": 0
}
The Mongoose Schema looks like this:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//var stats = new Schema({
//name: String,
//value: Number
//});
var armoringSchema = new Schema({
itemType: String,
itemClass: String,
itemRoles: String,
itemLevel: Number,
itemName: String,
itemRating: Number,
itemStats: [{ name:String, value:Number}]
});
module.exports = mongoose.model('Armor', armoringSchema);
Express API Route:
/ on routes that end in /armors/:id
// ----------------------------------------------------
router.route('/armors/:id')
// get method omitted
// update the armoring with specified id (accessed at PUT http://localhost:8080/api/armors/:id)
.put(function(req, res) {
// use our armor model to find the armor we want
Armoring.findById({_id: req.params.id}, function(err, armor) {
if (err) {
return res.send(err);
}
for(prop in req.body) {
armor[prop] = req.body[prop];
}
// save the armor
armor.save(function(err) {
if (err) {
return res.send(err);
}
res.json({success:true, message: 'Armor updated!' });
});
});
})
Resource Factory:
swtorGear.factory('armoringFactory', ['$resource', function ($resource) {
return $resource('http://localhost:8080/api/armors/:id', {}, {
update: { method: 'PUT', params: {id: '#_id'}},
delete: { method: 'DELETE', headers: {'Content-type': 'application/json'}, params: {id: '#_id'}}
});
}]);
Route for editing:
.when('/edit/armor/id/:id', {
templateUrl: 'views/modelViews/newArmor.html',
controller: 'editArmorCtrl',
resolve: {
armoring: ['$route', 'armoringFactory', function($route, armoringFactory){
return armoringFactory.get({ id: $route.current.params.id}).$promise;
}]
}
})
Contoller (just the save method, the first part of the controller populates the form with existing data):
$scope.save = function(id) {
$scope.armor.itemStats = [
$scope.armor.stats1,
$scope.armor.stats2
];
$scope.armor.itemRoles = '';
if($scope.armor.role.tank) {
$scope.armor.itemRoles += 'tank';
}
if($scope.armor.role.healer) {
if($scope.armor.itemRoles != '') {
$scope.armor.itemRoles += ',healer';
} else {
$scope.armor.itemRoles += 'healer';
}
}
if($scope.armor.role.dps) {
if($scope.armor.itemRoles != '') {
$scope.armor.itemRoles += ',dps';
} else {
$scope.armor.itemRoles += 'dps';
}
}
console.log($scope.armor);
$scope.armor.$update(id)
.then(function(resp) {
if(resp.success) {
var message = resp.message;
Flash.create('success', message, 'item-success');
$scope.armors = armoringFactory.query();
} else {
var message = resp.message;
Flash.create('success', message, 'item-success');
}
});
}
Formatted data being sent via PUT method (from console.log($scope.armor) ):
Error on save:
I haven't seen nesting schemas in the way that you're doing it. Here's something to try (hard to say if this is it for sure, there's a lot going on):
var armoringSchema = new Schema({
itemType: String,
itemClass: String,
itemRoles: String,
itemLevel: Number,
itemName: String,
itemRating: Number,
itemStats: [{
name: String,
value: Number
}]
});
Also we need to pass in an object to $update instead of just a number. Change $scope.armor.$update(id) to $scope.armor.$update({id: id}).

Resources