Firefox SDK monitoring http response - firefox-addon-sdk

This is mostly in reference to Firefox add-on SDK: Get http response headers. I am trying to log responses to http requests, but so far I am having no luck debugging this. Would really appreciate some advice... been banging my head on this for hours and gotten nowhere.
This is the main.js for my little extension:
var {Cc, Ci} = require("chrome");
var httpRequestObserver =
{
init: function() {
var observerService = Cc["#mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
observerService.addObserver( this, 'http-on-examine-response', false );
observerService.addObserver( this, 'http-on-examine-cached-response', false );
observerService.addObserver( this, 'http-on-examine-merged-response', false );
},
observe: function(subject, topic, data) {
if (topic === 'http-on-examine-response' || topic === 'http-on-examine-cached-response' || topic === 'http-on-examine-merged-response' ) {
subject.QueryInterface(Ci.nsIHttpChannel);
this.onExamineResponse(subject);
}
},
onExamineResponse: function(oHttp) {
try
{
console.log( oHttp.URI.spec );
}
catch(err)
{
console.log(err);
}
}
};
When I execute the firefox add-on sdk, the test browser boots up fine, and if I open Tools > Add-ons > Extensions, I see mine listed there. But when I point the test browser to google.com (or any url) nothing gets logged to the console.
I've compared my main.js to the techniques suggested # https://developer.mozilla.org/en-US/docs/Setting_HTTP_request_headers and everything seems to be congruent. In the end I plan to do something more complicated than just logging things, but I can't even get this basic functionality to work properly!

It seems that you set the observer for requests, not responses (http-on-examine-request).
Use this in the init function:
observerService.addObserver( this, 'http-on-examine-response', false );
observerService.addObserver( this, 'http-on-examine-cached-response', false );
observerService.addObserver( this, 'http-on-examine-merged-response', false );
Similarly, use this in the observe function:
if (topic === 'http-on-examine-response' || topic === 'http-on-examine-cached-response' || topic === 'http-on-examine-merged-response' ) { ... }

Related

Nodemailer. createTestAccount and cypress: generate same email address

I created an E2E to test for signups, using Nodemailer with Ethereal.
When the test runs the first time everything ends smoothly, but when I executed it a second time the test, for some reason, breaks.
While investigating the above issue, I noticed that the createTestAccount returns the same email address (unless cypress is restarted).
Here's the function code for createTestAccount: https://github.com/nodemailer/nodemailer/blob/master/lib/nodemailer.js#L58.
Is createTestAccount using an internal cache?
If yes, is there a way to disable it (besides setting and process.env.ETHEREAL_CACHE to false)?
Based on the current version (6.7.4) of code, it's not possible to disable the cache any other way than setting the env variable ETHEREAL_CACHE to something different than ['true', 'yes', 'y', '1'].
Aka process.env.ETHEREAL_CACHE needs to be false
Keep in mind that this is OS level env variable. Not the ones setup in Cypress.
And the best thing is the great documentation which mentions ETHEREAL_CACHE variable ...
const request = require("request");
async function createEmail (callback) {
request.post({
headers: { "content-type" : "application/json" },
method: "POST",
url: "https://api.nodemailer.com/user",
body: Buffer.from(
JSON.stringify({
requestor: "nodemailer",
version: "6.7.8"
})
)
}, (err, res, body) => {
if(err)
return callback("Failed to handle request!");
const data = JSON.parse(body) || null;
if(typeof(data) !== "object" || typeof(data.status) !== "string")
return callback("Failed to resolve data");
delete data.status;
return callback(false, data);
});
};
createEmail((err, account) => {
if(err)
return console.log(err);
console.log(account);
});

Service workers "sync" operation is working while its offline?

I have a PWA project where I send the data to server. During this process, if the user is offline then the data is stored in indexedDb and a sync tag is registered. So, then when the user comes online that data can sent to the server.
But In my case the sync event gets executed immediately when the we register a sync event tag, which means the data is tried to be sent to server while its offline, which is not going to work.
I think the sync event supposed to fire while its online only, what could be issue here ?
The service worker's sync event works accordingly when I tried to enable and disable the offline option of chrome devtools, and also works correctly in my android phone.
This is how I register my sync tag
function onFailure() {
var form = document.querySelector("form");
//Register the sync on post form error
if ('serviceWorker' in navigator && 'SyncManager' in window) {
navigator.serviceWorker.ready
.then(function (sw) {
var post = {
datetime1: form.datetime1.value,
datetime: form.datetime.value,
name: form.name.value,
image: form.url.value,
message: form.comment.value
};
writeData('sync-comments', post)
.then(function () {
return sw.sync.register('sync-new-comment');
})
.then(function () {
console.log("[Sync tag registered]");
})
.catch(function (err) {
console.log(err);
});
});
}
}
And this is how the sync event is called
self.addEventListener('sync', function (event) {
console.log("[Service worker] Sync new comment", event);
if (event.tag === 'sync-new-comment') {
event.waitUntil(
readAllData('sync-comments')
.then(function (data) {
setTimeout(() => {
data.forEach(async (dt) => {
const url = "/api/post_data/post_new_comment";
const parameters = {
method: 'POST',
headers: {
'Content-Type': "application/json",
'Accept': 'application/json'
},
body: JSON.stringify({
datetime: dt.datetime,
name: dt.name,
url: dt.image,
comment: dt.message,
datetime1: dt.datetime1,
})
};
fetch(url, parameters)
.then((res) => {
return res.json();
})
.then(response => {
if (response && response.datetimeid) deleteItemFromData('sync-comments', response.datetimeid);
}).catch((error) => {
console.log('[error post message]', error.message);
})
})
}, 5000);
})
);
}
});
you mention
The service worker's sync event works accordingly when I tried to enable and disable the offline option of chrome devtools, and also works correctly in my android phone.
So I'm not sure which case is the one failing.
You are right that the sync will be triggered when the browser thinks the user is online, if the browser detects that the user is online at the time of the sync registration it will trigger the sync:
In true extensible web style, this is a low level feature that gives you the freedom to do what you need. You ask for an event to be fired when the user has connectivity, which is immediate if the user already has connectivity. Then, you listen for that event and do whatever you need to do.
Also, from the workbox documentation
Browsers that support the BackgroundSync API will automatically replay failed requests on your behalf at an interval managed by the browser, likely using exponential backoff between replay attempts.

How to use botkit with facebook and wit.ai

I am a novice in chatbot development and I would like some help.
While it seems quite simple to connect botkit with facebook messenger and wit.ai in orger to use NLP. I haven't managed to do so. My initial goal is to have a simple conversation like hello-hello but using wit.ai as middleware.
Below I attach the code. What it should do is receive a "hello" message, pass it to wit.ai and then respond "I heard hello!" as a reply (without using wit at this stage). Instead I just receive
debug: RECEIVED MESSAGE
debug: CUSTOM FIND CONVO XXXXXXXXXXXXXX XXXXXXXXXXXXXX
debug: No handler for message_received
after every message I send to facebook messenger bot. In wit it seems like I am getting the messages since I receive messages in my inbox to update the intents.
If there is any code much simpler than the one below I would be very happy to have it so that I can start with something much simpler :).
Thanks
<pre><code>
if (!process.env.page_token) {
console.log('Error: Specify page_token in environment');
process.exit(1);
}
if (!process.env.page_token) {
console.log('Error: Specify page_token in environment');
process.exit(1);
}
if (!process.env.verify_token) {
console.log('Error: Specify verify_token in environment');
process.exit(1);
}
if (!process.env.app_secret) {
console.log('Error: Specify app_secret in environment');
process.exit(1);
}
var Botkit = require('./lib/Botkit.js');
var wit = require('./node_modules/botkit-middleware-witai')({
token: process.env.wit,
minConfidence: 0.6,
logLevel: 'debug'
});
var os = require('os');
var commandLineArgs = require('command-line-args');
var localtunnel = require('localtunnel');
const ops = commandLineArgs([
{name: 'lt', alias: 'l', args: 1, description: 'Use localtunnel.me to make your bot available on the web.',
type: Boolean, defaultValue: false},
{name: 'ltsubdomain', alias: 's', args: 1,
description: 'Custom subdomain for the localtunnel.me URL. This option can only be used together with --lt.',
type: String, defaultValue: null},
]);
if(ops.lt === false && ops.ltsubdomain !== null) {
console.log("error: --ltsubdomain can only be used together with --lt.");
process.exit();
}
var controller = Botkit.facebookbot({
debug: true,
log: true,
access_token: process.env.page_token,
verify_token: process.env.verify_token,
app_secret: process.env.app_secret,
validate_requests: true, // Refuse any requests that don't come from FB on your receive webhook, must provide FB_APP_SECRET in environment variables
});
var bot = controller.spawn({
});
controller.setupWebserver(process.env.port || 3000, function(err, webserver) {
controller.createWebhookEndpoints(webserver, bot, function() {
console.log('ONLINE!');
if(ops.lt) {
var tunnel = localtunnel(process.env.port || 3000, {subdomain: ops.ltsubdomain}, function(err, tunnel) {
if (err) {
console.log(err);
process.exit();
}
console.log("Your bot is available on the web at the following URL: " + tunnel.url + '/facebook/receive');
});
tunnel.on('close', function() {
console.log("Your bot is no longer available on the web at the localtunnnel.me URL.");
process.exit();
});
}
});
});
controller.middleware.receive.use(wit.receive);
controller.hears(['hello'], 'direct_message', wit.hears, function(bot, message) {
bot.reply(message, 'I heard hello!');
});
function formatUptime(uptime) {
var unit = 'second';
if (uptime > 60) {
uptime = uptime / 60;
unit = 'minute';
}
if (uptime > 60) {
uptime = uptime / 60;
unit = 'hour';
}
if (uptime != 1) {
unit = unit + 's';
}
uptime = uptime + ' ' + unit;
return uptime;
}
Make sure you have a few conversations in Wit.ai beforehand so for example hello there and highlight the hello in that statement as something like, greetings.
Now i'm not sure what your intents are called in wit.ai but in your statement controller.hears(['hello'] you're actually listening to the wit.ai intents. So in the example i mentioned above, we'd be using hears(['greetings']) since that's the intent in wit.ai.
Also, instead of using direct_message use message_received this is what it should look like:
controller.hears(['hello'], 'message_received', wit.hears, function(bot, message) {
bot.reply(message, 'I heard hello!');
});
If you're struggling tracking down the problem you can stick a console statement in your controller so something like console.log("Wit.ai detected entities", message.entities); and see what you get back from that.
Let me know if you're still having any issues :)

