How can I detect browser details in NestJs/NodeJs - node.js

I am trying to integrate device-detector npm module in my application in order to detect the browser details. For that I am using this module npm i device-detector-js
I have integrated as it is code snippet in my code.
Below is my code:
app.controller.ts
import { Controller, Get, Req } from '#nestjs/common';
import { AppService } from './app.service';
#Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
#Get()
getHello(#Req() req): string {
console.log(req.headers);
return this.appService.getHello();
}
}
app.service.ts
import { Inject, Injectable } from '#nestjs/common';
import DeviceDetector = require("device-detector-js");
#Injectable()
export class AppService {
private readonly deviceDetector = new DeviceDetector();
getHello(): string {
const userAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81(Windows; Intel windows 8_8.1_10_11) Safari/537.36";
const result = this.deviceDetector.parse(userAgent);
console.log(JSON.stringify(result));
return 'Hello World!';
}
}
Output
[Nest] 23300 - 12/04/2022, 1:26:55 pm LOG [RouterExplorer] Mapped {/test, GET} route +2ms
[Nest] 23300 - 12/04/2022, 1:26:55 pm LOG [NestApplication] Nest application successfully started +4ms
{
host: 'localhost:3000',
connection: 'keep-alive',
'cache-control': 'max-age=0',
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="98", "Google
Chrome";v="98"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
dnt: '1',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36'
}
It's working but not giving correct info as I am using Windows but it's showing Macintosh. Why is this happening?

Just pass headers from controller into service, something like this:
// controller
getHello(#Req() req): string {
console.log(req.headers);
return this.appService.getHello(req.headers);
}
// service
getHello(headers: {'user-agent': string }): string {
const userAgent = headers['user-agent'];
const result = this.deviceDetector.parse(userAgent);
console.log(JSON.stringify(result));
return 'Hello World!';
}

Related

Trying to get Twitch user name & check if its valid keeping running into an error Parse the body

I'm trying to parse so I can check if the username is valid or not. Though I have little to no experience working with JSON parasing in NodeJS. I'd appreciate some help on this issue. This has been a struggle moving over to NodeJS and trying to work with APIs and parasing them.
Here's the code and here is the error
userid = body[0]['data']['user']['id'];
^
TypeError: Cannot read properties of undefined (reading 'data')
at Request._callback (C:\Users\Tommy\Desktop\Misc\Node Projects\Discord Twitch Username Check\index.js:141:25)
at Request.self.callback (C:\Users\Tommy\Desktop\Misc\Node Projects\Discord Twitch Username Check\node_modules\request\request.js:185:22)
at Request.emit (node:events:390:28)
at Request.<anonymous> (C:\Users\Tommy\Desktop\Misc\Node Projects\Discord Twitch Username Check\node_modules\request\request.js:1154:10)
at Request.emit (node:events:390:28)
at IncomingMessage.<anonymous> (C:\Users\Tommy\Desktop\Misc\Node Projects\Discord Twitch Username Check\node_modules\request\request.js:1076:12)
at Object.onceWrapper (node:events:509:28)
at IncomingMessage.emit (node:events:402:35)
at endReadableNT (node:internal/streams/readable:1343:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21)
function getUser(username) {
const opts = {
"url": `https://gql.twitch.tv/gql`,
headers: {
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
'sec-ch-ua': '" Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"',
'Accept-Language': 'en-US',
'sec-ch-ua-mobile': '?0',
'Client-Version': '7b9843d8-1916-4c86-aeb3-7850e2896464',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36',
'Content-Type': 'text/plain;charset=UTF-8',
'Client-Session-Id': '51789c1a5bf92c65',
'Client-Id': 'kimne78kx3ncx6brgo4mv6wki5h1ko',
'X-Device-Id': 'xH9DusxeZ5JEV7wvmL8ODHLkDcg08Hgr',
'sec-ch-ua-platform': '"Windows"',
'Accept': '*/*',
'Origin': 'https://www.twitch.tv',
'Sec-Fetch-Site': 'same-site',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Dest': 'empty',
'Referer': 'https://www.twitch.tv/',
},
body: '[{"operationName": "WatchTrackQuery","variables": {"channelLogin": "'+username+'","videoID": null,"hasVideoID": false},"extensions": {"persistedQuery": {"version": 1,"sha256Hash": "38bbbbd9ae2e0150f335e208b05cf09978e542b464a78c2d4952673cd02ea42b"}}}]'
}
request(opts, (err, res, body) => {
body = JSON.parse(body);
userid = body[0]['data']['user']['id'];
if(userid === 0){
return "Invalid Username"
}else{
return userid;
}
});
};

