Chrome extension declarativeNetRequest: get notified on request blocked - google-chrome-extension

The new manifest version 3 of Chrome extension API offers a new function setExtensionActionOptions which allows a typical content blocker to display the number of blocked HTTP requests for a particular tab. The question is: when to call this API? How do I get notified that a request was just blocked and I need to call it with "increment: 1"? I'm looking for the event "onRequestBlocked" or some workaround.
The alarm API is no good because it fires once per minute. Ideally, I'd like to have this number updated in real time, as it is possible with the old MV2.
Another potential solution is to keep the service worker always running which kind of defeats the fruit of moving to MV3 at all.

There's no way to get notification outside of debugging in unpacked mode via onRuleMatchedDebug event.
You can enable automatic display of the number of the blocked requests on the icon badge.
For example, do it when the extension is installed/updated:
chrome.runtime.onInstalled.addListener(() => {
chrome.declarativeNetRequest.setExtensionActionOptions({
displayActionCountAsBadgeText: true,
});
});
You can also provide an explicit increment using tabUpdate property at any time you want:
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
if (msg.type === 'block') {
chrome.declarativeNetRequest.setExtensionActionOptions({
tabUpdate: {
tabId: sender.tab.id,
increment: msg.count, // Negative values will decrement the count
},
});
}
});

For future seekers: I've been able to find the following solution
chrome.webRequest.onErrorOccurred.addListener(
(details) => {
chrome.declarativeNetRequest.setExtensionActionOptions({
tabUpdate: {
tabId: details.tabId,
increment: 0
}
});
},
{
urls: ["<all_urls>"]
}
);
Yes, this also counts requests that are blocked by other extensions, but in practice I believe this is not so much of a problem. Another thing that's hard for me to explain, is this increment: 0 parameter. For some reason, the action count is actually incremented by increment + 1, not increment when the tabUpdate argument is provided. So, bizarre enough but works for me quite well this far.

Related

Is there a way to intercept multiple requests linked by an "OR" conditional operator?