Getting and "Error, wrong validation token" when trying to create a Facebook Chatbot

I'm trying to create a Facebook chatbot with NodeJS, Express, and a Heroku server.
I created my webhook on heroku and had it verified and saved by facebook. I then started adding code that would reply to the incoming messages and I can't seem to get it connected. It keeps saying "Error, wrong validation token" when I try to load my webhook in my browser. And when I try to send my bot a message I get no response. Even though I already had it verified and didn't change the code.
Here is my code:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
var port = process.env.PORT || 3000;
// body parser middleware
app.use(bodyParser.urlencoded({ extended: true }));
// test route
//app.get('/', function (req, res) { res.status(200).send('Hello world!') });
app.get('/', function (req, res) {
if (req.query['hub.verify_token'] === '8FKU9XWeSjnZN4ae') {
res.send(req.query['hub.challenge']);
}
res.send('Error, wrong validation token');
})
app.post('/', function (req, res) {
messaging_events = req.body.entry[0].messaging;
for (i = 0; i < messaging_events.length; i++) {
event = req.body.entry[0].messaging[i];
sender = event.sender.id;
if (event.message && event.message.text) {
text = event.message.text;
sendTextMessage(sender, "Text received, echo: "+ text.substring(0, 200));
}
}
res.sendStatus(200);
});
// error handler
app.use(function (err, req, res, next) {
console.error(err.stack);
res.status(400).send(err.message);
});
app.listen(port, function () {
console.log('Listening on port ' + port);
});
var token = <myToken>;
function sendTextMessage(sender, text) {
messageData = {
text:text
}
request({
url: 'https://graph.facebook.com/v2.6/me/messages',
qs: {access_token:token},
method: 'POST',
json: {
recipient: {id:sender},
message: messageData,
}
}, function(error, response, body) {
if (error) {
console.log('Error sending message: ', error);
} else if (response.body.error) {
console.log('Error: ', response.body.error);
}
});
}
So I'm confused as to why nothing is happening and why I'm getting that error. I feel like I'm missing a whole step. I am following this tutorial by the way: https://developers.facebook.com/docs/messenger-platform/quickstart
Any help is appreciated. Thanks!
Edit: Here are my heroku logs
Do not post your full access tokens here!
Have you tested the output of the challenge? Since it's just a GET and you know all values you can try it yourself: your-app-domain.com/your-callback-url?hub_mode=subscribe&hub_verify_token=the_token_you_set_in_your_app_config&hub_challenge=ping which sould print 'ping' if everything work fine.
Make sure you add sendStatus(200) to the hub challenge response, too.
You need to subscribe your page to the app first. To do so make a POST request to /your-page-id/subscribed_apps which should return "success". You can make a GET request to the same endpoint afterwards to double check your app is subscribed to your page
You did not mention which events you subscribed to (needs to be message_deliveries, messages, messaging_optins, messaging_postbacks)
Make sure the webhooks tab in your app dashboard now says "complete"
Test again
You are actually using "request" but you are never importing it anywhere. Here's how to fix it:
var request = require("request")
Once you have added that to your index.js or app.js file (basically whatever this file is), make sure you do:
npm install request --save
This should fix it. Unfortunately, Heroku doesn't error out and say that it does not know what "request" is and that's why it was so hard to figure this out in the first place!

