Nodejs express 如何实现请求转发

Nodejs express 如何实现请求转发

前端ajax进入nodejs,nodejs如何发送ajax到某台服务器? 代码如下,搞不清为什么app.get是可以的,app.post没有反应。http.request 里面都没有执行。

//routes.js
var sign = require('/sign');
//这个是 OK的
app.get('/api/getUser', function(req,res){
    sign.find(req,function(res,data){
        res.render('ruleConfig.html',{user:data});
    })
})
//这个没反应
app.post('/api/getUser', function(req,res){
    sign.find(req,function(res,data){
        res.contentType('json');
        res.write(JSON.stringify(data));
    res.end();
    })
})
//sign.js
var http = require('http');
exports.find = function(req,success){
    var headers = req.headers;
    headers.host = 'www.xxx.com';
    var options = {
	    host: 'www.xxx.com',
	    port: 80,
	    path: '/getUser',
	    method: 'GET',
	    headers: headers	
    };
    var req = http.request(options, function(res) {
	    res.setEncoding('utf8');
	    res.on('data', function (data) {
	      var data = JSON.parse(data);
	      success(res,data);
	    });
    });	
    req.on('error', function(e){
       console.log("auth_user error: " + e.message);
    });
    req.end();
}

9 回复

Nodejs Express 如何实现请求转发

在使用 Node.js 和 Express 实现请求转发时,可以通过 http.request 或者更现代的 axios 库来发起 HTTP 请求。在你的例子中,问题可能出在 http.request 的配置以及对响应的处理上。下面我会提供一个更简洁且正确的示例代码来展示如何正确地使用 http.request 来实现请求转发。

示例代码

首先,确保你已经安装了 expressbody-parser

npm install express body-parser

然后,你可以创建一个简单的 Express 应用来处理 GET 和 POST 请求,并将这些请求转发到另一个服务器。

// app.js
const express = require('express');
const bodyParser = require('body-parser');
const http = require('http');

const app = express();

app.use(bodyParser.json());

// 处理 GET 请求
app.get('/api/getUser', (req, res) => {
    forwardRequest(req, res, 'GET');
});

// 处理 POST 请求
app.post('/api/getUser', (req, res) => {
    forwardRequest(req, res, 'POST');
});

function forwardRequest(req, res, method) {
    const options = {
        host: 'www.xxx.com',
        port: 80,
        path: '/getUser',
        method: method,
        headers: req.headers
    };

    const request = http.request(options, (response) => {
        let data = '';

        response.on('data', (chunk) => {
            data += chunk;
        });

        response.on('end', () => {
            res.setHeader('Content-Type', 'application/json');
            res.send(JSON.parse(data));
        });
    });

    request.on('error', (error) => {
        console.error(`Error: ${error.message}`);
        res.status(500).send({ error: 'Internal Server Error' });
    });

    if (method === 'POST') {
        request.write(JSON.stringify(req.body));
    }

    request.end();
}

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

解释

  1. Express 配置

    • 使用 body-parser 中间件来解析 JSON 请求体。
    • 定义两个路由处理函数,分别处理 GET 和 POST 请求。
  2. 请求转发函数 forwardRequest

    • 接收 req, res, 和请求方法(GET 或 POST)作为参数。
    • 创建 http.request 对象并设置请求选项,包括目标主机、端口、路径和请求方法。
    • 监听响应事件,并将响应数据拼接起来。
    • 在响应结束时,将接收到的数据发送回客户端。
    • 处理请求错误,并返回内部服务器错误。

通过这种方式,你可以轻松地实现请求转发,并处理不同的请求类型(如 GET 和 POST)。


