node.js set cookie and send gif in response - node.js

I wrote a script in node.js (base on web beacon pixel), that need to set cookie and send a pixel back to the client.
My problem is that the cookie is not setting , if i remove from the code the part that send the GIF its working, but i cant find a way to make this 2 thing together set a cookie and send the GIF back.
http = require('http');
url = require('url');
http.createServer(function(req, res){
var requestURL = url.parse(req.url, true);
if (requestURL.pathname == '/log.gif') {
// Write a Cookie
res.writeHead(200, {
'Set-Cookie' : 'id='+requestURL.query.id+'; expires=' + new Date(new Date().getTime()+86409000).toUTCString()
});
var imgHex = '47494638396101000100800000dbdfef00000021f90401000000002c00000000010001000002024401003b';
var imgBinary = new Buffer(imgHex, 'hex');
res.writeHead(200, {'Content-Type': 'image/gif' });
res.end(imgBinary, 'binary');
} else {
res.writeHead(200, {'Content-Type': 'text/plain' });
res.end('');
}
}).listen(8080);

http://nodejs.org/api/http.html#http_response_writehead_statuscode_reasonphrase_headers:
“This method must only be called once on a message”
Just add the Set-Cookie header in your res.WriteHead call that sets the Content-type:
res.writeHead(200, {
'Content-Type': 'image/gif',
'Set-Cookie' : '…'
});

Related

Handle API Response in .gzip with XML file inside

I'm trying to handle this API interaction with node.js (using express and request) but i'm having a lot of trouble dealing with the data.
Here's my current code:
// Requirements
const express = require("express");
const bodyParser = require("body-parser");
const request = require("request");
const fs = require("fs");
const zlib = require("zlib");
const gunzip = require("gunzip-file");
const decompressResponse = require("decompress-response");
// Setting Up App
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
// Routes
app.get("/", (req, res) => {
res.send("App Running");
});
// API Integration
let responseXML = "";
let bodyXML =
'<?xml version="1.0" encoding="UTF-8"?><RequestMensagemCB><login>14087809000107</login><senha>xxxx</senha><mId>1</mId></RequestMensagemCB>';
const options = {
url: "http://webservice.newrastreamentoonline.com.br/",
method: "POST",
body: bodyXML
};
app.get("/onix", function(req, res) {
request(options, function(error, response, body) {
// body is the decompressed response body
console.log(
"server encoded the data as: " +
(response.headers["content-encoding"] || "identity")
);
console.log("the decoded data is: " + body);
})
.on("data", function(data) {
// decompressed data as it is received
console.log("decoded chunk: " + data);
})
.on("response", function(response) {
// unmodified http.IncomingMessage object
response.on("data", function(data) {
// compressed data as it is received
console.log("received " + data.length + " bytes of compressed data");
});
});
});
// Server Listening
app.listen(process.env.PORT || 3000, () => {
console.log("Server Online Listening to port 3000");
});
This is the console.log response i get:
Using postman i can reach the XML through the following route:
I first make the post request with the XML needed to validate the API Access, then i send and download the response giving it the extension of .gz and inside the .gz there's a compressed version of the file that when opened shows the XML response:
This is my first time working with an API that returns the data in .gz that way. I've tried piping the data using zLib and now was thinking on the following route: download the response in .gz, decompress the resulting file, then opening it to reach the XML. I imagine there's a better way of doing this!
I Could fix the code through another approach.
I've added 2 more params for the const options:
const options = {
url: "http://webservice.newrastreamentoonline.com.br/",
method: "POST",
body: bodyXML,
headers: {
"Accept-Encoding": "gzip"
},
encoding: null,
gzip: true
};
The key value is the following: encoding: null, , that way the stream comes without corruption.
Then i've been able to print out the XML response. Using xml2json NPM i've been able to convert it on a JSON object, and now i'll work normally with the data.

error Resource interpreted as Stylesheet but transferred with MIME type text/html: in nojd.js simple app

