Chrome extension, how to track each visited page? - google-chrome

I wanted to build a Google Chrome extension that would display domain popularity, the way Alexa domain stats did;
I am able to display any data inside popup.html when user clicks my extension button (to show domain rank, backlinks, etc) but in background I need to track popular urls visited by users.
Using manifest v3, I was able (inside background.js) to detect and trigger code on each url change, but I cannot find a function that would allow the extension to ping my servers in order to tell what url/domain is visited by user.
I assume best way to do this is to make an URL get request in background. How can I do something like that ? Basically I want the extension to send a text message to an url of mine.

As wOxxOm mentioned you can use built in fetch API. As mentioned in this documentation, you can use fetch like this -
fetch(your_url, fetchParams) //fetch returns promise, that resolves to a response object
.then(response => response.json()) //assuming JSON response
.then(data => console.log(data))
.catch(err => console.error(err));
where fetchParam is typically a javascript object that follows the documentation mentioned above. you can add your custom data in the fetchParam's body key. like this
fetchParam = {
method: your_metod,
headers: your_header_object,
body: your_data
};
Hope I understood the question correctly.

Related

How to authenticate a user in es6 while data coming from API?

I have an API which is working fine on Postman and getting a result when I provided the email and password in the header section ,now I have a login form and I want to authenticate the user from that API data result if the user name and password matched with API data then logged in otherwise show error. This type of work I wanted but I am very confused where to start it.and I only want to use es6 functions.
You create a login function that makes an ajax call to your API, probably using the fetch API (or some other ajax library like Axios). Your call returns a promise, with the result from the server, which you then act upon.
const login = (formValues) => {
return fetch('/your/api/url', {
method: 'POST',
body: JSON.stringify(formValues)
})
.then((response) => JSON.parse(response))
.then((data) => {
// do something with the server data
})
.catch((error) => {
// do something with the error
});
};
That's the gist. Your server may require additional request parameters, so review the API for whatever ajax method you choose. Again, there are libraries like Axios that can abstract/simplify/expand the fetch API for you, or you can just use it directly. Biggest thing to remember is that you can't access the return values until you actually have them, so if you are unfamiliar with Promises then you should also study up on them.
Using Fetch
Promise

How to serve static (or dynamic?) HTML files with RESTful API?

Hi I'm studying about RESTful API and making a website running on local to exercise.
I think RESTful is a quite good way. CRUD operations can be identified by HTTP methods and we can handle them with one url.
But most confusing things to me is that, How can we serve HTML files which are needed to request CRUD operations?
For example, If I'm implementing a forum, I need APIs to CRUD posts in forum like
[GET] /forum - see all posts in forum
[POST] /forum - create a new post
[GET] /forum/:id - see the post of id
[PUT] /forum/:id - modify the post of id
[DELETE] /forum/:id - delete the post of id
Think about how we use a forum, we need at least 3 type of HTML pages.
They are,
1. a page to see all posts in forum.
2. a page to see the specific post.
3. a page to type title and contents to create(or modify) a new post.
First and second type of HTML files can be served easily by GET requests above.
But in case of third type HTML files, I need to use extra parameters with above APIs or make a new API such like /forum/createpost to serve such HTML files.
I think, in the point of view of RESTful, I miss something and need to distinguish serving static (or dynamic) HTMLs and handling CRUD requests.
What is the bestpractices to handle this problem?
I also find some questions about this problem, but I couldn't find a clear answer.
I think you are mixing up two separate parts of the application. One is the REST API that provides the endpoints for CRUD operations. The HTML files that send the API requests are not part of the REST API. They are served by a web application that provides the front-end to the user, and makes calls to the REST API in the backend to fetch the information to display. To put it in another way, the web application making the calls is your Presentation layer. The REST API is your Business logic. Presumably, the REST API interacts with a database to write data to and read data from it. That is your Persistence or Storage layer.
You can use HTTP content type negotiation for that. POST/PUT requests (can) contain a Content-Type header declaring the type of content they're sending, and—more importantly—all requests contain an Accept header declaring the kinds of responses it accepts. If the client is accepting text/html responses, serve an HTML page; if they're accepting, say, application/json responses, serve a "RESTful" JSON response. This way your server can respond to different situations with the appropriate content and the same endpoint can serve as API and as HTML handler.
Alternatively, you can distinguish the request by using an extension: /posts.html serves a plain HTML file, while /posts gets served by a REST endpoint. That can easily be done in the web server configuration.
This might or might not be an anwser to your problem, however since you're working in Node + Express, routing might be a way to go (If I understood your question correctly). Below is an example of server implementation of accepted routes with parameters. Note, you can make parameters optional in some cases if needed.
app.get('/', function (req, res) {
res.send('Index')
})
app.get('/forum', function (req, res) {
res.send('Forum Index')
})
app.get('/forum/:id', function (req, res) {
// To access id you do 'req.params.id'
res.send('Forum Index')
})
app.put('/forum/:id', function (req, res) {
res.send('Modify Forum')
})
app.delete('/forum/:id', function (req, res) {
res.send('Delete Forum')
})
Reference : https://expressjs.com/en/guide/routing.html

