hapijs OnRequest server extension doesn't access the server plugin - node.js

i18n for internationalization purpose.
When user send the language code on url i will change the language of i18n like this http://localhost:8080/signup?language=en
For that i am using the server extension OnRequest. So that on it will global for each route,
but the problem occurs is when i access the i18n in OnRequest its shows undefined error
But in the route handler it shows all the properties of the hapi-i18n
Here is my code and output
server.ext('onRequest', function(request, response){
console.log("pre handler");
console.log(request.i18n);
return response.continue();
});
Output:
Undefined
But in the handler
{
method : 'POST',
path : "/signup",
config : {
tags : ['api'],
description : 'Customer signup',
},
handler: function(request, response){
console.log(request.i18n);
}
}
Output:
{ __: [Function],
__n: [Function],
getLocale: [Function],
setLocale: [Function],
getCatalog: [Function],
locale: 'en'
}

You need to use the onPostAuth extension point as the module you are using manipulates request object in the onPreAuth extension point during request object lifecycle.

Related

i18next - Loading translations from a JSON file

I'm trying to load translations from a JSON file using i18next library on Node. The path of the JSON file points to the correct location.
I'm getting the following error:
i18next::translator: missingKey en translation test test
import i18next from 'i18next';
import Backend from 'i18next-fs-backend';
const instance = i18next.use(Backend).createInstance({
lng: config.language,
debug: true,
fallbackLng: 'en',
initImmediate: false,
backend: {
loadPath: join(__dirname, `${config.language}.json`),
},
}, (error, t) => {
console.log(t('foo'));
});
JSON file:
{
"foo": "bar"
}
Specifying the translations directly in createInstance using resources property works perfectly.
I tried everything I could think of, with no success.
Found the solution!
import i18next from 'i18next';
import Backend from 'i18next-fs-backend';
const instance = i18next.use(Backend).createInstance();
instance.init({
lng: config.language,
debug: true,
fallbackLng: 'en',
initImmediate: false,
backend: {
loadPath: join(__dirname, `${config.language}.json`),
},
}, (error, t) => {
console.log(t('foo'));
});

Koa 404 when calling from Vue