Facing below error while creating a simple html, css application in node.js:
error Resource interpreted as Stylesheet but transferred with MIME type text/html:
server.js code is :
var http = require('http');
var fs = require('fs');
var url = require('url');
// Create a server
http.createServer( function (request, response) {
// Parse the request containing file name
var pathname = url.parse(request.url).pathname;
// Print the name of the file for which request is made.
console.log("Request for " + pathname + " received.");
// Read the requested file content from file system
fs.readFile(pathname.substr(1), function (err, data) {
if (err) {
console.log(err);
// HTTP Status: 404 : NOT FOUND
// Content Type: text/plain
response.writeHead(404, {'Content-Type': 'text/html'});
} else {
//Page found
// HTTP Status: 200 : OK
// Content Type: text/plain
response.writeHead(200, {'Content-Type': 'text/html'});
// Write the content of the file to response body
response.write(data.toString());
}
// Send the response body
response.end();
});
}).listen(9999);
// Console will print the message
console.log('Server running at http://127.0.0.1:9999/');
index.html
<link rel="stylesheet" type="text/css" href="css/style.css">
You could use the path module to identify the extension and set the mime type accordingly:
// require path module
var path = require('path');
// check for extenstion
var pathname = url.parse(request.url).pathname;
var ext = path.extname(pathname).substr(1);
// check extension and set mime type
// HTTP Status: 200 : OK
if (ext === 'css') {
// check for css
response.writeHead(200, {'Content-Type': 'text/css'});
} else {
// Content Type: text/plain
// maybe also check .html type
response.writeHead(200, {'Content-Type': 'text/html'});
}
// Write the content of the file to response body
response.write(data.toString());

How can I rewrite/redirect the default page in Meteor to point to /public/index.html

I am using Meteor as the backend to my ionic+angular webApp. I'm deploying the app using meteor-up. I have put my entire app in the Meteor /public folder and it works find when I access it like this:
http://localhost:3000/index.html
How can I set/rewrite/redirect the Meteor default page so I can load the same page from:
http://localhost:3000/ or http://localhost:3000/myApp
without losing my Meteor server
Here is the complete solution:
fs = Npm.require('fs');
crypto = Npm.require('crypto');
WebApp.connectHandlers.use("/", function(req, res, next) {
var data, filepath;
if (req.method !== 'GET') {
return next();
}
filepath = process.env.PWD + '/public/index.html';
// serve default file, with eTag,
// i.e. http://localhost:3000/
fs.readFile(filepath, function(err, buf) {
var eTag;
eTag = crypto.createHash('md5').update(buf).digest('hex');
if (req.headers['if-none-match'] === eTag) {
res.writeHead(304, 'Not Modified');
return res.end();
}
res.writeHead(200, {
'ETag': eTag,
'Content-Type': 'text/html'
});
return res.end(buf);
});
return;
// serve default file, without eTag or caching headers
// i.e. http://localhost:3000/
data = fs.readFileSync(filepath);
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.write(data);
return res.end();
// redirect to default file
// i.e. http://localhost:3000/index.html
res.writeHead(301, {
'Location': '/index.html'
});
return res.end();
});

Node.js, Express, Jade - Error: Can't set headers after they are sent

I'm getting the following error when trying to produce an HTML page using Jade. Has anybody else experienced this issue. I noted below where exactly the error is caused.
Error
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (http.js:644:11)
at ServerResponse.res.setHeader (/Users/dereklo/node_modules/express/node_modules/connect/lib/patch.js:59:22)
at ServerResponse.res.set.res.header (/Users/dereklo/node_modules/express/lib/response.js:475:10)
at ServerResponse.res.contentType.res.type (/Users/dereklo/node_modules/express/lib/response.js:350:15)
at ServerResponse.res.send (/Users/dereklo/node_modules/express/lib/response.js:111:14)
at res.render.fn (/Users/dereklo/node_modules/express/lib/response.js:672:10)
at Object.exports.render (/Users/dereklo/node_modules/jade/lib/jade.js:216:5)
Node.js/Express/Jade Source Code
var http = require('http'),
express = require('express'),
jade = require('jade'),
url = require('url'),
jsdom = require('jsdom'),
child_proc = require('child_process'),
w,
h,
scripts = ["/Users/dereklo/Node/pie/d3.min.js",
"/Users/dereklo/Node/pie/d3.v2.js",
"/Users/dereklo/Node/pie/d3.layout.min.js",
"/Users/dereklo/Node/pie/RadialScriptMobileServ.js",
"/Users/dereklo/Node/pie/RadialScriptMobile.js",
"/Users/dereklo/Node/pie/canvg.js"];
//scripts = ["./d3.v2.js",
// "./d3.layout.min.js",
// "./pie.js"]
htmlStub = '<!DOCTYPE html><div id="RadialScriptMobileServ"></div>',
querystring = require("querystring"),
fs = require("fs"),
formidable = require("formidable"),
path = require('path'),
request = require('request')
svgsrc = '';
//create an app server
var app = require('express').createServer();
//set path to the views (template) directory
app.set('views', __dirname + '/views');
//set path to static files
app.use(express.static(__dirname + '/../public'));
//handle GET requests on /
app.get('/', function(req, res){
res.writeHead(200, {'Content-Type': 'text/plain'});
w = (url.parse(req.url, true).query['width']);
h = (url.parse(req.url, true).query['height']);
console.log("width: ",w);
console.log("height: ",h);
request("http://dcaps-staging.media.mit.edu:8080/api/reality_analysis_service/get_reality_analysis_data?document_key=radialData&bearer_token=8e2f9e3129", function (err, result, json) {
json = JSON.parse(json);
console.log("my radial data: ",json.radialData.data);
jsdom.env({features:{QuerySelector:true}, html:htmlStub, scripts:scripts, done:function(errors, window) {
svgsrc = window.insertRadial("#RadialScriptMobileServ",w,h,json).innerHTML;
console.log(svgsrc);
res.render('/Users/dereklo/Node/pie/Jade_radial.jade', {pageTitle: 'Franz Enzenhofer'}); // ERROR OCCURRING HERE!
// res.write(svgsrc);
res.end();
}})
})
});
//listen on localhost:3000
app.listen(3000);
//console.log('Pie SVG server running at http://127.0.0.1:3000/');
My issue was that I needed to remove:
res.writeHead(200, {'Content-Type': 'text/plain'});
It now works perfectly. I hope this will help others who stumble upon this post...
You can do it two ways. Either add another route above your app.get(/ ..) like this:
// global controller
app.get('/*',function(req,res,next){
res.header('Content-Type': 'text/plain' , 0 );
next(); // http://expressjs.com/guide.html#passing-route control
});
Or you can add middle ware function to your existing route
addToHeader = function (req, res, next) {
console.log("add to header called ... " + req.url);
res.header('Content-Type': 'text/plain', '0');
next();
}
and then change your routes to sth like this:
app.get('/', addToHeader, function(req,res){
var stuff = { 'title': 'blah' };
res.render('mytemplate',stuff);
});
When using res.render(), you don't need to handle response manually (res.end(), res.writeHead(), etc.).