MEAN.js $http.get() return index html content instead of json file

I'm doing a web app based on original MEAN.js framework. When I want to request local json test file using $http.get() method in my AngularJS file, it returned my index html content.Is it a routing problem? I didnot change the original mean.js routing code(https://github.com/meanjs/mean), just added a $http.get() method in home.client.controller.js file. Can anyone help me with this? Thanks!
That is most likely happening, because you didn't define an endpoint for that particular GET request in your app.
Everytime you make a request to your server (for example a GET request to /my-request) nodejs/express are configured in MEAN.js so that your server will try to find the endpoint for that request, if it does not find any, that request will be handled by this particular code block (specified in /modules/core/server/routes/core.server.routes.js):
// Define application route
app.route('/*').get(core.renderIndex);
Which will basically render the index view.
I'm not sure if you're using a custom module or not, eitherway, if you want that request to be handled in a different way in MEAN.js, you can specify your endpoint in your custom module routes file (or in core.server.controller.js) like so:
// Define application route
app.route('/my-request').get(core.sendMyJSON);
Be careful, because this route must be placed before the one I mentioned earlier, otherwise your request will still be handled the same way and the index view will be rendered and served again.
Then you will have to create the controller that should be called to handle that request:
exports.sendMyJSON = function (req, res) {
// logic to serve the JSON file
};
This way you should be able to get it done with a few adjustments.
Side note:
I'm not entirely sure but I think if you place your JSON file in the public directory of your app you should be able to directly access it without the need for the extra logic.

Chrome dev tools fails to show response even the content returned has header Content-Type:text/html; charset=UTF-8

