How can I use the unpkg url in my nodejs project? - node.js

Is it possible to use an unpkg.com url in my nodejs project?
I have a project setup to use nodejs https to get the url and it works but I am not sure how or if its possible yet to use that in my nodejs project like we do with a regular installed npm package.
const https = require('https');
const url = 'https://unpkg.com/#tensorflow-models/speech-commands#0.3.3/dist/speech-commands.min.js';
Then I need to use it here:
async function app() {
https.get(url, (res) => {
const statusCode = res.statusCode;
if (statusCode != 200) console.error(`Error ${statusCode}: ${res.statusMessage} ${url}.`);
else console.log('Success');
});
recognizer = speechCommands.create('BROWSER_FFT');
await recognizer.ensureModelLoaded();
predictWord();
};
The response comes back with success but I ultimately need to use the package via that url. I want to be able to substitute the instance speechCommands with the res from unpkg.com. Is this possible? The reason I am trying this is because when I use the npm package I get a fetch undefined error and since this package is rather new, there isn't an issues section setup in their repo to ask.

Related

How to process JS file returned from Express response.sendFile()

I have an API which uses Node.js + Express on the backend.
For one of the API endpoints, I'd like to use the Express response object method of "sendFile", documented here:
https://expressjs.com/en/api.html#res.sendFile
The API should return a Javascript file through the sendFile method.
What I can't figure out is how to read in the .js file on the front end so that I can use the JavaScript functions defined in the file. The sendFile portion appears to be working -- it's just the use of the file which I can't figure out.
Here's what I'm doing on the backend:
app.get("/api/member", async (req, res) => {
options = {
root: path.join(__dirname, '/static'),
dotfiles: 'deny'
}
res.sendFile("member.js", options, (err) => {
if (err) {
console.log(err)
next(err)
} else {
console.log('Sent file')
}
})
});
This seems to be working fine, as I can navigate to the endpoint on my localhost and it loads the JS file. The file member.js simply contains some javascript function definitions.
But, I can't figure out how to consume/use the file once it arrives to the front end.
Here's what I have currently on the frontend:
async function refreshJS() {
const url = `${baseUrl}/member`;
const response = await fetch(url, { credentials: "include" });
const script = document.createElement("script")
script.type = "text/javascript"
script.src = response.body
document.head.appendChild(script)
eval(script)
}
I've spent a lot of time looking through the console/debugger to find the text associated with the JS functions -- but they're nowhere to be found.
I've tested this general framework by loading JS files locally through the console and it worked, so I think it's wrapped up in a misunderstanding of where the JS functions live in the API response. For example, if I replace the command above of:
script.src = response.body
with
script.src = "member.js"
then everything works fine provided I have the file locally.
The examples that I've reviewed seem to deal exclusively with sending an HTML file which is loaded on the frontend. But, I can't find supporting documentation from the fetch API to understand how to use the JS file contents.

How to determine http vs https in nodejs / nextjs api handler

In order to properly build my urls in my xml sitemaps and rss feeds I want to determine if the webpage is currently served over http or https, so it also works locally in development.
export default function handler(req, res) {
const host = req.headers.host;
const proto = req.connection.encrypted ? "https" : "http";
//construct url for xml sitemaps
}
With above code however also on Vercel it still shows as being served over http. I would expect it to run as https. Is there a better way to figure out http vs https?
As Next.js api routes run behind a proxy which is offloading to http the protocol is http.
By changing the code to the following I was able to first check at what protocol the proxy runs.
const proto = req.headers["x-forwarded-proto"];
However this will break the thing in development where you are not running behind a proxy, or a different way of deploying the solution that might also not involve a proxy. To support both use cases I eventually ended up with the following code.
const proto =
req.headers["x-forwarded-proto"] || req.connection.encrypted
? "https"
: "http";
Whenever the x-forwarded-proto header is not present (undefined) we fall back to req.connection.encrypted to determine if we should serve on http vs https.
Now it works on localhost as well a Vercel deployment.
my solution:
export const getServerSideProps: GetServerSideProps = async (context: any) => {
// Fetch data from external API
const reqUrl = context.req.headers["referer"];
const url = new URL(reqUrl);
console.log('====================================');
console.log(url.protocol); // http
console.log('====================================');
// const res = await fetch(`${origin}/api/projets`)
// const data = await res.json()
// Pass data to the page via props
return { props: { data } }
}

Nodejs Fetch API: unable to verify the first certificate

I'm using the fetch API module in my Philips Hue project and when I make a call to the local ip address (my hub) it produces that error in the title.
const fetch = require('node-fetch');
const gateway = "192.168.0.12";
const username = "username";
let getLights = function(){
fetch(`https://${gateway}/api/${username}/lights`, {
method: 'GET'
}).then((res) => {
return res.json();
}).then((json) => {
console.log(json);
});
}
module.exports = {getLights};
Any SECURE fix this will eventually go onto the public internet for me to access my lights from anywhere sooo?
To skip the SSL tests, you can use this:
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = 0;
It seems like you tried to access it using HTTPS. Most likely on your local network it is going to be HTTP
So by changing https://${gateway}/api/${username}/lights to http://${gateway}/api/${username}/lights should work.
If you're trying to keep it HTTPS then you will have to install a SSL certificate authority onto your network.
These may be useful sources if you're trying to get that done:
https://www.freecodecamp.org/news/how-to-get-https-working-on-your-local-development-environment-in-5-minutes-7af615770eec/
https://letsencrypt.org/docs/certificates-for-localhost/

