Downloading a File from HapiJs Server - node.js

I need a little help
I want to generate a pdf report.
I'm using PDFKit Node Module
const PDFDocument = require("pdfkit");
function generatePDF(request, reply) {
let doc = new PDFDocument();
let path = __dirname + "/payments/" + "filename" + ".pdf";
doc.text = "Hello World!";
doc.text = "Hello Me!";
doc.end();
return reply(doc)
.header('Content-disposition', 'attachment; filename=' + 'payments.pdf')
}
On the client-side, I have tried so many things:
1.
button.addEventListener("click", function (event) {
axios.get('/payment-pdf')
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}, false)
2.
<a href="/payment-pdf" download>Export</a>
How do I download the PDF file?
It seems as a simpe task, but I'm not able to get it done.
Thank you.

.text does not look like a string from the examples in the PDFKit readme. It is a function to be used like doc.text('Hello world!').
I tested with the following route:
{
method: 'GET',
path: '/payment-pdf',
config: {
auth: false
},
handler: (request: hapi.Request, reply: hapi.IReply) => {
let doc = new PDFDocument();
doc.text('Hello world!');
doc.text('Hello me!');
doc.end();
reply(doc)
.header('Content-Disposition', 'attachment; filename=payments.pdf');
}
}
And I used this html to file to download the pdf:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
Export
</body>
</html>

Related

Server-sent events with node.js http2 module - how should I use it with stream / pushStream?

I am trying to implement a server which send large amount of data (objects, not files) every 500 ms.
After some reading, Server-sent events over http2 seems like the fastest option (due to http2 being a binary protocol and SSE reduce the traffic overhead)
After playing a bit with SSE on http/1.1
I've been trying to do the same on http2. I've tried to do so with stream and pushStream, but without success. However, using the same manner I used for http/1.1 seems to work.
My question is - why server 1 (see below) which using stream is not working, while server 2 seems to work fine? am I missing something when working node streams?
I'm using node v10.9.0 and chrome 68.0.3440.106
I've read the following questions and posts, but still couldn't solve this issue:
Can I stream a response back to the browser using http2?
Node.js HTTP2 server Error: socket hang up
HTTP2 / SPDY Push-Stream Verification: How to Test?
HTTP/2 Server Push with Node.js
Using Server Sent Events with express
Server 1 - http2 with stream (Not working - client don't get events. chrome describe the request as unfinished request):
const fs = require('fs');
const http2 = require('http2');
const HTTPSoptions = {
key: fs.readFileSync('./cert/selfsigned.key'),
cert: fs.readFileSync('./cert/selfsigned.crt'),
};
const template = `
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
const source = new EventSource('/sse/');
source.onmessage = function(e) {
document.body.innerHTML += e.data + '<br>';
};
</script>
</body>
</html>
`;
const server = http2.createSecureServer(HTTPSoptions);
server.on('stream', (stream, headers, flags) => {
if (stream.url === 'sse/') {
console.log(stream.respond);
stream.respond({
':status': 200,
'content-type': 'text/event-stream'
});
setInterval(() => stream ? res.write(`data: ${Math.random()}\n\n`) : '', 200);
}
});
server.on('request', (req, res) => {
if(req.url === '/') {
res.end(template);
}
});
server.listen(3001);
Server 2 - http2 with stream (working just fine):
const fs = require('fs');
const http2 = require('http2');
const HTTPSoptions = {
key: fs.readFileSync('./cert/selfsigned.key'),
cert: fs.readFileSync('./cert/selfsigned.crt'),
};
const template = `
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
const source = new EventSource('/sse/');
source.onmessage = function(e) {
document.body.innerHTML += e.data + '<br>';
};
</script>
</body>
</html>
`;
const server = http2.createSecureServer(HTTPSoptions);
server.on('request', (req, res) => {
req.socket.setKeepAlive(true);
if(req.url === '/sse/') {
res.writeHead(200, {
'Content-Type': 'text/event-stream', // <- Important headers
'Cache-Control': 'no-cache'
});
res.write('\n');
setInterval(() => res.write(`data: ${Math.random()}\n\n`), 200);
} else {
res.end(template);
}
});
server.listen(3001);
To get the request path for a http2 stream, you have to look at the :path header (docs):
if (headers[':path'] === '/sse/') {
You also tried to use res.write, while res should be stream.
This is a working handler function based on your "Server 1" implementation:
server.on('stream', (stream, headers, flags) => {
if (headers[':path'] === '/sse/') {
stream.respond({
':status': 200,
'content-type': 'text/event-stream'
});
setInterval(() => stream.write(`data: ${Math.random()}\n\n`), 200);
}
});

Node.js set Headers in HTTP GET request

I'm using Node.js 'https' module. And i'm sending a GET request with some headers option but I get the following error:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD>
<BODY>
<H1>ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px"> Bad request.
<BR clear="all">
<HR noshade size="1px">
<PRE> Generated by cloudfront (CloudFront) Request ID: 7H9MBMS_ullYt-ZSpdMw4WjAU0O1QlVaDNw_8QLwlXZa8olpjmRPDQ== </PRE>
<ADDRESS></ADDRESS>
</BODY> </HTML>
Following is my code
const var https = require('https')
var optionsget = {
headers: {
'client': process.env.MOVIEGLU_CLIENT,
'x-api-key': process.env.MOVIEGLUE_API_KEY,
'api-version': process.env.MOVIEGLU_API_VERSION,
'Authorization': process.env.MOVIEGLUE_AUTHORISATION,
'geolocation': user.loc[0] + ';' + user.loc[1],
'Content-Type':'application/x-www-form-urlencoded'
},
host: process.env.MOVIEGLU_HOST,
path: path,
method: 'GET'
};
// do the GET request
var content = ''
var reqGet = https.request(optionsget, function (response) {
response.on('data', function (data) {
// Append data.
content += data;
});
response.on('end', function () {
console.log('content ', content)
callback(null, content)
})
});
reqGet.end();
reqGet.on('error', function (e) {
callback(e, null)
});
});
Can someone please guide me what i'm doing wrong in setting headers? I'm really stuck.
Thanks

