how to get pretty urls in hapi js - javascript

I have my server.js file working. at localhost:8080 it will serve the file i give it from the the corresponding url name like so http://localhost:8080/about.html, as long as the file exists in public/pages. I'm wondering if I can somehow set a wildcard to leave of extensions for all html files in the url so that I don't have to individually specify each file as an alias in the routes like - ['about','about.html'].
Here is my working code -
'use strict';
const Path = require('path');
const Hapi = require('hapi');
const server = new Hapi.Server();
server.connection({
port: Number(process.argv[2] || 8080),
host: 'localhost'
});
server.register(require('inert'), (err) => {
if (err) {
throw err;
}
server.route({
method: 'GET',
path: '/{param*}',
handler: {
directory: {
path: 'public/pages',
listing: true
}
},
config: {
state: {
parse: false, // parse and store in request.state
failAction: 'ignore' // may also be 'ignore' or 'log'
}
}
});
server.start((err) => {
if (err) {
throw err;
}
console.log('Server running at:', server.info.uri);
});
});
Any help is greatly appreciated, thank you.

Related

How to use Hapi.js to serve a static HTML index

With express.js i can do this
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var port = 9200;
var path = require('path');
var options = {
index: "html/index.html"
};
app.use('/', express.static('res', options));
server.listen(port);
console.log("Listening on port " + port);
How do i achieve the same thing using Hapi.js?
I have tried some things also with inertjs but I can't seem to find the correct way. Does anyone have experience with it?
Found my way to this implementation, but im getting TypeErrors:
TypeError: Cannot read property 'register' of undefined
server.register(require('inert'), (err) => {
if (err) {
throw err;
}
server.route({
method: 'GET',
path: '/index',
handler: function (request, reply) {
reply.file('C:/blabla/html/index.html');
}
});
});
Straight from the doc
In detail, you just have to call reply.file()
This will not work with hapi 17 because of the major change in the request system
server.route({
method: 'GET',
path: '/picture.jpg',
handler: function (request, reply) {
reply.file('/path/to/picture.jpg');
}
});
Fixed by using Hapi#16.x.x and Inert#4.x.x and using Ernest Jones answer.
For anyone dealing with this problem in the future here is my complete change:
const Hapi = require('hapi');
const Inert = require('inert');
const server = new Hapi.Server();
server.connection({port: 9200});
server.register(Inert, (err) => {
if (err) {
throw err;
}
server.route({
method: 'GET',
path: '/index',
handler: function (request, reply) {
reply.file('/res/html/index.html');
}
});
server.route({
path: "/res/{path*}",
method: "GET",
handler: {
directory: {
path: "./res",
listing: false,
index: false
}
}});
});
server.start();

How to use hapi js on Firebase Cloud Function?