Use Cordova's Filetransfer plugin with express/blob storage

I am using Typescript and Cordova 4.0.
I have the following sample code:
uploadImages(imageUris: Array<string>): any {
var fileTransfer = new FileTransfer();
for (var i = 0; i < imageUris.length; i++) {
fileTransfer.upload(imageUris[i], encodeURI('http://3187cf3.ngrok.com/test/photos'), (success) => {
alert('success');
}, (err) => {
alert('error');
});
}
}
This corresponds to an express route:
var router = express.Router(),
test = test.controller;
router
.post('/test/photos', bind(test.uploadPhotos, test));
Which corresponds to a controller method:
uploadPhotos(req: express.Request, res: express.Response) {
console.log(req);
}
I can't seem to figure out how to, inside of my controller, grab the "file" or image I'm posting to my server using Filetransfer. It's not on req.body or req.query, and when I look through the entire req I can't seem to locate the file. The app flow is working enough to actually make the POST request to test/photos, I just don't know how to or if I can access the file at that point.
How does Filetransfer work, and how can I access the data I need in my controller so that I can push it to Azure Blob Storage?
It looks like you have everything setup correctly to send the data through to your controller. The issue is that you need to put the file on the request since cordova's filetransfer plugin doesn't do that by default.
You can do that with a popular library multer.
npm install multer --save-dev To install multer and save it to your package.json file.
In your express config file, add something like the following:
var multer = require('multer');
app.use(multer({ dest: path.resolve(config.root, 'public/img/') }))
'public/img/' is the path you would like for your image to be saved.
Now your req will have files on it. To upload a single file, you would use req.files.file. You'll want to use this variable to send your file to azure's blob storage using something like blobSvc.createBlockBlobFromLocalFile(containerName, fileName, filePath)
Since you're using Azure for remote storage, chances are you will want to remove the local file that multer has saved. I'd recommend using fs or rimraf to remove the file stored in public/img/, or whatever you set the path to in your express config. If you are using fs, you'll want to use the .unlink command.

How to track usage on a node.js RESTful service with Google Analytics?

I've written a RESTful node.js service as a backend for http://www.cross-copy.net and would like to not only track usage of the web-client but also other clients (like commandline or Apps) which use the service for inter-device copy/paste. Is it possible to embed the Google Analytics JavaScript API into a node.js application and do server-side tracking?
Since all of the answers are really old, I will mention a new npm package:
https://www.npmjs.com/package/universal-analytics
It's really great and incredible easy to use.
Install universal analytics
npm install universal-analytics --save
In your routes file, require the module. (Replace process.env.GA_ACCOUNT with string like 'UA-12345678-1')
// Init GA client
var ua = require('universal-analytics');
var visitor = ua(process.env.GA_ACCOUNT);
Now inside your endpoint functions, you can track a pageview. (Replace request.url with the current url string like '/api/users/1')
// Track pageview
visitor.pageview(request.url).send();
Read the documentation on UA for more info on this module.
As Brad rightfully sad, there was nothing for Node... So I wrote a nodejs module tailored for this these last few days and just published it on NPM: node-ga
The module is still really new (barely trying it in production on a pet project), so don't hesitate to give your input :)
You won't be able to just drop ga.js into your Node project. It has to be loaded in a browser to function correctly.
I don't believe there is anything out there for Node yet (correct me if I'm wrong!), but you should be able to easily adapt the existing PHP classes for doing logging server-side:
https://developers.google.com/analytics/devguides/collection/other/mobileWebsites
You can see how the URL to request the tracking GIF is constructed within ga.php. Translate ga.php to JS and you're set.
$utmGifLocation = "http://www.google-analytics.com/__utm.gif";
// Construct the gif hit url.
$utmUrl = $utmGifLocation . "?" .
"utmwv=" . VERSION .
"&utmn=" . getRandomNumber() .
"&utmhn=" . urlencode($domainName) .
"&utmr=" . urlencode($documentReferer) .
"&utmp=" . urlencode($documentPath) .
"&utmac=" . $account .
"&utmcc=__utma%3D999.999.999.999.999.1%3B" .
"&utmvid=" . $visitorId .
"&utmip=" . getIP($_SERVER["REMOTE_ADDR"]);
I tried out node-ga, but didn't get event tracking to work. nodealytics did the job.
See Core Reporting API Client Libraries & Sample Code (v3).
There is also the following version: Google APIs Client Library for Node.js (alpha).
I wrote a script to query data with Node.js from Googles Analytics Core Reporting API (v3). The script and a detailed setup description is available here.
Here is the script part:
'use strict';
var googleapi = require('googleapis');
var ApiKeyFile = require('mywebsiteGAapi-6116b1dg49a1.json');
var viewID = 'ga:123456700';
var google = getdefaultObj(googleapi);
var Key = getdefaultObj(ApiKeyFile);
function getdefaultObj(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var jwtClient = new google.default.auth.JWT(Key.default.client_email, null, Key.default.private_key, ['https://www.googleapis.com/auth/analytics.readonly'], null);
jwtClient.authorize(function (err, tokens) {
if (err) {
console.log(err);
return;
}
var analytics = google.default.analytics('v3');
queryData(analytics);
});
function queryData(analytics) {
analytics.data.ga.get({
'auth': jwtClient,
'ids': viewID,
'metrics': 'ga:users,ga:pageviews',
'start-date': 'yesterday',
'end-date': 'today',
}, function (err, response) {
if (err) {
console.log(err);
return;
}
console.log(JSON.stringify(response, null, 4));
});
}

Resources