请教一个在http.request的response事件中的嵌套data事件中Nodejs的http跳转问题(已解决,statusCode错误地取默认值200所致)
请教一个在http.request的response事件中的嵌套data事件中Nodejs的http跳转问题(已解决,statusCode错误地取默认值200所致)
我按照如下流程执行了一序列的嵌套操作 1,普通的get请求handler ↓ 2,发起post请求 ↓ 3,post请求的response事件的handler ↓ 3,注册post请求的response对象的data事件 ↓ 4,data事件中使用1中的response对象通过setHeader执行跳转
但实际的结果是在浏览器端仍然停留在1中的请求上,并没有执行4中所执行的跳转。本人也是刚开始学习nodejs,不明白问题出在哪里。恳请对此熟悉的大侠指点一下!先谢过!
好的,让我们来分析并解决这个问题。根据你的描述,问题出在 statusCode
错误地取了默认值 200,导致跳转没有正确执行。我们可以通过检查 response.statusCode
并在需要时进行跳转来解决这个问题。
下面是具体的代码示例:
const http = require('http');
function makeGetRequest() {
const options = {
hostname: 'example.com',
port: 80,
path: '/api/get-data',
method: 'GET'
};
const req = http.request(options, (res) => {
res.on('data', (chunk) => {
console.log(`Received data: ${chunk}`);
// 检查响应状态码是否为3xx(重定向)
if (res.statusCode >= 300 && res.statusCode < 400) {
const location = res.headers.location;
if (location) {
console.log(`Redirecting to: ${location}`);
// 发起新的GET请求到重定向的URL
makeGetRequest(location);
} else {
console.error('Location header not found in the response.');
}
}
});
res.on('end', () => {
console.log('Response ended.');
});
});
req.on('error', (e) => {
console.error(`Problem with request: ${e.message}`);
});
req.end();
}
// 调用函数发起初始GET请求
makeGetRequest();
解释:
- 发起GET请求:首先,我们创建一个HTTP GET请求。
- 处理响应:当接收到响应时,我们监听
data
事件以获取响应数据。 - 检查状态码:在
data
事件的处理器中,我们检查响应的状态码是否在 300-399 范围内,这表示一个重定向。 - 处理重定向:如果状态码是重定向状态码,我们从响应头中获取
Location
字段,并发起一个新的GET请求到该位置。 - 结束事件:最后,我们监听
end
事件以确保响应已经完全接收完毕。
这样,当服务器返回重定向状态码时,客户端会自动跟随重定向,并不会停留在原始请求页面。这样就能解决你遇到的问题。
补充一下4中有设置statusCode和end()调用,没有遗漏什么东西
请上代码
感谢朴灵的回复,代码如下
app.get('/weibo', function(req, res){
if (!req.query.code)
{
console.log(req.query);
res.statusCode = 400;
res.end('error: '+req.query.error_description);
return;
}
var data = ['client_id='+weibo.config.client_id,
'client_secret='+weibo.config.client_secret,
'grant_type=authorization_code',
'redirect_uri='+weibo.config.redirect_uri,
'code='+req.query.code].join('&');
httpclient.post('https://api.weibo.com/oauth2/access_token', data, function(resp){
console.log('weibo.token string: '+resp);
weibo.token = JSON.parse(resp);
console.log('weibo.token.access_token: '+weibo.token.access_token);
console.log('now we will go back to /');
res.statucCode = 302;
res.setHeader('Location', '/');
res.end();
});
});
/weibo是weib open api的回调uri,是正常从 https://api.weibo.com/oauth2/authorize 跳转回来的,实际console打印中有 weibo.token string: weibo.token.access_token: now we will go back to / 的输出,但是没有跳转;app.get()实现是《深入浅出nodejs》中的example,就不列举了;httpclient是对http.request/https.request直观的封装,代码如下
var httpclient = {};
httpclient.post = function(u, data, callback){
var urlparts = url.parse(u, true);
var request;
if (urlparts.protocol === 'http:')
{
request = http.request({
hostname: urlparts.host,
port: urlparts.port || 80,
method: 'POST',
path: urlparts.pathname
});
}
else if (urlparts.protocol === 'https:')
{
request = https.request({
hostname: urlparts.host,
port: urlparts.port || 443,
method: 'POST',
path: urlparts.pathname
});
}
else
{
console.error('unsupported protocol: '+urlparts.protocol);
return;
}
request.on('response', function(res){
res.on('data', function(d){
callback(d.toString());
});
});
request.setHeader('Content-Type', 'application/x-www-form-urlencoded');
request.setHeader('Content-Length', data.length);
request.end(data);
}
module.exports = httpclient;
解决了就好,我还特意去翻了翻Express框架中response.redirect()
的实现代码,呵呵。
根据你的描述,问题可能是由于在 http.request
的 response
事件中,statusCode
可能没有正确地从响应头中获取到,导致你误以为 statusCode
是默认的 200
,从而未能执行跳转。
在 Node.js 中,HTTP 响应的状态码可以通过 response.statusCode
来获取。你需要确保在处理 response
事件时,检查 response.statusCode
是否为重定向状态码(如 301
, 302
, 307
等),然后相应地进行处理。
以下是一个示例代码,展示了如何正确处理 HTTP 跳转:
const http = require('http');
function makeRequest(url) {
const options = {
hostname: new URL(url).hostname,
port: 80,
path: new URL(url).pathname,
method: 'GET',
headers: {
'User-Agent': 'node.js'
}
};
const req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
if ([301, 302, 307].includes(res.statusCode)) {
// 如果是重定向状态码,提取 Location 头并重新请求
const location = res.headers.location;
if (location) {
console.log(`Redirecting to: ${location}`);
makeRequest(location);
} else {
console.error('Location header not found in redirect response');
}
} else {
// 处理非重定向状态码的响应
let data = '';
res.on('data', (chunk) => {
data += chunk;
});
res.on('end', () => {
console.log(data);
});
}
});
req.on('error', (e) => {
console.error(`Problem with request: ${e.message}`);
});
req.end();
}
// 初始请求
makeRequest('http://example.com');
在这个示例中,我们创建了一个 makeRequest
函数来发起 HTTP GET 请求。当接收到重定向状态码时,我们提取 Location
头并重新发起请求。对于其他状态码,我们继续读取数据并在结束时打印出来。
希望这段代码能帮助你理解如何处理 HTTP 跳转,并解决你的问题。