Testing Angular $resource with external service

I'm trying to make some basic tests on REST requests I'm doing using Angular $resource.
The service code works just fine.
'use strict';
angular.module('lelylan.services', ['ngResource']).
factory('Device', ['Settings', '$resource', '$http', function(Settings, $resource, $http) {
var token = 'df39d56eaa83cf94ef546cebdfb31241327e62f8712ddc4fad0297e8de746f62';
$http.defaults.headers.common["Authorization"] = 'Bearer ' + token;
var resource = $resource(
'http://localhost:port/devices/:id',
{ port: ':3001', id: '#id' },
{ update: { method: 'PUT' } }
);
return resource;
}]);
I'm using the Device resource inside a directive and it works. The problems comes out
when I start making some tests on the services. Here is a sample test where I mock the
HTTP request using $httpBackend and I make a request to the mocked URL.
Unluckily it does not return anything, although the request is made. I'm sure about this
because if a request to another URL is made, the test suite automatically raises an error.
I've been spending lot of time, but no solutions. Here the test code.
'use strict';
var $httpBackend;
describe('Services', function() {
beforeEach(module('lelylan'));
beforeEach(inject(function($injector) {
var uri = 'http://localhost:3001/devices/50c61ff1d033a9b610000001';
var device = { name: 'Light', updated_at: '2012-12-20T18:40:19Z' };
$httpBackend = $injector.get('$httpBackend');
$httpBackend.whenGET(uri).respond(device)
}));
describe('Device#get', function() {
it('returns a JSON', inject(function(Device) {
device = Device.get({ id: '50c61ff1d033a9b610000001' });
expect(device.name).toEqual('Light');
}));
});
});
As the device is not loaded this is the error.
Expected undefined to equal 'Light'.
Error: Expected undefined to equal 'Light'.
I've tried also using the following solution, but it doesn't get into the function
to check the expectation.
it('returns a JSON', inject(function(Device) {
device = Device.get({ id: '50c61ff1d033a9b610000001' }, function() {
expect(device.name).toEqual('Light');
});
}));
Any suggestion or link to solve this problem is really appreciated.
Thanks a lot.
You were very close, the only thing missing was a call to the $httpBackend.flush();. The working test looks like follows:
it('returns a JSON', inject(function(Device) {
var device = Device.get({ id: '50c61ff1d033a9b610000001' });
$httpBackend.flush();
expect(device.name).toEqual('Light');
}));
and a live test in plunker: http://plnkr.co/edit/Pp0LbLHs0Qxlgqkl948l?p=preview
You might also want to check docs for the $httpBackend mock.
In later versions of angular, I'm using 1.2.0rc1 you also need to call this within a $apply or call $digest on a scope. The resource call isn't made unless you do something like this:
var o, back, scope;
beforeEach(inject(function( $httpBackend, TestAPI,$rootScope) {
o = TestAPI;
back = $httpBackend;
scope = $rootScope.$new();
}));
it('should call the test api service', function() {
back.whenGET('/api/test').respond({});
back.expectGET('/api/test');
scope.$apply( o.test());
back.flush();
});