AWS-serverless-express never resolving with promises

can anyone shed light on my issue opened at the aws-serverless-express repo on github? https://github.com/awslabs/aws-serverless-express/issues/276
I am trying to run my previous express.js server using the aws-serverless-express package. When running without any special options I resolve, but the promises in the chain are never respected, meaning I dont execute all things in the event loop.
If I run the serverlessexpress with 'PROMISE' flag, I execute all my promises, but the program never resolves and times out after the maximum time set.
I even started a new project as per the example in that repo, same result.
My main executing file (index.js) when resolving but not respecting my promises
const awsServerlessExpress = require('aws-serverless-express')
const app = require('./app.js')
const server = awsServerlessExpress.createServer(app, null)
exports.handler = (event, context) => {
return awsServerlessExpress.proxy(server, event, context)
}
My main executing file (index.js) when NOT resolving, but respecting my promises
const awsServerlessExpress = require('aws-serverless-express')
const app = require('./app.js')
const server = awsServerlessExpress.createServer(app, null)
exports.handler = (event, context) => {
return awsServerlessExpress.proxy(server, event, context, 'PROMISE')
}
I also tried this:
const awsServerlessExpress = require('aws-serverless-express')
const app = require('./app.js')
const server = awsServerlessExpress.createServer(app, null)
exports.handler = (event, context) => {
return awsServerlessExpress.proxy(server, event, context, 'PROMISE').promise
}
My express server file (app.js)
const express = require('express')
const bodyParser = require('body-parser')
const awsServerlessExpressMiddleware = require('aws-serverless-express/middleware')
const app = express()
const router = express.Router()
router.use(bodyParser.json())
router.use(bodyParser.urlencoded({ extended: true }))
router.use(awsServerlessExpressMiddleware.eventContext())
router.get('/', (req, res) => {
res.render('index', {
apiUrl: req.apiGateway ? `https://${req.apiGateway.event.headers.Host}/${req.apiGateway.event.requestContext.stage}` : 'http://localhost:3000'
})
})
router.get('/users', (req, res) => {
res.json(users)
})
const users = [{
id: 1,
name: 'Joe'
}, {
id: 2,
name: 'Jane'
}]
function myFunc () {
console.log('hey')
}
setTimeout(myFunc, 3000)
app.use('/', router)
module.exports = app
Make sure you are setting context.callbackWaitsForEmptyEventLoop to false
read more about it here https://docs.aws.amazon.com/lambda/latest/dg/nodejs-context.html
The issue was regarding my testing tool:
https://www.npmjs.com/package/run-local-lambda
When I spoke with the AWS Support, they told me to use:
sam local invoke "Test" -e event.json
With a event.json file that includes the following:
{
"httpMethod": "OPTIONS",
"//body": "{\"name\": \"Sam\"}",
"path": "/api/auth",
"resource": "/{proxy+}",
"queryStringParameters": {},
"pathParameters": {
"proxy": "users"
},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, sdch, br",
"Accept-Language": "en-US,en;q=0.8",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-Mobile-Viewer": "false",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Viewer-Country": "US",
"Content-Type": "application/json",
"Host": "xxxxxxxxxx.execute-api.us-east-1.amazonaws.com",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
"Via": "1.1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx_xxxxxxxxxxx_xxxx==",
"X-Forwarded-For": "11.111.111.111, 11.111.111.111",
"X-Forwarded-Port": "111",
"X-Forwarded-Proto": "http",
"x-apigateway-event": "hej"
},
"requestContext": {
"accountId": "111111111111",
"resourceId": "xxxxxx",
"stage": "prod",
"requestId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"identity": {
"cognitoIdentityPoolId": "",
"accountId": "",
"cognitoIdentityId": "",
"caller": "",
"apiKey": "",
"sourceIp": "11.111.111.111",
"cognitoAuthenticationType": "",
"cognitoAuthenticationProvider": "",
"userArn": "",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
"user": ""
},
"resourcePath": "/{proxy+}",
"httpMethod": "GET",
"apiId": "xxxxxxxxxx"
}
}
And a template file to use just for testing that looks like this:
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description:
A test project
Resources:
Test:
Type: AWS::Serverless::Function
Properties:
Runtime: nodejs10.x
Handler: index.handler
Timeout: 10
Environment:
Variables:
NODE_ENV: "test"
DB_NAME: "dbname"
DB_USER: "dbuser"
DB_PASSWORD: "secret"
DB_URL: "dburl"
The code I use looks like this in the handler:
'use strict'
const awsServerlessExpress = require('aws-serverless-express')
const app = require('./main.js')
const server = awsServerlessExpress.createServer(app, null)
exports.handler = (event, context) => {
return awsServerlessExpress.proxy(server, event, context,'PROMISE').promise
}
Then my code executed wonderful with no timeouts ever.