少了个括号: res.write(JSON.stringify(data);

嗯,这只是个简单的例子便于解释我的问题。已经更正了。请问真正导致不能转发的原因在哪里?

我提议两个方法给你试试

app.post('/api/getUser', function(req,res){
    sign.find(req,function(res,data){
        res.json(data);
    })
})

var req = http.request(options, function(res) {
	res.setEncoding('utf8');
	var str = '';
	res.on('data', function(d) {
	    str += d;
	});
	res.on('end', function () {
	    var data=JSON.parse(str);
	    success(res,data);
    });
/**
 * 简单的HTTP代理服务器
 *
 * [@author](/user/author) 老雷<leizongmin@gmail.com>
 */
var http = require('http');

// 记录日志
var log = function () {
  var now = new Date().toISOString();
  arguments[0] = '[' + now + '] ' + arguments[0];
  console.log.apply(console, arguments);
};

// 获取请求的headers,去掉host和connection
var getHeader = function (req) {
  var ret = {};
  for (var i in req.headers) {
    if (!/host|connection/i.test(i)) {
      ret[i] = req.headers[i];
    }
  }
  return ret;
};

// 获取请求的路径
var getPath = function (req) {
  var url = req.url;
  if (url.substr(0, 7).toLowerCase() === 'http://') {
    var i = url.indexOf('/', 7);
    if (i !== -1) {
      url = url.substr(i);
    }
  }
  return url;
};

// 代理请求
var counter = 0;
var onProxy = function (req, res) {
  counter++;
  var num = counter;
  var opt = {
    host:     req.headers.host,
    path:     getPath(req),
    method:   req.method,
    headers:  getHeader(req)
  };
  log('#%d\t%s http://%s%s', num, req.method, opt.host, opt.path);
  var req2 = http.request(opt, function (res2) {
    res.writeHead(res2.statusCode, res2.headers);
    res2.pipe(res);
    res2.on('end', function () {
      log('#%d\tEND', num);
    });
  });
  if (/POST|PUT/i.test(req.method)) {
    req.pipe(req2);
  } else {
    req2.end();
  }
  req2.on('error', function (err) {
    log('#%d\tERROR: %s', num, err.stack);
    res.end(err.stack);
  });
};


// 启动http服务器
var server = http.createServer(onProxy);
server.listen(8080);
log('proxy server listen on http://127.0.0.1:8080');

不错。这个就是我想要的,多谢

利用pipe处理转发是最简单的

要实现请求转发(无论是 GET 还是 POST 请求),可以使用 httphttps 模块来发起新的 HTTP 请求并将响应返回给客户端。在你的例子中,问题可能在于你对 res 变量的命名冲突。在回调函数中,你再次声明了一个名为 res 的参数,这会覆盖外部作用域中的 res 变量。

以下是修正后的代码:

// routes.js
var sign = require('./sign');

app.get('/api/getUser', function(req, res) {
    sign.find(req, function(response, data) {
        res.render('ruleConfig.html', { user: data });
    });
});

app.post('/api/getUser', function(req, res) {
    sign.find(req, function(response, data) {
        res.contentType('application/json');
        res.send(JSON.stringify(data));
    });
});

// sign.js
var http = require('http');

exports.find = function(req, success) {
    var headers = req.headers;
    headers.host = 'www.xxx.com';
    var options = {
        host: 'www.xxx.com',
        port: 80,
        path: '/getUser',
        method: req.method, // 使用原始请求的方法
        headers: headers
    };

    var reqProxy = http.request(options, function(resProxy) {
        resProxy.setEncoding('utf8');
        let data = '';
        resProxy.on('data', function(chunk) {
            data += chunk;
        });

        resProxy.on('end', function() {
            try {
                const parsedData = JSON.parse(data);
                success(resProxy, parsedData);
            } catch (e) {
                console.error('Error parsing response:', e);
            }
        });
    });

    reqProxy.on('error', function(e) {
        console.log("auth_user error: " + e.message);
    });

    req.on('data', function(chunk) {
        reqProxy.write(chunk);
    });

    req.on('end', function() {
        reqProxy.end();
    });
};

解释

  1. 请求方法:在 sign.js 中,我们使用了 req.method 来确定转发请求时使用的方法(GET 或 POST)。
  2. 命名冲突:在 success 回调中,我们将内部的 res 更改为 response,以避免与外部的 res 变量冲突。
  3. 处理数据:在 resProxy 响应事件中,我们累积了所有的数据片段,并在 end 事件中进行解析。
  4. 请求体处理:在 req 上添加 'data''end' 事件处理器,以便将客户端请求的数据传递给代理请求。

这样,无论是 GET 还是 POST 请求都能正确转发并返回响应。

回到顶部