Why does my Chrome developer tools show
Failed to show response data
in response when the content returned is of type text/html?
What is the alternative to see the returned response in developer tools?
I think this only happens when you have 'Preserve log' checked and you are trying to view the response data of a previous request after you have navigated away.
For example, I viewed the Response to loading this Stack Overflow question. You can see it.
The second time, I reloaded this page but didn't look at the Headers or Response. I navigated to a different website. Now when I look at the response, it shows 'Failed to load response data'.
This is a known issue, that's been around for a while, and debated a lot.
As described by Gideon, this is a known issue with Chrome that has been open for more than 5 years with no apparent interest in fixing it.
Unfortunately, in my case, the window.onunload = function() { debugger; } workaround didn't work either. So far the best workaround I've found is to use Firefox, which does display response data even after a navigation. The Firefox devtools also have a lot of nice features missing in Chrome, such as syntax highlighting the response data if it is html and automatically parsing it if it is JSON.
For the ones who are getting the error while requesting JSON data:
If your are requesting JSON data, the JSON might be too large and that what cause the error to happen.
My solution is to copy the request link to new tab (get request from browser)
copy the data to JSON viewer online where you have auto parsing and work on it there.
As described by Gideon, this is a known issue.
For use window.onunload = function() { debugger; } instead.
But you can add a breakpoint in Source tab, then can solve your problem.
like this:
If you make an AJAX request with fetch, the response isn't shown unless it's read with .text(), .json(), etc.
If you just do:
r = fetch("/some-path");
the response won't be shown in dev tools.
It shows up after you run:
r.then(r => r.text())
"Failed to show response data" can also happen if you are doing crossdomain requests and the remote host is not properly handling the CORS headers. Check your js console for errors.
For the once who receive this error while requesting large JSON data it is, as mentioned by Blauhirn, not a solution to just open the request in new tab if you are using authentication headers and suchlike.
Forturnatly chrome does have other options such as Copy -> Copy as curl.
Running this call from the commandoline through cURL will be a exact replicate of the original call.
I added > ~/result.json to the last part of the commando to save the result to a file.
Otherwise it will be outputted to the console.
For those coming here from Google, and for whom the previous answers do not solve the mystery...
If you use XHR to make a server call, but do not return a response, this error will occur.
Example (from Nodejs/React but could equally be js/php):
App.tsx
const handleClickEvent = () => {
fetch('/routeInAppjs?someVar=someValue&nutherVar=summat_else', {
method: 'GET',
mode: 'same-origin',
credentials: 'include',
headers: {
'content-type': 'application/json',
dataType: 'json',
},
}).then((response) => {
console.log(response)
});
}
App.js
app.route('/getAllPublicDatasheets').get(async function (req, res) {
const { someVar, nutherVar } = req.query;
console.log('Ending here without a return...')
});
Console.log will here report:
Failed to show response data
To fix, add the return response to bottom of your route (server-side):
res.json('Adding this below the console.log in App.js route will solve it.');
I had the same problem and none of the answers worked, finally i noticed i had made a huge mistake and had chosen other as you can see
Now this seems like a dumb mistake but the thing is even after removing and reinstalling chrome the problem had remained (settings are not uninstalled by default when removing chrome) and so it took me a while until I found this and choose All again...!
This happened because my backend doesn't handle OPTIONS method and because I had clicked on other by mistake which caused me to spend a couple days trying answers!
As long as the body of the Response is not consumed within your code (using .json() or .text() for instance), it won't be displayed in the preview tab of Chrome dev tools
Bug still active.
This happens when JS becomes the initiator for new page(200), or redirect(301/302)
1 possible way to fix it - it disable JavaScript on request.
I.e. in puppeteer you can use: page.setJavaScriptEnabled(false) while intercepting request(page.on('request'))
another possibility is that the server does not handle the OPTIONS request.
One workaround is to use Postman with same request url, headers and payload.
It will give response for sure.
For me, the issue happens when the returned JSON file is too large.
If you just want to see the response, you can get it with the help of Postman. See the steps below:
Copy the request with all information(including URL, header, token, etc) from chrome debugger through Chrome Developer Tools->Network Tab->find the request->right click on it->Copy->Copy as cURL.
Open postman, import->Rawtext, paste the content. Postman will recreate the same request. Then run the request you should see the JSON response.
[Import cURL in postmain][1]: https://i.stack.imgur.com/dL9Qo.png
If you want to reduce the size of the API response, maybe you can return fewer fields in the response. For mongoose, you can easily do this by providing a field name list when calling the find() method.
For exmaple, convert the method from:
const users = await User.find().lean();
To:
const users = await User.find({}, '_id username email role timecreated').lean();
In my case, there is field called description, which is a large string. After removing it from the field list, the response size is reduced from 6.6 MB to 404 KB.
Use firefox, it always display the response and give the same tools that chrome does.

How to GET Recent Status Updates on Facebook Page Using Facebook Graph Search API?

Similar to Getting Recent Page feeds? Facebook Graph API / FQL and Getting Facebook Status updates with JSon I would like to do a GET request using Facebook's Graph API, and insert that data into a page. Using the search API, I am able to retrieve information about the page like locale, description, and website, but there is no status update/post update included in the resulting JSON.
How can I retrieve the latest status updates/posts from a given page using Facebook's public Graph API?
It turns out it is possible to do this, but you need to generate an access token (for the page). To do this, you will need to have admin rights to the page in question. So for me, I had to request from that the page make me an admin (point them to the "Manage Admin Roles" dropdown on the page).
Next, you will need to generate an access token. Go here Facebook API Browser, and click on the "GET Access Token" button the right. Select the manage_pages role only.
The final URL should look something like this: https://graph.facebook.com/{page_id}/statuses?access_token=BAACEdE...
Here is the javascript function I used to test my URL (you could also just navigate there on your browser):
function populateFacebookUpdates() {
var pageID = "mycompanypage",
accessToken = "BAACEdE...";
var postsURL = "https://graph.facebook.com/" + pageID + "/statuses?access_token=" + accessToken;
$.ajax({
url: postsURL,
method: 'GET',
dataType: "jsonp",
success: function (data)
{
console.log("Successfully retrieved Facebook data");
console.dir(data);
},
error: function(status) {
console.log("Facebook data could not be retrieved. Failed with a status of " + status);
}
});
}
The data returned in JSON was what I wanted. Also, note that the retrieval would work on any browser/machine/IP (it does expire, however). I would just caution against putting the entire URL inside a client-side javascript file for obvious security reasons...
Status's is a connection and not a field as per the documentation. As far as I know only field information can be retrieved via the search API. If you want statuses you'll have to get the page Id from your search and then query for that pages statuses using the call below.
https://graph.facebook.com/{pageID}/statuses