I am a beginner with cypress. I've been looking for a way to intercept API calls to at least one of multiple URLs.
Let's say a button is clicked and something like this code is executed to check if a list of requests were called :
cy.get('#request1').should('have.been.called').log(`Request was made to 'REQUEST1_URL'`)
OR
cy.get('#request2').should('have.been.called').log(`Request was made to ''REQUEST2_URL'`)
I want to check if a request was sent to one url or the other, or both.
Has anyone encountered this problem before ? Any contribution is appreciated.
Thanks.
The URL you use in the intercept should be general enough to catch both calls.
For example if the calls have /api/ in common, this catches both
cy.intercept('**/api/*') // note wildcards in the URL
.as('apiRequest')
cy.visit('/')
cy.wait('#apiRequest')
If you have more paths in the url than you need to catch, for example /api/dogs/ /api/cats/ and /api/pigs/, then use a function to weed out the ones you want
cy.intercept('**/api/*', (req) => {
if (req.url.includes('dogs') || req.url.includes('cats') { // no pigs
req.alias = 'dogsOrCats' // set alias
}
})
cy.visit('/')
cy.wait('#dogsOrCats')
Catching 0, 1, or 2 URLs
This is a bit tricky, if the number of calls isn't known then you have to know within what time frame they would be made.
To catch requests which you are fired fairly quickly by the app
let count = 0;
cy.intercept('**/api/*', (req) => {
count = count +1;
})
cy.visit('/')
cy.wait(3000) // wait to see if calls are fired
cy.then(() => {
cy.wrap(count).should('be.gt', 0) // 0 calls fails, 1 or 2 passes
})

how to use/implement a custom nodejs Circuit Breaker based on the number of requests?

I'm trying to figure out what is the best wait to implement a circuit breaker based of the number of requests been served in a Typescript/express application instead of fails percentage.
Since the application is meant to be executed by large number of users and under a heavy load, I'm trying to customize the response code in order to trigger a horizontal scaling event with k8s/istio.
The first thing I want to start with is to get is the number of requests in nodejs eventloop event if there is some async work in progress, because a big part of my request are executed asynchronously using async/await.
BTW:
I have seen these Libs
https://github.com/bennadel/Node-Circuit-Breaker
https://github.com/nodeshift/opossum
Is there any good Idea/path I can start with in order to make this possible ?
I can't tell for sure from your question, but if what you're trying to do is to just keep track of how many requests are in progress and then do something in particular if that number exceeds a particular value, then you can use this middleware:
function requestCntr() {
let inProgress = 0;
const events = ['finish', 'end', 'error', 'close'];
return function(req, res, next) {
function done() {
// request finished, so decrement the inProgress counter
--inProgress;
// unhook all our event handlers so we don't count it more than one
events.forEach(event => res.off(event, done));
}
// increment counter for requests in progress
++inProgress;
const maxRequests = 10;
if (inProgress > maxRequests) {
console.log('more than 10 requests in flight at the same time');
// do whatever you want to here
}
events.forEach(event => res.on(event, done));
next();
}
}
app.use(requestCntr());

Make an event handler seamless?

I have written an event handler under Excel online add-in. It is activated by a button activate, then when a user clicks on another cell or range, the address will be written on a text area myTextArea. The whole thing works.
However, once a new cell is selected, a green loading symbol is shown near the focus; WORKING... is shown on the bottom of Excel; it takes almost 0.5 second.
I am just surprised that it takes time for such a simple action. Does anyone know if it is possible to make this event hander faster? Otherwise, is there any other mean than event handling to make this seamless?
(function() {
"use strict";
Office.initialize = function(reason) {
$(document).ready(function() {
app.initialize();
$('#activate').click(addSelectionChangedEventHandler);
});
}
;
function addSelectionChangedEventHandler() {
Office.context.document.addHandlerAsync(Office.EventType.DocumentSelectionChanged, MyHandler);
}
function MyHandler(eventArgs) {
doStuffWithNewSelection();
}
function doStuffWithNewSelection() {
Excel.run(function(ctx) {
var selectedRange = ctx.workbook.getSelectedRange();
selectedRange.load(["address"]);
return ctx.sync().then(function() {
write(selectedRange.address)
})
}).then(function() {
console.log("done");
}).catch(function(error) {
...
});
}
function write(message) {
document.getElementById("myTextarea").value = message;
}
})();
What you're seeing is network lag. The selection changed event -- once registered -- originates on the server, and triggers the code if Office.js that fires your event handler. Your event handler, in turn, creates a local request for getting the selection Range object and its address, sends it over to the server as part of ctx.sync(), and then waits to hear back from the server before firing the .then.
There's not anything you can do to optimize this flow -- you will pay a pretty high per-transaction cost on Excel Online, and event handlers only add one extra step to that cost. On the other hand, the good news is that the Excel.run/ctx-based model does allow you to batch multiple requests into one, drastically reducing the number of roundtrips that would otherwise be required. That is, fetching the values of 10 different ranges is almost identical in speed to fetching just one; whereas it would be 10 times more expensive if each call were made individually.
Hope this helps!
~ Michael Zlatkovsky, developer on Office Extensibility team, MSFT

Request rate is large

Im using Azure documentdb and accessing it through my node.js on express server, when I query in loop, low volume of few hundred there is no issue.
But when query in loop slightly large volume, say around thousand plus
I get partial results (inconsistent, every time I run result values are not same. May be because of asynchronous nature of Node.js)
after few results it crashes with this error
body: '{"code":"429","message":"Message: {\"Errors\":[\"Request rate is large\"]}\r\nActivityId: 1fecee65-0bb7-4991-a984-292c0d06693d, Request URI: /apps/cce94097-e5b2-42ab-9232-6abd12f53528/services/70926718-b021-45ee-ba2f-46c4669d952e/partitions/dd46d670-ab6f-4dca-bbbb-937647b03d97/replicas/130845018837894542p"}' }
Meaning DocumentDb fail to handle 1000+ request per second?
All together giving me a bad impression on NoSQL techniques.. is it short coming of DocumentDB?
As Gaurav suggests, you may be able to avoid the problem by bumping up the pricing tier, but even if you go to the highest tier, you should be able to handle 429 errors. When you get a 429 error, the response will include a 'x-ms-retry-after-ms' header. This will contain a number representing the number of milliseconds that you should wait before retrying the request that caused the error.
I wrote logic to handle this in my documentdb-utils node.js package. You can either try to use documentdb-utils or you can duplicate it yourself. Here is a snipit example.
createDocument = function() {
client.createDocument(colLink, document, function(err, response, header) {
if (err != null) {
if (err.code === 429) {
var retryAfterHeader = header['x-ms-retry-after-ms'] || 1;
var retryAfter = Number(retryAfterHeader);
return setTimeout(toRetryIf429, retryAfter);
} else {
throw new Error(JSON.stringify(err));
}
} else {
log('document saved successfully');
}
});
};
Note, in the above example document is within the scope of createDocument. This makes the retry logic a bit simpler, but if you don't like using widely scoped variables, then you can pass document in to createDocument and then pass it into a lambda function in the setTimeout call.

Chrome extension delay condition

I have created a chrome extension which does something after its button is clicked.
However I dont want it be abused so I need the its code to be executed after some time.
How can I surround this code with a timeout in order to achieve this?
Thank you for reading me!
chrome.tabs.getSelected(null,function(tab) {
var Mp=tab.url.substring(0,23);
if(Mp=='https://www.example.com')
{
onWindowLoad();
chrome.extension.onMessage.addListener(function(request, sender) {
if (request.action == "getSource")
{
...Working here
}
});
}
else
{
message.innerHTML='<span style="color: #f00">This is not a valid page</span>';
}
});
function onWindowLoad()
{
var message = document.querySelector('#message');
chrome.tabs.executeScript(null, {file: "getPagesSource.js"});
}
I had to make a compromise so just after the getSelected I added the following line:
chrome.browserAction.disable(tab.Id);
It disables the action button thus it cant be clicked while the script sends the data to the server, as with this extension I grab the tab url in order to store it in my database.
After the ajax response and adding the following
if(xhr.readyState==4)
{
message.innerHTML=xhr.responseText;
chrome.browserAction.enable(tab.Id); /////<---THAT LINE
}
the button gets ready again to be clicked.
I couldnt find the way to add a specific delay in seconds, this way seems stupid but its working, as the response's delay from my server is enough for switching the 2 states of the action button.
With this, however another problem came up, which Ill write in different question.

Resources