Nodejs - Redirect url

How do I get a node.js server to redirect users to a 404.html page when they enter an invalid url?
I did some searching, and it looks like most results are for Express, but I want to write my server in pure node.js.
The logic of determining a "wrong" url is specific to your application. It could be a simple file not found error or something else if you are doing a RESTful app. Once you've figured that out, sending a redirect is as simple as:
response.writeHead(302, {
'Location': 'your/404/path.html'
//add other headers here...
});
response.end();
If you are using ExpressJS, it's possible to use:
res.redirect('your/404/path.html');
To indicate a missing file/resource and serve a 404 page, you need not redirect. In the same request you must generate the response with the status code set to 404 and the content of your 404 HTML page as response body. Here is the sample code to demonstrate this in Node.js.
var http = require('http'),
fs = require('fs'),
util = require('util'),
url = require('url');
var server = http.createServer(function(req, res) {
if(url.parse(req.url).pathname == '/') {
res.writeHead(200, {'content-type': 'text/html'});
var rs = fs.createReadStream('index.html');
util.pump(rs, res);
} else {
res.writeHead(404, {'content-type': 'text/html'});
var rs = fs.createReadStream('404.html');
util.pump(rs, res);
}
});
server.listen(8080);
404 with Content/Body
res.writeHead(404, {'Content-Type': 'text/plain'}); // <- redirect
res.write("Looked everywhere, but couldn't find that page at all!\n"); // <- content!
res.end(); // that's all!
Redirect to Https
res.writeHead(302, {'Location': 'https://example.com' + req.url});
res.end();
Just consider where you use this (e.g. only for http request), so you don't get endless redirects ;-)
Try this:
this.statusCode = 302;
this.setHeader('Location', '/url/to/redirect');
this.end();
I used a switch statement, with the default as a 404:
var fs = require("fs");
var http = require("http");
function send404Response (response){
response.writeHead(404, {"Content-Type": "text/html"});
fs.createReadStream("./path/to/404.html").pipe(response);
}
function onRequest (request, response){
switch (request.url){
case "/page1":
//statements
break;
case "/page2":
//statements
break;
default:
//if no 'match' is found
send404Response(response);
break;
}
}
http.createServer(onRequest).listen(8080);
You have to use the following code:
response.writeHead(302 , {
'Location' : '/view/index.html' // This is your url which you want
});
response.end();
Use the following code this works fine in Native Nodejs
http.createServer(function (req, res) {
var q = url.parse(req.url, true);
if (q.pathname === '/') {
//Home page code
} else if (q.pathname === '/redirect-to-google') {
res.writeHead(301, { "Location": "http://google.com/" });
return res.end();
} else if (q.pathname === '/redirect-to-interal-page') {
res.writeHead(301, { "Location": "/path/within/site" });
return res.end();
} else {
//404 page code
}
res.end();
}).listen(8080);
use
res.redirect('/path/404.html');
or you can redirect to any defined URI as
res.redirect('/');

Resources