Service worker for web traffic analysis - service-worker

I have developed an application to analyse the network traffic while playing a youtube video. It uses chrome.webRequest and I calculate the traffic using onHeadersReceived event.
I want to do the same using service workers so that the application becomes browser independent. I fetch event of service worker, but it does not work.
Any suggestions how I can proceed?

Well, the broad idea is to listen to the fetch event, extract the information you need and allow the request to reach the network. You have a working demo in the Service Worker Cookbook: https://serviceworke.rs/api-analytics.html but the relevant code is here (in the cookbook you have the annotated source as well):
self.onfetch = function(event) {
event.respondWith(
// Log the request…
log(event.request)
// …and then actually perform it.
.then(fetch)
);
};
// Post basic information of the request to a backend for historical purposes.
function log(request) {
var returnRequest = function() {
return request;
};
var data = {
method: request.method,
url: request.url
};
return fetch(LOG_ENDPOINT, {
method: 'POST',
body: JSON.stringify(data),
headers: { 'content-type': 'application/json' }
})
.then(returnRequest, returnRequest);
}

Related

In electron how to send custom header and value for every request?

I use electronjs for building a cross platform desktop application. I would like to send a custom header with a value for every request from electron. Initially in loadURL(), i could use extraHeaders to set the custom header. How to send it in all subsequent requests?
As recommended by the documentation, you should use session object and the method onBeforeSendHeaders:
const { session } = require('electron')
// Modify the user agent for all requests to the following urls.
const filter = {
urls: ['https://*.github.com/*', '*://electron.github.io']
}
session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
details.requestHeaders['User-Agent'] = 'MyAgent'
callback({ requestHeaders: details.requestHeaders })
})

Disable relayjs garbage collection

