重定向

时间:2018-11-03 15:00:48

标签: javascript node.js

我有此代码:

const http = require('http');

const server = http.createServer((req, res) => {
  const url = req.url;
      
  if(url == "/")
  {
    new Main(req, res).index()
  }
  else if(url == "/login")
  {
    new Main(req, res).login()
  }
});

server.listen(8000)

class Main
{
  constructor(req, res)
  {
    this.req = req;
    this.res = res;
    
    if(true && this.req.url != "/login")
    //   ^ not important variable
    {
      this.res.statusCode = 302;
      this.res.setHeader('Location', '/login')
      this.res.end()
    }
  }
  index()
  {
    this.res.statusCode = 200;
    this.res.setHeader('Content-Type', 'text/plain');
    this.res.write('Index');
    this.res.end()
  }
  login()
  {
    this.res.statusCode = 200;
    this.res.setHeader('Content-Type', 'text/plain');
    this.res.write('Login');
    this.res.end()
  }
}

它必须检查用户是否未授权,并将其重定向到“ /登录”

但是,在重定向时会引发此错误“发送头后无法设置头”。 节点js中有重定向的inauther方法吗?

1 个答案:

答案 0 :(得分:0)

那是因为您多次将响应发送回给呼叫者。为了易于理解,我们举个例子:

function main() {
    ...statement1;
     return true;  // Will return when reach here
    // Will never reach hear as already returned;
    ...statement2;
    return false; // Since already returned thus will never come here;
}

这是自我解释,声明2永远不会达到已返回的状态。让我们使用res函数代替return:

function main() {
    ...statement1;
    res.send(true);  // Will call function res.send() and continue processing
    // Will be here as function didn't returned and thus after calling one function main function continue execution
    ...statement2;
    res.send(false); // will call another function
}

由于res.send(),res.write(),res.end()和其他res函数只是函数调用,因此执行不会停止并继续调用。但是res.send()res.end()res.json()都终止了来自请求源的连接,并将响应发送回请求源。因此,再次调用这些函数将产生错误,因为连接已经关闭并且响应已发送回请求,并且一旦发送就无法更改一个响应。

为什么在代码中发生这种情况是由于发送回响应并在构造函数中终止与请求源的连接,然后尝试将另一个响应发送回关闭的连接。

class Main
{
  constructor(req, res)
  {
    this.req = req;
    this.res = res;

    if(true && this.req.url != "/login")
    //   ^ not important variable
    {
      this.res.statusCode = 302;
      this.res.setHeader('Location', '/login')
      this.res.end() // Response is send back and ended connection with request source.
    }
  }
  index()
  {
    this.res.statusCode = 200;
    this.res.setHeader('Content-Type', 'text/plain');
    this.res.write('Index');
    this.res.end()
  }
  login()
  {
    this.res.statusCode = 200;
    this.res.setHeader('Content-Type', 'text/plain');
    this.res.write('Login');
    this.res.end()
  }
}

在创建类的新对象时,将调用其构造函数,此处的构造函数为:

constructor(req, res)
  {
    this.req = req;
    this.res = res;

    if(true && this.req.url != "/login")
    //   ^ not important variable
    {
      this.res.statusCode = 302;
      this.res.setHeader('Location', '/login')
      this.res.end() // Response is send back and ended connection with request source.
    }
  }

如您所见,在req.url不是login的情况下,您终止了连接,因此只有在再次调用login()时才会出错,因为login()将响应发送回封闭的连接。

new Main(req, res); // Calling constructor.

new Main(req, res).login(); // Calling constructor first then calling login function

登录功能为:

  login()
  {
    this.res.statusCode = 200;
    this.res.setHeader('Content-Type', 'text/plain');
    this.res.write('Login');
    this.res.end()   // Sending response to request source
  }

要在这里解决问题,您要做的就是不要在构造函数中返回并终止连接:

class Main
{
  constructor(req, res)
  {
    this.req = req;
    this.res = res;

    if(true && this.req.url != "/login")
    //   ^ not important variable
    {
      this.res.statusCode = 302;
      this.res.setHeader('Location', '/login')
    }
  }
  index()
  {
    this.res.statusCode = 200;
    this.res.setHeader('Content-Type', 'text/plain');
    this.res.write('Index');
    this.res.end()
  }
  login()
  {
    this.res.statusCode = 200;
    this.res.setHeader('Content-Type', 'text/plain');
    this.res.write('Login');
    this.res.end()
  }
}

根据您当前的编码风格,这是一个解决方案,您应该尝试实现更好的体系结构并使用更好的框架来维护API和路由。