Log4js - Disable logs for http calls

I'm using log4js to log messages. For some reason, the logger automatically logs the http calls, and I can't find a way to disable it. Here is my code:
// Initialize the log4js logger by configurations parameters and appenders.
log4js.configure({
appenders: {
app: {
type: 'file',
filename: 'logs/app.log',
pattern: '-yyyy-MM-dd',
maxLogSize: LOGS_FILES_MAXIMUM_SIZE
},
mq: {
type: '#log4js-node/rabbitmq',
host: LOG_SERVER_HOST_ADDRESS,
port: LOG_SERVER_HOST_PORT,
username: LOG_SERVER_USERNAME,
password: LOG_SERVER_PASSWORD,
routing_key: LOG_SERVER_ROUTING_KEY,
exchange: LOG_SERVER_EXCHANGE_NAME,
mq_type: 'direct',
durable: true
}
},
categories: {
default: { appenders: ['app'], level: LogLevel.ALL },
development: { appenders: ['app'], level: LogLevel.ALL },
production: { appenders: ['app', 'mq'], level: LogLevel.ALL }
}
});
this.log = log4js.getLogger('production');
and in app.js
this.app.use(log4js.connectLogger(log4js.getLogger('production'), { level: 'off' }));
For some reason the logger automatically log messages like this:
[2019-06-19T16:02:16.182] [OFF] development - ::1 - - "POST
/api/log/logMessage HTTP/1.1" 200 2
"http://localhost:3000/?recording-session-id=b983cb82-4812-4c43-87b3-a17e7ed1f6b4&environment=data-center"
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/75.0.3770.90 Safari/537.36"
[2019-06-19T16:02:16.182] [OFF] development - ::1 - - "OPTIONS
/api/stream/getStreamData HTTP/1.1" 204 0
"http://localhost:3000/?recording-session-id=b983cb82-4812-4c43-87b3-a17e7ed1f6b4&environment=data-center"
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/75.0.3770.90 Safari/537.36"
[2019-06-19T16:02:16.189] [OFF] development - ::1 - - "POST
/api/stream/getStreamData HTTP/1.1" 200 999
"http://localhost:3000/?recording-session-id=b983cb82-4812-4c43-87b3-a17e7ed1f6b4&environment=data-center"
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/75.0.3770.90 Safari/537.36"
In my code it had to do with the following lines in app.js:
const logger = require('morgan');
app.use(logger('dev'));
I deleted these lines so as to only use log4js, an not Morgan.

