Javascript Angular2:对节点服务器的PUT请求不起作用-身份验证丢失

Javascript Angular2:对节点服务器的PUT请求不起作用-身份验证丢失,javascript,node.js,angular,authentication,server,Javascript,Node.js,Angular,Authentication,Server,我在客户端使用Angular2,在后端使用node express服务器。节点服务器用作API中间件,也用作我的身份验证服务。用户请求必须包含有效的JWT令牌才能在节点服务器上执行请求 我所有的GET函数和其他PUT函数都工作正常。我写了一个新的,它应该删除第三方API上的ID,但没有 此外,我的node express服务器在某些点向客户端发送自定义错误消息。这就是我的问题所在,每当我运行最新的PUT函数时,我的服务器都会响应而不提供令牌。当用户未在客户端登录时会发生这种情况 正如我所说,我的

我在客户端使用Angular2,在后端使用node express服务器。节点服务器用作API中间件,也用作我的身份验证服务。用户请求必须包含有效的JWT令牌才能在节点服务器上执行请求

我所有的GET函数和其他PUT函数都工作正常。我写了一个新的,它应该删除第三方API上的ID,但没有

此外,我的node express服务器在某些点向客户端发送自定义错误消息。这就是我的问题所在,每当我运行最新的PUT函数时,我的服务器都会响应而不提供令牌。当用户未在客户端登录时会发生这种情况

正如我所说,我的所有其他功能都正常工作。this.createAuthenticationHeaders;是在服务器端执行有效请求所必需的。但它已经实现了

换句话说,客户端和服务器之间的身份验证会丢失,我会收到自己的错误消息:没有提供令牌

Appointment-Detail.Component.ts

API服务

一个API服务可以工作

到第三方API的服务器路由

认证中间件


在没有深入研究您的auth头的情况下,我看到了一个非常明显的问题,我认为这可能是您遇到麻烦的原因

HTTP REST动词具有不同的意图,在本例中,我们特别关心的意图是您的请求是否应该有一个主体

获取请求时不要随身携带尸体

把请求放在身上

因此,angular的HttpClient请求方法http.get、http.post等具有不同的方法签名

切中要害的是,http.put的方法签名接受3个参数:url、body和options,而http.get的方法签名只接受2:url和options

如果您看一下您的示例,对于http.put,您提供了this.httpOptions作为第二个参数,而不是第三个参数,因此Angular将您的options对象打包为put请求主体。这就是为什么你有一个工作示例和一个非工作示例;工作示例是一个GET

解决方案是什么?只需在第二个参数中放入其他内容作为请求主体,然后将this.options向下移动到第三个参数槽中。如果您不关心它是什么,只需使用空对象:{}

因此,您的请求应该如下所示:

返回此文件。http .putthis.domain+'api/appoints/'+id+'/cancel',{},this.options 至少,这应该将this.options中的内容正确地发送到服务器。现在,选项中的内容是否正确是另一回事了


Angular的文档中的PUT调用示例:

导致错误!谢谢你的解释,对我来说很有意义
cancelAppointment() {
    this.authService.getProfile().subscribe(profile => {
      this.username = profile.user.username; // Set username
      this.email = profile.user.email; // Set e-mail
      if (profile.user.email) {
        this.apiService.cancelUserAppointment(this.id).subscribe(data => {
          console.log(this.id);
          if (!data.success) {
            this.messageClass = 'alert alert-danger'; // Set error bootstrap class
            this.message = data.message; // Set error message
          } else {
            this.messageClass = 'alert alert-success'; // Set success bootstrap class
            this.message = data.message; // Set success message
            // After two seconds, navigate back to blog page
          }
        });
      }
    });
  }
cancelUserAppointment(id) {
    this.createAuthenticationHeaders();
    console.log('API SERVICE ' + id);
    return this.http
      .put(this.domain + 'api/appointments/' + id + '/cancel', this.options)
      .map(res => res.json());
  }
getCertificatesByUser(email) {
    this.createAuthenticationHeaders();
    return this.http
      .get(this.domain + 'api/user/' + email + '/certificates', this.options)
      .map(res => res.json());
  }
  router.put('/appointments/:id/cancel', (req, res) => {
    console.log('hi');
    var id = req.params.id;
    const url = process.env.acuityUri + '/appointments/' + id + '/cancel';
    console.log(id);
  });
router.use((req, res, next) => {
    const token = req.headers['authorization']; // Create token found in headers
    // Check if token was found in headers
    if (!token) {
      res.json({
        success: false,
        message: 'No token provided'
      }); // Return error
    } else {
      // Verify the token is valid
      jwt.verify(token, config.secret, (err, decoded) => {
        // Check if error is expired or invalid
        if (err) {
          res.json({
            success: false,
            message: 'Token invalid: ' + err
          }); // Return error for token validation
        } else {
          req.decoded = decoded; // Create global variable to use in any request beyond
          next(); // Exit middleware
        }
      });
    }
  });