Is there a way to disable the relayjs garbage collection (version 5.0.0 or 6.0.0)?
We are still using relayjs classic and it caches all data in a session. This makes loading previous pages fast while fetching new data. In relayjs 5.0.0 they have a dataFrom on the QueryRenderer that can be set to "STORE_THEN_NETWORK" which will try the relay cache store first and fetch from the network, just like rejay classic. Except that the newer versions of relay uses a garbage collection feature to remove data that is not currently used. This makes almost all pages fetch data from the network.
I managed to get this working. The key thing here is the environment.retain(operation.root); which will retain the objects in the cache.
Then in the QueryRenderer use the fetchPolicy="store-and-network".
See my full Relay Environment file below.
import {Environment, Network, RecordSource, Store} from 'relay-runtime';
function fetchQuery(operation, variables) {
const environment = RelayEnvironment.getInstance();
environment.retain(operation.root);
return fetch(process.env.GRAPHQL_ENDPOINT, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
credentials: 'include',
body: JSON.stringify({
query: operation.text,
variables
})
}).then(response => {
return response.json();
});
}
const RelayEnvironment = (function() {
let instance;
function createInstance() {
return new Environment({
network: Network.create(fetchQuery),
store: new Store(new RecordSource())
});
}
return {
getInstance: function() {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
export default RelayEnvironment;
Also got this from the Relay Slack Channel. Haven't tried it yet.
const store = new Store(new RecordSource());
(store as any).holdGC(); // Disable GC on the store.

IBM DataPower - How to handle HTML Response from openurl?

I tried looking for the solution in the forum but I was unable to find something similar to what I'm trying to achieve. I have a gateway script in an MPG which kinda looks like this:
session.INPUT.readAsJSON(function (error, json) {
if (error){
throw error;
} else {
var SAMLResponse = json['SAMLResponse'];
var RelayState = json['RelayState'];
var urlopen = require('urlopen');
var options = {
target: 'https://************.com/e32d32der2tj90g8h4',
method: 'POST',
headers: { 'HEADER_NAME' : 'VALUE'},
contentType: 'application/json',
timeout: 60,
sslClientProfile: 'ClientProfile',
data: {"SAMLResponse": SAMLResponse, "RelayState": RelayState}
};
urlopen.open(options, function(error, response) {
if (error) {
session.output.write("urlopen error: "+JSON.stringify(error));
} else {
var responseStatusCode = response.statusCode;
var responseReasonPhrase = response.reasonPhrase;
response.readAsBuffer(function(error, responseData){
if (error){
throw error;
} else {
session.output.write(responseData);
console.log(responseData);
}
});
}
});
}
});
I'm doing a POST request and the response I get from the urlopen function is an HTML page, how to I display the contents of that page in my browser? I need that to initiate a process flow. am I going in the wrong direction here? what's the best way to POST to a URI and display it's response in DataPower?
with regards to my experience with DataPower, I just started learning, So I might not be familiar with many of the concepts.
Thanks in Advance!
session.INPUT.readAsJSON() would indicate that you are receiving JSON data as the input (from the POST).
Since you are building this in a Multi-Protocol Gateway (MPGW) you need to set the Response type to non-xml if the response is HTML and if there is no backend call being made (other than the url-open()) you also must set the skip-backside=1 variable.
Is the scenario as:
JSON HTTP Request -> [MPGW] -> url-open() -> Backend server --|
HTTP Response <-----------------------------------------|
Or:
JSON HTTP Request -> [MPGW] -> url-open() --| (skip-backside)
HTTP Response <------------------------|
If there is no backend call I would recommend building this in a XML Firewall (XMLFW) service instead and set it to "loopback" and non-xml.
If there is a backend and that is where you are sending your HTML from the url-open() then only MPGW Response type needs to be set to non-xml.
If it is the second option the you can just set the payload and headers in GWS and just call the target (https://************.com/e32d32der2tj90g8h4) as teh MPGW backside connection, no need for the url-open().

Ignore ajax requests in service worker

I have an app with a basic 'shell' of HTML, CSS and JS. The main content of the page is loaded via multiple ajax calls to an API that is at another URL to the one my app is running on. I have set up a service-worker to cache the main 'shell' of the application:
var urlsToCache = [
'/',
'styles/main.css',
'scripts/app.js',
'scripts/apiService.js',
'third_party/handlebars.min.js',
'third_party/handlebars-intl.min.js'
];
and to respond with the cached version when requested. The problem I am having is that the response of my ajax calls are also being cached. I'm pretty sure that I need to add some code to the fetch event of the service-worker that always get them from the network rather than looking in the cache.
Here is my fetch event:
self.addEventListener('fetch', function (event) {
// ignore anything other than GET requests
var request = event.request;
if (request.method !== 'GET') {
event.respondWith(fetch(request));
return;
}
// handle other requests
event.respondWith(
caches.open(CACHE_NAME).then(function (cache) {
return cache.match(event.request).then(function (response) {
return response || fetch(event.request).then(function (response) {
cache.put(event.request, response.clone());
return response;
});
});
})
);
});
I'm not sure how I can ignore the requests to the API. I've tried doing this:
if (request.url.indexOf(myAPIUrl !== -1) {
event.respondWith(fetch(request));
return;
}
but according to the network tab in Chrome Dev Tools, all of these responses are still coming from the service-worker.
You do not have to use event.respondWith(fetch(request)) to handle requests that you want to ignore. If you return without calling event.respondWith browser will fetch the resource for you.
You can do something like:
if (request.method !== 'GET') { return; }
if (request.url.indexOf(myAPIUrl) !== -1) { return; }
\\ handle all other requests
event.respondWith(/* return promise here */);
IOW as long as you can determine synchronously that you don't want to handle the request you can just return from the handler and let the default request processing to take over. Check out this example.

ionic framework bad request when calling web service over 3G

I'm developing iOS app using ionic framework and I have one problem when I try to call web service by using 3G network.
here is my service in UserService:
function getUserStat(user_id){
var request = $http({ method: "get",
url: "http://www.example.com/user.php",
params: {
action: "stat",
user_id:user_id
},
data: {
}
});
return(request.then(handleSuccess, handleError));
}
function handleError( response ) {
// The API response from the server should be returned in a
// nomralized format. However, if the request was not handled by the
// server (or what not handles properly - ex. server error), then we
// may have to normalize it on our end, as best we can.
if (!angular.isObject( response.data ) || !response.data.message) {
return( $q.reject("An unknown error occurred.") );
}
// Otherwise, use expected error message.
return( $q.reject( response.data.message ) );
}
// I transform the successful response, unwrapping the application data
// from the API response payload.
function handleSuccess( response ) {
return( response.data );
}
the getUserStat() function will return json back.
here is my controller
UserService.getUserStat($scope.user_id).then(function(data){
alert("Result: " + JSON.stringify(data));
});
in my control I just show the json.
I build this code to my iPhone and test it over WIFI network, everything work fine. If i update the serverside, UserService.getUserStat in controller will show update. but the problem is when I test it on 3G network, iPhone always show the old json returned from the server (even I change server side data).
any idea to solve this problem?
Thank you
I had a similar problem when I tried to upload a camera photo to my data server.when i tested the app on my local WIFI it worked perfectly but when I tested it outside i noticed it fails to upload the file. eventualy the problem was that since the internet outside is much slower the app moved to another view without finish the upload action.
so for example if your controller looks something like this:
.controller('Ctrl1', function(webService, $scope, $state) {
UserService.getUserStat($scope.user_id).then(function(data){
alert("Result: " + JSON.stringify(data));
});
$state.go('app.posts');
});
it should be like this:
.controller('Ctrl1', function(webService, $scope, $state) {
UserService.getUserStat($scope.user_id).then(function(data){
alert("Result: " + JSON.stringify(data));
})
.finally(function() {
$state.go('app.posts');
});
});

Resources