I try to learn from an example to use express together with handlebars on firebase.
For the express way, we can send the "app" instance directly to the "functions.https.onRequest" like...
const app = express();
...
app.get('/', (req, res) => {
...
});
exports.app = functions.https.onRequest(app);
See live functions
As my understanding it's working because "express" act like http-node, so it can respond "http plain".
Comparing to hapi, here is hello-world
const Hapi = require('hapi');
const server = new Hapi.Server();
server.connection({
host: 'localhost',
port: 8000
});
server.route({
method: 'GET',
path:'/hello',
handler: function (request, reply) {
return reply('hello world');
}
});
server.start((err) => {
console.log('Server running at:', server.info.uri);
});
From the hapi example, is it possible to use hapi on firebase cloud function?
Can I use hapi without starting a server like express?
This code was straight forward as i mixed the express API that used by Firebase with hapijs API, thanks to the blog given by mister #dkolba
You can ivoke the url hapijs handler by going to
http://localhost:5000/your-app-name/some-location/v1/hi
example: http://localhost:5000/helloworld/us-central1/v1/hi
const Hapi = require('hapi');
const server = new Hapi.Server();
const functions = require('firebase-functions');
server.connection();
const options = {
ops: {
interval: 1000
},
reporters: {
myConsoleReporter: [{
module: 'good-squeeze',
name: 'Squeeze',
args: [{ log: '*', response: '*' }]
}, {
module: 'good-console'
}, 'stdout']
}
};
server.route({
method: 'GET',
path: '/hi',
handler: function (request, reply) {
reply({data:'helloworld'});
}
});
server.register({
register: require('good'),
options,
}, (err) => {
if (err) {
return console.error(err);
}
});
// Create and Deploy Your First Cloud Functions
// https://firebase.google.com/docs/functions/write-firebase-functions
exports.v1 = functions.https.onRequest((event, resp) => {
const options = {
method: event.httpMethod,
url: event.path,
payload: event.body,
headers: event.headers,
validate: false
};
console.log(options);
server.inject(options, function (res) {
const response = {
statusCode: res.statusCode,
body: res.result
};
resp.status(res.statusCode).send(res.result);
});
//resp.send("Hellworld");
});
Have a look at the inject method (last code example): http://www.carbonatethis.com/hosting-a-serverless-hapi-js-api-with-aws-lambda/
However, I don't think that this is feasible, because you would still need to hold onto the response object of the express app instance Google Cloud Functions provide to http triggered functions, as only send(), redirect() or end() will work to respond to the incoming request and not hapi's methods (see https://firebase.google.com/docs/functions/http-events).
A few changes are required in order to get compatible with hapijs 18.x.x
'use strict';
const Hapi = require('#hapi/hapi')
, functions = require('firebase-functions');
const server = Hapi.server({
routes: {cors: true},
});
server.register([
{
plugin: require('./src/plugins/tools'),
routes: {
prefix: '/tools'
}
},
]);
server.route({
method: 'GET',
path: '/',
handler: (request, h) => {
return 'It worlks!';
}
});
exports.v1 = functions.https.onRequest((event, resp) => {
//resp: express.Response
const options = {
method: event.httpMethod,
headers: event.headers,
url: event.path,
payload: event.body
};
return server
.inject(options)
.then(response => {
delete response.headers['content-encoding']
delete response.headers['transfer-encoding']
response.headers['x-powered-by'] = 'hapijs'
resp.set(response.headers);
return resp.status(response.statusCode).send(response.result);
})
.catch(error => resp.status(500).send(error.message || "unknown error"));
});

TypeError: server.views is not a function in hapi.js

I am a beginner on node.js I am using hapi framework for my web app. In that i am using handlebars for template. When i configure the server views i am getting the type error.
'use strict';
const hapi = require('hapi');
const server = new hapi.Server();
const inert = new require('inert');
server.connection({
host: '127.0.0.1',
port: 8080,
});
//Starting server
server.start((error) => {
if(error){
throw error;
}
console.log("Server running" + server);
});
server.register(inert, () => {
console.log("hhh");
server.views({
engines: {
html: require('handlebars')
},
path: 'views',
layoutPath: 'views/layout',
layout: 'default',
partialsPath: 'views/partials'
//helpersPath: 'views/helpers',
});
});
I getting this error:
TypeError: server.views is not a function
at server.register (/home/developer/Workspace/kravein-test/app/backend/server.js:22:9)
at process.nextTick (/home/developer/Workspace/kravein-test/node_modules/hoek/lib/index.js:854:22)
at _combinedTickCallback (internal/process/next_tick.js:67:7)
at process._tickCallback (internal/process/next_tick.js:98:9)
at Module.runMain (module.js:577:11)
at run (bootstrap_node.js:352:7)
at startup (bootstrap_node.js:144:9)
at bootstrap_node.js:467:3
I am using hapi 15.0.3. Thanks
For making use of server.views, you would need the Vision plugin
e.g. with Handlebars
const server = new Hapi.Server();
server.connection({ port: 8000 });
const handler = function (request, reply) {
reply.view('basic/index', {
title: 'examples/views/handlebars/basic.js | Hapi ' + request.server.version,
message: 'Hello World!'
});
};
server.register(require('vision'), (err) => {
if (err) {
throw err;
}
server.views({
engines: { html: require('handlebars') },
path: __dirname + '/templates'
});
server.route({ method: 'GET', path: '/', handler: handler });
});

Angular2 server-side-listener for file uploads

In an Angular2 CLI project, i finnaly implemented this upload button from Vaadin. The button UI works, but i don't know how to actually make it upload a file anywhere.
I keep finding solutions about express server that listens for file uploads, multer or node server, and i really have no idea how to write such a server, where to put it, how to start it, how to access it, etc.. I figured that something as trivial as file upload should be easier to achieve, but it seems is not.
What is a simple solution to implement along side Angular2 in order make the button actually upload files somewhere so i can download them later?
Found the solution in ng2-uploader repo and adapted to work with Vaadin Upload.
component.html
<div *ngIf="newName.valid">
<vaadin-upload
target="http://localhost:10050/upload"
</vaadin-upload>
</div>
server.js
'use strict';
const Hapi = require('hapi');
const Inert = require('inert');
const Md5 = require('md5');
const Multiparty = require('multiparty');
const fs = require('fs');
const path = require('path');
const server = new Hapi.Server();
server.connection({ port: 10050, routes: { cors: true } });
server.register(Inert, (err) => {});
const upload = {
payload: {
maxBytes: 209715200,
output: 'stream',
parse: false
},
handler: (request, reply) => {
const form = new Multiparty.Form();
form.parse(request.payload, (err, fields, files) => {
if (err) {
return reply({status: false, msg: err});
}
let responseData = [];
files.file.forEach((file) => {
let fileData = fs.readFileSync(file.path);
const originalName = file.originalFilename;
const generatedName = Md5(new Date().toString() +
originalName) + path.extname(originalName);
const filePath = path.resolve(__dirname, 'uploads',
originalName);
fs.writeFileSync(filePath, fileData);
const data = {
originalName: originalName,
generatedName: generatedName
};
responseData.push(data);
});
reply({status: true, data: responseData});
});
}
};
const uploads = {
handler: {
directory: {
path: path.resolve(__dirname, 'uploads')
}
}
};
server.route([
{ method: 'POST', path: '/upload', config: upload },
{ method: 'GET', path: '/uploads/{path*}', config: uploads }
]);
server.start(() => {
console.log('Upload server running at', server.info.uri);
});
And a bonus for those who need server.js running at startup this is an awesome solution tested and working.

How to transfer node.js results to HTML with javascript

I'm trying to use SQL server and nodejs with my HTML file.
I'm connecting with my database with nodejs using mssql and hapijs, and i can obtain my table in json format, but i dont know how to obtain this information on my HTML.
Also, how can i make the server update from HTML?
Here is my nodejs code:
var http = require("http");
getData = function(callback){
var sql = require('mssql');
//Data Connection
sql.connect("mssql://username:password#localhost\\SQLEXPRESS/CrudExample?encrypt:true").then(function() {
// Query
new sql.Request().query('select * from MOCK_DATA').then(function(recordset) {
//console.dir(recordset);
callback(recordset)
response.writeHead(200, {"Content-Length": results.length});
response.writeHead(200, {"Content-Type": "application/json"});
response.end(results);
}).catch(function(err) {
// ... query error checks
});
}).catch(function(err) {
// ... connect error checks
console.log('Error en la consulta')
console.log(err)
});
}
const Hapi = require('hapi');
const Path = require('path');
// Create a server with a host and port
const server = new Hapi.Server({
connections: {
routes: {
files: {
relativeTo: Path.join(__dirname, 'public')
}
}
}
});
server.connection({
host: 'localhost',
port: 8000
});
// Add the route
// Start the server
server.register(require('inert'), (err) => {
if (err) {
throw err;
}
server.route({
method: 'GET',
path:'/getTable',
handler: function (request, reply) {
getData(function(r) {return reply(r)})
}
});
server.route({
method: 'GET',
path:'/',
handler: function (request, reply) {
reply("hello world")
}
});
server.start((err) => {
if (err) {
throw err;
}
console.log('Server running at:', server.info.uri);
});
});
You can use handlebars as a view engine
refer to http://hapijs.com/tutorials/views

Categories

Resources