I am trying to build an app with Koa and Nuxt. this is what I have:
Define service to retrieve from firestore:
const Firestore = require('#google-cloud/firestore');
const getItems = () => {
const db = new Firestore({
projectId: '*******',
keyFilename: "******"
});
db.collection('items').get()
.then((snapshot) => {
return snapshot;
})
}
Define them in routes.js:
const Router = require('#koa/router');
const articleService = require('./services/itemservice');
const router = new Router();
router.get('/getitems', async(ctx, next) => {
ctx.body = articleService.getItems();
});
module.exports = router;
Add routes to retrieve from routes.js:
app.use(router.routes());
app.use(router.allowedMethods());
And finally call it from a component:
let articles = axios.get('/getitems')
.then(response => {
console.log(response);
})//.....
I am receiving this error:
response:
{ status: 404,
statusText: 'Not Found',
headers:
{ 'content-type': 'text/html; charset=us-ascii',
server: 'Microsoft-HTTPAPI/2.0',
date: 'Fri, 25 Oct 2019 16:08:00 GMT',
connection: 'close',
'content-length': '315' },
config:
{ url: '/getarticles',
method: 'get',
headers: [Object],
transformRequest: [Array],
transformResponse: [Array],
timeout: 0,
adapter: [Function: httpAdapter],
xsrfCookieName: 'XSRF-TOKEN',
xsrfHeaderName: 'X-XSRF-TOKEN',
maxContentLength: -1,
validateStatus: [Function: validateStatus],
data: undefined },
request:
ClientRequest {
_header:
'GET /getitems HTTP/1.1\r\nAccept: application/json, text/plain, */*\r\nUser-Agent: axios/0.19.0\r\nHost: localhost\r\nConnection: close\r\n\r\n',
_onPendingData: [Function: noopPendingOutput],
agent: [Agent],
socketPath: undefined,
timeout: undefined,
method: 'GET',
path: '/getitems',
_ended: true,
res: [IncomingMessage],
aborted: undefined,
timeoutCb: null,
upgradeOrConnect: false,
parser: null,
maxHeadersCount: null,
_redirectable: [Writable],
[Symbol(isCorked)]: false,
[Symbol(outHeadersKey)]: [Object] },
data:
'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">\r\n<HTML><HEAD><TITLE>Not Found</TITLE>\r\n<META HTTP-EQUIV="Content-Type" Content="text/html; charset=us-ascii"></HEAD>\r\n<BODY><h2>Not Found</h2>\r\n<hr><p>HTTP Error 404. The requested resource is not found.</p>\r\n</BODY></HTML>\r\n' },
isAxiosError: true,
toJSON: [Function] }
Can anyone point me in the right direction?
I've never built an app with Nuxt, but I'll try to help you anyway.
First, I recommend you to read about Promises:
- https://github.com/leonardomso/You-Dont-Know-JS/blob/master/async%20%26%20performance/ch3.md
- https://github.com/leonardomso/You-Dont-Know-JS/blob/master/es6%20%26%20beyond/ch8.md
(those are two chapters of a good JS book series!)
Second, you can try two things in order to find the bug:
- add a .catch block to your thenables, to check if something went wrong;
- add a dummy route that just logs an 'OK', to make sure the routes are be registered and up to respond.
I hope this will help you!
I had this problem with my nuxt / express.js app:
If you would try to type in your browser yourURL/getitems your nuxt app will try to route you to that page instead of just to show u the data.
First thing to do, how to say, you need to define what url your backend should handle.
You go to your nuxt.config.js and add this line of code:
serverMiddleware: ["~/api/index.js"],
That means you have a folder called api and in that folder you have an index.js file and thats your express.js / koa app.
Now in your index.js where your express.js / koa app is you need to add at the end of the line this peace of code:
module.exports = {
path: "/api",
handler: app
};
If everything works fine your URL should have now a prefix api and you should be able to get the data with localhost:PORT/api/getitems
Now nuxt wont try to route you to your url/api because it knows now that this is your backend
If you could provide me your folder structure of your nuxt app i could help you more.
Here is more information about serverMiddleware
https://nuxtjs.org/api/configuration-servermiddleware
EDIT:
somewhere you have a Folder, lets say ist named server or api
in that Folder there should be a index.js file and your routes, model, Controllers etc.
Lets say you have a Folder called server and in that Server you have index.js that should look something like this
const Koa = require('koa');
const app = new Koa();
Import routes from "./routes.js"
app.use(routes)
//here you define now your backend path
module.exports = {
//you can use any path you want
path: "/backend",
handler: app
};
app.listen(3000);
Now you Need to go to your nuxt.config.js file and Point to that index.js File
serverMiddleware: ["~/server/index.js"]
Now you can Access your data with axios:
axios.get("/backend/getitems").then(data => { console.log(data) })
You will Need to add backend to your axios url because thats the path you defined that your Server will handle.

nodejs : unknown error when trying to talk to SignalR api

im trying to use this pakcage
https://www.npmjs.com/package/signalr-client
to talk with SignalR api written in c# , but i get some error just when i trying to create the client
here is my code
var signalR = require('signalr-client');
try
{
var client = new signalR.client(
"https://firouzex.exphoenixtrade.com/realtime",
['GetNewAPIToken' , 'OmsClientHub']
);
}
catch (e) {
console.log('error');
}
but i get this error
Error Message: Protocol Error
Exception: undefined
Error Data: Url {
protocol: 'https:',
slashes: true,
auth: null,
host: 'firouzex.exphoenixtrade.com',
port: null,
hostname: 'firouzex.exphoenixtrade.com',
hash: null,
search:
'?connectionData=%5B%7B%22name%22%3A%22getnewapitoken%22%7D%2C%7B%22name%22%3A%22omsclienthub%22%7D%5D&clientProtocol=1.5',
query:
[Object: null prototype] {
connectionData: '[{"name":"getnewapitoken"},{"name":"omsclienthub"}]',
clientProtocol: '1.5' },
pathname: '/realtime/negotiate',
path:
'/realtime/negotiate?connectionData=%5B%7B%22name%22%3A%22getnewapitoken%22%7D%2C%7B%22name%22%3A%22omsclienthub%22%7D%5D&clientProtocol=1.5',
href:
'https://firouzex.exphoenixtrade.com/realtime/negotiate?connectionData=%5B%7B%22name%22%3A%22getnewapitoken%22%7D%2C%7B%22name%22%3A%22omsclienthub%22%7D%5D&clientProtocol=1.5',
headers: {} }
Known issue "client.Proxy settings currently only work for HTTP and not HTTPS". There is an another package for https https://www.npmjs.com/package/signalrjs. Copied it from npm package for signalr client not getting connected

