I have a simple expressjs script like:
var app = require('express')();
var http = require('http').Server(app);
var requestAuth = function (req, res, next) {
var xhr = new XMLHttpRequest()
console.log("a", xhr)
next()
}
app.use(requestAuth)
app.get('/', function(req, res){
res.send('<h1>Hello again</h1>');
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
Here I want to make simple ajax call and check for authentication in url.
Whhen I execuste the above script it gives me error like XMLHttpRequest is not defined. What is the issue here ?
Same type of error I got when I tried using promise
How can I make http request using xhr or fetch ?
Isnt it nodejs should accept all the functions that normal javascript accept ?
Can anyone make me more clear ? I am very new to expressjs
You have not requrie module xmlhttprequest require it like that.
first run command
npm install xmlhttprequest --save
then require ("xmlhttprequest").XMLHttpRequest;
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
It will work perfectly fine even if you remove this part of code from your app. i.e
var requestAuth = function (req, res, next) {
var xhr = new XMLHttpRequest()
console.log("a", xhr)
next()
}
app.use(requestAuth)
Related
I want to create a request GET that returns a json data type with ajax
The route is so simply like this:
app.get('/', function(req, res) {
res.json({ answer: 42})
});
When I open / in the browser it render this:
All ok, but I trying to get answer json with XMLHttpRequest vanilla JS (no jquery):
var xhr = new XMLHttpRequest();
xhr.open("GET", 'http://localhost:3000/');
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.responseType = 'json'
xhr.addEventListener('load', function () {
alert(this.response) // response is 'null'
})
xhr.send();
the response property is null and thw browser look like this:
I get nothing back. What am I missing here?
I don't see any issue with the code It must be a cross domain issue. The reason it works from postman is it handle the preflight automatically. You need to enable cors in your express server like this.
const express = require('express')
const app = express();
var cors = require('cors')
app.use(cors())
app.get('/', function(req, res) {
res.json({ answer: 42})
});
app.listen(3000, () => {
console.log("listening");
});
Hope it helps.
I am trying to capture current GET URL and query params in node.js code. I jut realized windows.loication does not work in node.js as it is for client-based execution only. I have tried multiple things but am not able to capture the GET request. Here is what all I have tried.
var url = require('url');
var url_parts = url.parse(request.url, true);
var query = url_parts.query;
var request = require('request');
var query = url.parse(request.url,true).query;
getFormattedUrl(req);
function getFormattedUrl(req) {
console.log("req.url: " + req.url);
return url.format({
protocol: req.protocol,
host: req.get('host')
});
}
All of these fail for me, giving the errors like :
2016-12-17T03:32:36.164600+00:00 app[web.1]: ReferenceError: request is not defined
2016-12-17T03:43:46.569603+00:00 app[web.1]: ReferenceError: request is not defined
2016-12-17T03:45:14.509168+00:00 app[web.1]: TypeError: Parameter 'url' must be a string, not undefined
Can someone pls suggest how to cpature the GET params in node.js.
If you are using express 4.x then you want req.query
If you are trying to capture the request that is being made from a NODE JS server to another http/https endpoint for debugging or viewing purposes, this might help
var options2 = {
url: "https://www.google.com",
port: '443',
method: 'GET'
}
request(options2, function(error, response){
console.log(options2);
});
where options2 is the defined URL the node js server is trying to reach
When you console log options2 (a variable name i've used, you can call it anything), it will give you all the information about the HTTPS/HTTP call the server is making.
Sample Express JS 4 Code
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.send('Someting')
console.log(req.query);
})
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
})
This will launch a localhost server on port 3000
If you do localhost:3000?q=test you will see
{q: test}
in the console/log.
To fix the problem above, just install request module from the command line first, before using it:
npm install request
Interesting things is that to achieve what you need, you do not need to use request module at all. Just use url module as you did above, pass request object (not a module, but actual calling request), and format it using url.format
const url = require('url')
function getFormattedUrl(req) { return url.format(req.url) }
I am using node-http-proxy for the POST request as follows:
route.js
---------
var express = require('express');
var httpProxy = require('http-proxy');
var bodyParser = require('body-parser');
var proxy = httpProxy.createProxyServer({secure:false});
var jsonParser = bodyParser.json();
proxy.on('proxyReq', function(proxyReq, req, res, options) {
logger.debug("proxying for",req.url);
//set headers
logger.debug('proxy request forwarded succesfully');
});
proxy.on('error', function (err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Something went wrong. And we are reporting a custom error message.');
});
proxy.on('proxyRes', function (proxyRes, req, res) {
console.log('RAW Response from the target', JSON.stringify(proxyRes.headers, true, 2));
});
module.exports = function(app){
app.post('/recording',jsonParser,function(req,res){
// update request body
proxy.web(req, res, { target: <<host>>:<<port>>});
});
}
app.js
---------
var express = require('express');
var app = express();
require('./routes')(app);
app.listen(8080);
console.log("Demo server running");
I also use bodyparser middleware and it has a known issue as mentioned in Gitbug issue. So I tried adding this line as the last line in app.js
app.use(require('connect-restreamer')());
But still the POST request hangs and ultimately fails. How do I fix this ? Is there any alternatives for bodyparser ?
Try reversing the order of the bodyParser- and proxy middleware:
module.exports = function(app){
app.post('/recording', function(req,res){
// update request body
proxy.web(req, res, { target: <<host>>:<<port>>});
}, jsonParser);
}
Think this issue is similar to: socket hang up error with nodejs.
To expand on this a bit, what's happening here is that the node request is a stream, it can only be read once, after that the stream data is consumed.
When you use body-parser middleware in express, it will consume the request stream body - if you try to proxy the request after this, there's no body stream to send, so the other end of the proxy receives a POST with a content-length, etc... but waits indefinitely to receive the POST body which never arrives.
If you want to proxy POST/PUT or really any requests that contain a body, you have to do that before any middleware consumes the body. That's why #chimmurai answer above works.
Also, be aware that for the same reason, middleware that executes after you proxy a request will be affected the same way, once the request stream is consumed there won't be anything for subsequent middleware to read. That's the reason for things like connect-restreamer.
In my scenario I need forward get request to another end point. In my machine there are two servers php and node.js server. Node.js is like a "man in the middle", PHP server must work in the same way.
Node.js server code
var express = require('express');
var fs = require('fs');
var path = require('path');
var http = require('http');
var https = require('https');
var app = express();
var HTTP_PORT = 3000;
// Create an HTTP service
http.createServer(app).listen(HTTP_PORT,function() {
console.log('Listening HTTP on port ' + HTTP_PORT);
});
//endpoint for tracking
app.get('/track', function(req, res) {
sendRequestToOtherEndPoint(req);
processRequest(req);
res.setHeader('Content-Type', 'application/json');
res.send('Req OK');
});
function processRequest(req){
console.log("request processed");
}
function sendRequestToOtherEndPoint(req){
//magic here :)
}
When this server receive a get request in port 3000, it process request information and it must forward the same requesto to another end point.
For example:
Get localhost:3000/track?param1=1¶m2=2
Server process get request
Server forward get request to localhost/final-endpoint?param1=1¶m2=2
Depending on what you're trying to do, you can create a new request to the end-point:
//endpoint for tracking
app.get('/track', function(req, res) {
req.get({url: 'http://end-point', headers: req.headers});
processRequest(req);
res.setHeader('Content-Type', 'application/json');
res.send('Req OK');
});
More info: https://github.com/request/request
There are a couple of useful libraries that one could use:
http-proxy-middleware:
const proxy = require('http-proxy-middleware')
var apiProxy = proxy('/track', {target: 'http://end-point'});
app.use(apiProxy)
axios-express-proxy
import express from 'express';
import { Proxy } from 'axios-express-proxy';
const app = express();
const port = 3000;
app.get('/track', (req, res) => Proxy('http://end-point', req, res));
In you case res.redirect might help.
app.get('/track', function(req, res) {
// process the request
// then redirect
res.redirect('/final-endpoint');
});
Then catch the redirected request in final endpont.
app.get('/final-endpoint', function(req, res) {
// proceess redirected request here.
});
See the Express docs
If your second endpoint is on a different server, (e.g. PHP) then you're going to need to either redirect the client (as in sohel's answer), or spoof a request from Node to the PHP server and then send the response back to the client. This latter option is definitely non-trivial so I would question whether it's crucial not to use a client redirect.
If you're talking about two express endpoints, then I think the simplest answer might be not to actually forward at all, but just use the endpoint callback directly instead:
app.get('/track', trackCallback);
app.get('/otherendpoint', otherendpointCallback);
function otherendpointCallback(req, res) {
// do your thing
}
function trackCallback(req, res) {
otherendpointCallback(req, res);
processRequest(req);
res.setHeader('Content-Type', 'application/json');
res.send('Req OK');
};
Depending on exactly what you want to do at the other end point, you might need to spoof some of req's fields (e.g. req.url)
I have the following...
var request = require('request');
exports.list = function(req, res){
res.send("Listing");
};
exports.get = function(req, res){
request.get("<URL>", function (err, res, body) {
if (!err) {
res.send(body,"utf8");
}
});
};
This fails with the following....
TypeError: Object #<IncomingMessage> has no method 'send'
How do I do this?
UPDATE tried to use write instead of send but...
/Users/me/Development/htp/routes/property.js:9
res.setHeader('Content-Type', 'text/html');
^
TypeError: Object #<IncomingMessage> has no method 'setHeader'
Also writing out to the console instead works fine.
Problem was with scope of variables, my response output was the same name as the response object I got back in my callback. Changing this around (resp vs res) made it work....
exports.get = function(req, res){
request.get("<url>", function (err, resp, body) {
if (!err) {
res.send(body);
}
});
};
What you are trying to do, is to make Request > Response server. But you are using Request module, that allows to get stuff rather than respond.
What you need is http or better get express.js and use it, as it is straight forward and well popular web framework for exactly what you need.
I wasn't aware OP is using Express. You will encounter a similar error if you attempt to use req.send with the vanilla HTTP module instead of Express.
var http = require('http');
function requestHandler(req, res){
//res.send(200, '<html></html>'); // not a valid method without express
res.setHeader('Content-Type', 'text/html');
res.writeHead(200);
res.end('<html><body>foo bar</body></html>');
};
http.createServer(handler).listen(3000);