Uncaught (in promise): Error: No provider for GooglePlus

I am trying to use the cordova-plugin-googleplus plugin.
I have read the other posts that say to add the plugin as a provider, and have tried to do that to no avail.
When I try to visit my login page I get this error with stack trace:
Runtime Error
Uncaught (in promise): Error: No provider for GooglePlus! Error: No provider for GooglePlus! at injectionError (http://localhost:8100/build/vendor.js:1590:86) at noProviderError (http://localhost:8100/build/vendor.js:1628:12) at ReflectiveInjector_.throwOrNull (http://localhost:8100/build/vendor.js:3129:19) at ReflectiveInjector.getByKeyDefault (http://localhost:8100/build/vendor.js:3168:25) at ReflectiveInjector.getByKey (http://localhost:8100/build/vendor.js:3100:25) at ReflectiveInjector.get (http://localhost:8100/build/vendor.js:2969:21) at AppModuleInjector.get (ng:///AppModule/module.ngfactory.js:332:145) at AppModuleInjector.getInternal (ng:///AppModule/module.ngfactory.js:615:44) at AppModuleInjector.NgModuleInjector.get (http://localhost:8100/build/vendor.js:3936:44) at LoginPageModuleInjector.NgModuleInjector.get (http://localhost:8100/build/vendor.js:3937:52)
Stacktrace
Error: Uncaught (in promise): Error: No provider for GooglePlus!
Error: No provider for GooglePlus!
at injectionError (http://localhost:8100/build/vendor.js:1590:86)
at noProviderError (http://localhost:8100/build/vendor.js:1628:12)
at ReflectiveInjector_._throwOrNull (http://localhost:8100/build/vendor.js:3129:19)
at ReflectiveInjector_._getByKeyDefault (http://localhost:8100/build/vendor.js:3168:25)
at ReflectiveInjector_._getByKey (http://localhost:8100/build/vendor.js:3100:25)
at ReflectiveInjector_.get (http://localhost:8100/build/vendor.js:2969:21)
at AppModuleInjector.get (ng:///AppModule/module.ngfactory.js:332:145)
at AppModuleInjector.getInternal (ng:///AppModule/module.ngfactory.js:615:44)
at AppModuleInjector.NgModuleInjector.get (http://localhost:8100/build/vendor.js:3936:44)
at LoginPageModuleInjector.NgModuleInjector.get (http://localhost:8100/build/vendor.js:3937:52)
at c (http://localhost:8100/build/polyfills.js:3:13535)
at Object.reject (http://localhost:8100/build/polyfills.js:3:12891)
at NavControllerBase._fireError (http://localhost:8100/build/vendor.js:45902:16)
at NavControllerBase._failed (http://localhost:8100/build/vendor.js:45890:14)
at http://localhost:8100/build/vendor.js:45945:59
at t.invoke (http://localhost:8100/build/polyfills.js:3:9283)
at Object.onInvoke (http://localhost:8100/build/vendor.js:4508:37)
at t.invoke (http://localhost:8100/build/polyfills.js:3:9223)
at r.run (http://localhost:8100/build/polyfills.js:3:4452)
at http://localhost:8100/build/polyfills.js:3:14076
Platform details
Ionic Framework: 3.6.1
Ionic App Scripts: 2.1.4
Angular Core: 4.1.3
Angular Compiler CLI: 4.1.3
Node: 6.11.2
OS Platform: Windows 10
Navigator Platform: Win32 User Agent: Mozilla/5.0 (Windows NT 10.0;
Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/60.0.3112.113 Safari/537.36
Login.ts
import { Component } from '#angular/core';
//import { GooglePlus } from '#ionic-native/google-plus';
import { TranslateService } from '#ngx-translate/core';
import { IonicPage, NavController, ToastController } from 'ionic-angular';
import { User } from '../../providers/providers';
import { MainPage } from '../pages';
#IonicPage()
#Component({
selector: 'page-login',
templateUrl: 'login.html'
})
export class LoginPage {
// The account fields for the login form.
// If you're using the username field with or without email, make
// sure to add it to the type
account: { username: string, password: string } = {
username: '',
password: ''
};
// Our translated text strings
private loginErrorString: string;
constructor(public navCtrl: NavController,
public user: User,
public toastCtrl: ToastController,
public translateService: TranslateService,
// private GooglePlus: GooglePlus
) {
this.translateService.get('LOGIN_ERROR').subscribe((value) => {
this.loginErrorString = value;
})
}
// Attempt to login in through our User service
doLogin() {
this.user.login_basic(this.account).subscribe((resp) => {
this.navCtrl.push(MainPage);
}, (err) => {
this.navCtrl.push(MainPage);
// Unable to log in
let toast = this.toastCtrl.create({
message: this.loginErrorString,
duration: 3000,
position: 'top'
});
toast.present();
});
}
}
login.module.ts
import { NgModule } from '#angular/core';
import { GooglePlus } from '#ionic-native/google-plus';
import { TranslateModule } from '#ngx-translate/core';
import { IonicPageModule } from 'ionic-angular';
import { LoginPage } from './login';
#NgModule({
declarations: [
LoginPage,
],
imports: [
IonicPageModule.forChild(LoginPage),
TranslateModule.forChild()
],
exports: [
LoginPage
],
providers: [
GooglePlus,
],
})
export class LoginPageModule { }
You need to add the GooglePlus-provider to the AppModule (app.module.ts)
Adding GooglePlus to the App.module.ts worked for me
#NgModule({
...
providers: [
GooglePlus,
],
bootstrap: [AppComponent]
})
In case of the Angular, GooglePlus should be imported like this (app.module.ts):
import { GooglePlus } from '#ionic-native/google-plus/ngx';
...
providers: [
GooglePlus,
]

Socket.io handshake address value changes

This is peculiar. Socket.io version ~1.3
io.sockets.on('connection', function (socket) {
console.log('Client connected from: ' + socket.handshake.address);
}
Returns
Client connected from: ::1
However
io.sockets.on('connection', function (socket) {
console.log(socket.handshake);
console.log('Client connected from: ' + socket.handshake.address);
}
Returns
{ headers:
{ host: 'localhost:8000',
connection: 'keep-alive',
origin: 'http://localhost:3000',
'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTM
L, like Gecko) Chrome/43.0.2357.130 Safari/537.36',
accept: '*/*',
dnt: '1',
referer: 'http://localhost:3000/dev.html',
'accept-encoding': 'gzip, deflate, sdch',
'accept-language': 'en-US;q=0.8,en;q=0.6,ko;q=0.4,de;q=0.2,ru;q=0.2,fr;q=0.2,ja;q=0.2,it;q=0.2',
cookie: 'io=yhyuAabou3GufhzNAAAA' },
time: 'Wed Jun 24 2015 22:50:19 GMT+0200 (Central European Daylight Time)',
address: '::ffff:127.0.0.1',
xdomain: true,
secure: false,
issued: 1435179019584,
url: '/socket.io/?EIO=3&transport=polling&t=1435179017804-3',
query: { EIO: '3', transport: 'polling', t: '1435179017804-3' } }
Client connected from: ::ffff:127.0.0.1
Why? Is there some ES6 proxy in the way? I thought maybe some weird JS conversion magic was in place, but it doesn't seem like it.
::ffff:127.0.0.1 is an IPv6 version of 127.0.0.1 and ::1 is an IPv6 shortcut for both.
See Express.js req.ip is returning ::ffff:127.0.0.1 for a similar question.

Resources