Authenticate UBER API through AngularJS 6 & Node

I am working on an application, in this application we consume UBER API. I am using NODE as backend and AngularJS 6 as frontend.
Workflow
In NODE part I have access authentication and other UBER API. i have tested through JQuery. It's working perfectly. But when I am trying to access with AngularJS 6. I am getting following error.
SyntaxError: Unexpected token h in JSON at position 0 at JSON.parse (<anonymous>) at XMLHttpRequest.onLoad (http://localhost:4200/vendor.js:11697:51) at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:2743:31) at Object.onInvokeTask (http://localhost:4200/vendor.js:41155:33) at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (http://localhost:4200/polyfills.js:2742:36) at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (http://localhost:4200/polyfills.js:2510:47) at ZoneTask.push../node_modules/zone.js/dist/zone.js.ZoneTask.invokeTask [as invoke] (http://localhost:4200/polyfills.js:2818:34) at invokeTask (http://localhost:4200/polyfills.js:3862:14) at XMLHttpRequest.globalZoneAwareCallback (http://localhost:4200/polyfills.js:3888:17)
text: "https://login.uber.com/oauth/v2/authorize?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A4200%2Flogin&scope=profile%20history%20places%20request&client_id=XXXXXXXXXXXXXXXXXXXXXXXXX"
__proto__: Object
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
message: "Http failure during parsing for http://localhost:1455/api/login"
name: "HttpErrorResponse"
ok: false
status: 200
statusText: "OK"
url: "http://localhost:1455/api/login"
__proto__: HttpResponseBase
Here is my code
NODE
app.get('/api/login', function(request, response) {
response.header('Access-Control-Allow-Origin', '*');
response.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
response.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
response.setHeader('Access-Control-Allow-Credentials', true);
var authURL=uber.getAuthorizeUrl(config.uber.scopes);
response.redirect(authURL);
});
AngularJS 6
data.service.ts
UberAuthenticate(){
return this.http.get('http://localhost:1455/api/login');
}
login.components.ts
export class LoginComponent implements OnInit {
constructor(private dataService: DataService) {
}
ngOnInit() {
this.dataService.UberAuthenticate().subscribe((response)=>{
console.log('response is ', response)
},(error) => {
console.log('error is ', error)
})
}
}
My Node application in running on PORT:1455, AngularJS PORT:4200 and callback url http://localhost:1455/api/callback.
I also set some configuration in proxy.config.json
{
"/api/*": {
"target": "http://localhost:1455",
"secure": false,
"changeOrigin": false,
"pathRewrite": {"^/api" : ""}
}
}
I haven't experience on NODE and AngularJS 6. I don't know where I am doing wrong?
Since the authorize endpoint is returning a plain text link, you need to specify it to angular in your service like this:
UberAuthenticate(){
return this.http.get('http://localhost:1455/api/login', { responseType: 'text' });
}
And in the NodeJS part, you will have to return the authorization url, the redirection has to be made in the frontend side.

Console.log(err) is crashing my website

I'm currently a student studying Web Development with Node. I recently was reviewing RESTful routes. I was building a blog site to do so. I was setting up a route to show a specific blog "/blogs/:id" which lets you see all the contents of a blog. Here's the route:
app.get("/blogs/:id", function(req, res){
blog.findById(req.params.id, function(err, blog){
if(err){
console.log(err)
} else{
res.render("show", {body: blog});
}
})
})
When I access the route using the browser, it loads forever and I get the following error in the terminal:
{ CastError: Cast to ObjectId failed for value "app.css" at path "_id" for model "blog"
at MongooseError.CastError (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/error/cast.js:29:11)
at ObjectId.cast (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schema/objectid.js:158:13)
at ObjectId.SchemaType.applySetters (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:724:12)
at ObjectId.SchemaType._castForQuery (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:1113:15)
at ObjectId.SchemaType.castForQuery (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:1103:15)
at ObjectId.SchemaType.castForQueryWrapper (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/schematype.js:1082:15)
at cast (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/cast.js:303:32)
at Query.cast (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/query.js:3355:12)
at Query._castConditions (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/query.js:1327:10)
at Query._findOne (/home/ubuntu/workspace/RESTful/node_modules/mongoose/lib/query.js:1552:8)
at process.nextTick (/home/ubuntu/workspace/RESTful/node_modules/kareem/index.js:333:33)
at _combinedTickCallback (internal/process/next_tick.js:73:7)
at process._tickCallback (internal/process/next_tick.js:104:9)
message: 'Cast to ObjectId failed for value "app.css" at path "_id" for model "blog"',
name: 'CastError',
stringValue: '"app.css"',
kind: 'ObjectId',
value: 'app.css',
path: '_id',
reason: undefined,
model:
{ [Function: model]
hooks: Kareem { _pres: [Object], _posts: [Object] },
base:
Mongoose {
connections: [Object],
models: [Object],
modelSchemas: [Object],
options: [Object],
_pluralize: [Function: pluralize],
plugins: [Object] },
modelName: 'blog',
model: [Function: model],
db:
NativeConnection {
base: [Object],
collections: [Object],
models: [Object],
config: [Object],
replica: false,
options: null,
otherDbs: [],
relatedDbs: {},
states: [Object],
_readyState: 1,
_closeCalled: false,
_hasOpened: true,
_listening: false,
_connectionOptions: [Object],
client: [Object],
name: 'restful_routing_revision',
'$initialConnection': [Object],
db: [Object] },
discriminators: undefined,
'$appliedMethods': true,
'$appliedHooks': true,
schema:
Schema {
obj: [Object],
paths: [Object],
aliases: {},
subpaths: {},
virtuals: [Object],
singleNestedPaths: {},
nested: {},
inherits: {},
callQueue: [],
_indexes: [],
methods: {},
methodOptions: {},
statics: {},
tree: [Object],
query: {},
childSchemas: [],
plugins: [Object],
s: [Object],
_userProvidedOptions: {},
options: [Object],
'$globalPluginsApplied': true,
_requiredpaths: [] },
collection:
NativeCollection {
collection: [Object],
opts: [Object],
name: 'blogs',
collectionName: 'blogs',
conn: [Object],
queue: [],
buffer: false,
emitter: [Object] },
Query: { [Function] base: [Object] },
'$__insertMany': [Function],
'$init': Promise { [Object], catch: [Function] } } }
But for some reason, when I change the callback to be the following:
app.get("/blogs/:id", function(req, res){
blog.findById(req.params.id, function(err, blog){
if(err){
res.redirect("/")
} else{
res.render("show", {body: blog});
}
})
})
The website works perfectly fine. I also tried removing the header from the show.ejs(the file being rendered when accessing the route) while keeping the console.log(err) and it also solved the problem. I tried removing the header because the header contains the tag that links the app.css file which I saw mentioned in the error. I would like to know what's wrong in console.log(err) with the css file.
p.s. I am using Expres for the routes and mongoose to access the MongoDB database. "blog" is the array of blogs. Incase you want to take a look at my show.ejs file, here it is:
<% include partials/header %>
<h1><%= body.title%></h1>
<img src="<%=body.image%>">
<p><%=body.body%></p>
<div><%=body.created%></div>
<% include partials/footer %>
And if you want to take a look at the app.css file, here it is:
img{
max-width: 600px;
width: 600px;
}
And if you want to take a look at the header.ejs file, here it si:
<!DOCTYPE html>
<html>
<head>
<title>Blogs Website</title>
<link rel="stylesheet" type="text/css" href="app.css">
</head>
<body>
Here is the full app.js file (the file containing the routes):
var express = require("express"),
app = express(),
mongo = require("mongoose"),
bodyParser = require("body-parser"),
expressSanitizer = require("express-sanitizer"),
methodOverride = require("method-override");
mongo.connect("mongodb://localhost/restful_routing_revision");
app.use(bodyParser.urlencoded({extended: true}));
app.use(expressSanitizer());
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(methodOverride('_method'));
var blogSchema = new mongo.Schema({
title: String,
body: String,
image: String,
created: {type: Date, default: Date.now}
});
var blog = mongo.model("blog", blogSchema);
app.get("/", function(req, res){
res.render("landing");
});
app.get("/blogs", function(req, res){
blog.find({}, function(err, body){
if(err){
console.log(err)
}else{
res.render("index", {blogs: body})
}
})
})
app.get("/dogs/new", function(req, res){
res.render("new");
})
app.post("/dogs", function(req, res){
var blogBody = req.body.blog;
blog.create(blogBody, function(err, body){
if(err){
console.log(err)
}else{
res.redirect("/blogs")
}
})
})
app.get("/blogs/:id", function(req, res){
blog.findById(req.params.id, function(err, blog){
if(err){
// res.redirect("/")
console.log(err)
} else{
res.render("show", {body: blog});
}
})
})
// blog.findById(req.params.id, function(err, blog){
// if(err){
// res.redirect("/");
// } else {
// res.render("show", {body: blog});
// }
// });
// });
app.listen(process.env.PORT, process.env.IP, function(){
console.log("The Server has Started!!!!");
})
There are alot of npm packages on top that I'm planning to use later. And I know that the blog Schema isn't well formatted. I also tried doing console.log(err) and res.redirect("/") at the same time, I arrive to the show page but still get the same error.
Just use absolute path /style.css instead of relative path style.css.
Explanation:
You are using app.use(express.static("public")); which will make the route app.get("/blogs/:id", function(req, res){...}); when triggered it tries to render style.css in your html link tag because it meets the route path as /blogs/style.css since your public folder is in the same level with blogs, so by putting / in front of style.css makes it an absolute path, so execution will start the path from the seed, and not continue down from blogs.
Another solution is to just handle triggering the route blogs/style.css by actually creating a route for it as follows:
app.get('/campgrounds/app.css', function(req, res) {
break;
});
Make sure to put it before the route app.get("/blogs/:id", function(req, res){...}); to be executed first, if triggered.
I hope this helps.
Regarding the CastError, I don't know what is going on in the underlying ejs code that causes it to try to run a Mongo query with the css filename, but this post explains how to fix your syntax (read the answer's comments about using a relative path for the css name):
NodeJS error when rendering page:Cast to ObjectId failed for value "styles.css" at path "_id"
I think that will get rid of the error in your endpoint.
For the headline question about crashing the server and the observation that:
When I access the route using the browser, it loads forever
is because the endpoint does not ever issue a response to the client when you get an error. All endpoints need to respond to the client in some way. In your case, the documented1 recommendation is to call the Express middleware function next:
blog.findById(req.params.id, function(err, blog){
if(err){
console.log(err);
next(err);
} else{
The next function will return an error result to the client browser. You need to use next because the .find function of your Mongoose model is asynchronous and Expresses next function is designed to deal with this correctly.
A separate detail, from what you posted, your Express server is most likely not crashing. It is logging the console message with an error just like you asked then continuing on waiting for new requests (logging an error to the console is perfectly ok!). If it crashed, you would likely get a 500 error page in the browser and the node process would terminate. I mention this in hopes to help future debugging. I think if you had searched on the client issue of the endpoint not returning, you would likely have found an existing answer about endpoints that never return to the client (this is a common issue to run into when getting started). I hope that helps!
Express Error Handling Doc
You have to put this line at the end
In app.js file
cut this line and paste it at the end:
app.use(express.static("public"));

Resources