How to redirect from an xhr request

When I send an xhr post request to my server. It replies with a 302 redirect, but I can only log the entire redirect html, and cannot get the browser to redirect to the new url.
server.js
const Hapi = require('hapi');
const Inert = require('inert');
const server = new Hapi.Server();
const port = 8888;
server.connection({ port });
server.register([ Inert ], () => {
server.route([
{
method: 'get',
path: '/',
handler: (request, reply) => {
reply.file('index.html');
}
},
{
method: 'get',
path: '/login',
handler: (request, reply) => {
reply.file('login.html');
}
},
{
method: 'post',
path: '/login',
handler: (request, reply) => {
reply.redirect('/');
}
}
]);
server.start(() => {
console.log('Server running on ', server.info.uri);
});
});
index.html
<!doctype html>
<html>
<body>
<h1> Home </h1>
go to login
</body>
</html>
login.html
<!doctype html>
<html>
<body>
<button id="home">home</button>
<script>
function goHome () {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if(xhr.readyState === 4 && xhr.status === 200) {
console.log('Response: ', xhr.response);
}
}
xhr.open('post', '/login');
xhr.send();
}
document.getElementById('home').addEventListener('click', goHome);
</script>
</body>
</html>
Is there a way to redirect to '/' without doing it client side?
Thanks in advance for the help
Is there a way to redirect to '/' without doing it client side?
No.
A redirect means "What you asked for can be found here" not "Navigate the browser to this URL". The browser will only navigate to the redirected URL if it was going to navigate to the URL it originally asked for.
A request initiated by XMLHttpRequest will get a response that will be processed by XMLHttpRequest. If that response is a redirect, it will be followed and the response to the new request will be handled by XMLHttpRequest.
Ajax is the act of making an HTTP request from JS without leaving the page.
If you want to leave the page, don't use Ajax.
Was looking for something similar, ended up setting header and then on client side used that for redirect:
$(document).on 'ajax:success', selector, (e, data, status, xhr) =>
redirectToPath = xhr.getResponseHeader('Location')
window.location = redirectToPath if redirectToPath
Can't give Node.js example, but basic Ruby on Rails controller method example with setting just header and head response:
def create
response.headers['Location'] = polymorphic_path(#document, action: :edit)
head(:ok)
end

using microsoft ocr computer vision api

My node.js web-app is using microsoft's ocr computer vision api
https://www.microsoft.com/cognitive-services/en-us/computer-vision-api
When I pass a static link to the api, it works
like:
body: "{'url':'LINK_TO_IMAGE'}",
this is the part of the request callback.
What I want is to pass links dynamically.
So that the callback function is evoked the variable link
I have tried using this:
body: {'url':link},
but this does not work, there is no response.
Is there any other format I should follow?
Look document, here https://dev.projectoxford.ai/docs/services/54ef139a49c3f70a50e79b7d/operations/5527970549c3f723cc5363e4
<!DOCTYPE html>
<html>
<head>
<title>JSSample</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
$(function() {
var params = {
// Request parameters
"language": "unk",
"detectOrientation ": "true",
};
$.ajax({
url: "https://api.projectoxford.ai/vision/v1/ocr?" + $.param(params),
beforeSend: function(xhrObj){
// Request headers
xhrObj.setRequestHeader("Content-Type","application/json");
xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key","{subscription key}");
},
type: "POST",
// Request body
data: "{body}",
})
.done(function(data) {
alert("success");
})
.fail(function() {
alert("error");
});
});
</script>
</body>
</html>

Angularjs REST API Interaction failure

I am a Angularjs New bee.This is my first Angularjs application, i am just trying to interact with Nodejs service call and to print the response. But I am receiving different error in Chrome and Firefox.
In chrome i got uncaught error and in firefox i got Error: [$injector:modulerr]
Here is my coding:
index.html:
<!doctype html>
<html data-ng-app="myapp">
<head>
<title>Monitoring</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="chrome=1">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular.min.js">
</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular-route.js">
</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular-resource.js">
</script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular-route.js">
</script>
<script type="text/javascript" src="controller/controller.js"></script>
</head>
<body>
<div ng-controller="CommonMetricsCtrl">
{{data}}
</div>
</body>
</html>
controller.js
var App = angular.module('myapp', ['ngRoute', 'ngResource']);
App.controller('CommonMetricsCtrl', ['$scope', '$resource',
function($scope, $resource) {
function createResource(url) {
return $resource(url + '?alt=:alt&method=:callback', {
alt: 'json',
callback: 'JSON_CALLBACK'
}, {
get: {
method: 'JSONP',
headers: [{
'Content-Type': 'application/json'
}, {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
}]
},
isArray: false
});
}
URL = "http://localhost:1111/servicelist";
var resource = createResource(URL);
resource.get({}, function processResponse(response) {
console.log(response);
$scope.data = response;
if (response.error) {
console.log('Error here');
}
});
}
]);
I dont know where i went wrong, Can any one sort out the issue please?
You're adding the angular-route module twice.

Resources