javascript - API 调用在 Angular 4 上不起作用。没有 'Access-Control-Allow-Origin' header ,400

标签 javascript node.js angular express cors

我的票务系统有问题。帖子票可以用,但评论票不行。 错误: 加载失败http://localhost:3977/api/tickets/comment :请求的资源上不存在“Access-Control-Allow-Origin” header 。来源'http://localhost:4200 ' 因此不允许访问。响应的 HTTP 状态代码为 400。

遵循代码: 前端:

// Function to create new ticket form
  createNewTicketForm() {
    this.form = this.formBuilder.group({
      // Title field
      title: ['', Validators.compose([
        Validators.required,
        Validators.maxLength(50),
        Validators.minLength(5),
        this.alphaNumericValidation
      ])],
      // Body field
      body: ['', Validators.compose([
        Validators.required,
        Validators.maxLength(500),
        Validators.minLength(5)
      ])]
    })
  }

  // Create form for posting comments
  createCommentForm() {
    this.commentForm = this.formBuilder.group({
      comment: ['', Validators.compose([
        Validators.required,
        Validators.minLength(1),
        Validators.maxLength(200)
      ])]
    })
  }

   // Enable the comment form
  enableCommentForm() {
    this.commentForm.get('comment').enable(); // Enable comment field
  }

  // Disable the comment form
  disableCommentForm() {
    this.commentForm.get('comment').disable(); // Disable comment field
  }
  // Enable new ticket form
  enableFormNewTicketForm() {
    this.form.get('title').enable(); // Enable title field
    this.form.get('body').enable(); // Enable body field
  }

  // Disable new ticket form
  disableFormNewTicketForm() {
    this.form.get('title').disable(); // Disable title field
    this.form.get('body').disable(); // Disable body field
  }

  // Validation for title
  alphaNumericValidation(controls) {
    const regExp = new RegExp(/^[a-zA-Z0-9 ]+$/); // Regular expression to perform test
    // Check if test returns false or true
    if (regExp.test(controls.value)) {
      return null; // Return valid
    } else {
      return { 'alphaNumericValidation': true } // Return error in validation
    }
  }

  // Function to display new ticket form
  newTicketForm() {
    this.newPost = true; // Show new ticket form
  }

  // Reload tickets on current page
  reloadTickets() {
    this.loadingTickets = true; // Used to lock button
    this.getTickets(); // Add any new tickets to the page
    setTimeout(() => {
      this.loadingTickets = false; // Release button lock after four seconds
    }, 4000);
  }

  // Function to post a new comment on ticket post
  draftComment(id) {
 this.commentForm.reset(); // Reset the comment form each time users starts a new comment
    this.newComment = []; // Clear array so only one post can be commented on at a time
    this.newComment.push(id); // Add the post that is being commented on to the array

  }

  // Function to submit a new ticket post
  onTicketSubmit() {
    this.processing = true; // Disable submit button
    this.disableFormNewTicketForm(); // Lock form

    // Create ticket object from form fields
    const ticket = {
     title: this.form.get('title').value, // Title field
      body: this.form.get('body').value, // Body field
      createdBy: this.username // CreatedBy field
    }

    // Function to save ticket into database
    this._ticketService.newTicket(this.token, ticket ).subscribe(data => {
      // Check if ticket was saved to database or not
      if (!data.success) {
        this.messageClass = 'alert alert-danger'; // Return error class
        this.message = data.message; // Return error message
        this.processing = false; // Enable submit button
        this.enableFormNewTicketForm(); // Enable form
      } else {
        this.messageClass = 'alert alert-success'; // Return success class
        this.message = data.message; // Return success message
        this.getTickets();
        // Clear form data after two seconds
        setTimeout(() => {
          this.newPost = false; // Hide form
          this.processing = false; // Enable submit button
          this.message = false; // Erase error/success message
          this.form.reset(); // Reset all form fields
          this.enableFormNewTicketForm(); // Enable the form fields
        }, 2000);
      }
    });
  }

  // Function to go back to previous page
  goBack() {
    window.location.reload(); // Clear all variable states
  }

  // Function to get all tickets from the database
  getTickets() {
    // Function to GET all tickets from database
    this._ticketService.getTickets(this.token).subscribe(data => {
      this.ticketPosts = data.tickets; // Assign array to use in HTML
    });
  }
// Function to post a new comment
  postComment(id) {
    this.disableCommentForm(); // Disable form while saving comment to database
    this.processing = true; // Lock buttons while saving comment to database
    const comment = this.commentForm.get('comment').value; // Get the comment value to pass to service function
    // Function to save the comment to the database
      this._ticketService.postComment(this.token, comment).subscribe(data => {
      this.getTickets(); // Refresh all tickets to reflect the new comment
      const index = this.newComment.indexOf(id); // Get the index of the ticket id to remove from array
      this.newComment.splice(index, 1); // Remove id from the array
      this.enableCommentForm(); // Re-enable the form
      this.commentForm.reset(); // Reset the comment form
      this.processing = false; // Unlock buttons on comment form
      if (this.enabledComments.indexOf(id) < 0) this.expand(id); // Expand comments for user on comment submission
    
    });
  }

后端:

function saveTicket(req, res){
	if (!req.body.title) {
      res.json({ success: false, message: 'Ticket title is required.' }); // Return error message
    } else {
      // Check if ticket body was provided
      if (!req.body.body) {
        res.json({ success: false, message: 'Ticket body is required.' }); // Return error message
      } else {
       
          // Create the ticket object for insertion into database
          const ticket = new Ticket({
            title: req.body.title, // Title field
            body: req.body.body, // Body field
            createdBy: req.body.createdBy // CreatedBy field
          });
          ticket.save((err, ticketStored) => {
            // Check if error
            if (err) {
              // Check if error is a validation error
              if (err.errors) {
                // Check if validation error is in the title field
                if (err.errors.title) {
                  res.json({ success: false, message: err.errors.title.message }); // Return error message
                } else {
                  // Check if validation error is in the body field
                  if (err.errors.body) {
                    res.json({ success: false, message: err.errors.body.message }); // Return error message
                  } else {
                    res.json({ success: false, message: err }); // Return general error message
                  }
                }
              } else {
                res.json({ success: false, message: err }); // Return general error message
              }
            } else {
              res.json({ success: true, message: 'Ticket Salvo' }); // Return success message
            }
          });
        }
      }
    
};
function saveComment(req, res){
	// Check if comment was provided in request body
    if (!req.body.comment) {
      res.json({ success: false, message: 'No comment provided' }); // Return error message
    } else {
      // Check if id was provided in request body
      if (!req.body.id) {
        res.json({ success: false, message: 'No id was provided' }); // Return error message
      } else {
        // Use id to search for ticket post in database
        Ticket.findOne({ _id: req.body.id }, (err, ticket) => {
          // Check if error was found
          if (err) {
            res.json({ success: false, message: 'Invalid ticket id' }); // Return error message
          } else {
            // Check if id matched the id of any ticket post in the database
            if (!ticket) {
              res.json({ success: false, message: 'Ticket not found.' }); // Return error message
            } else {
              // Grab data of user that is logged in
              User.findOne({ _id: req.decoded.userId }, (err, user) => {
                // Check if error was found
                if (err) {
                  res.json({ success: false, message: 'Something went wrong' }); // Return error message
                } else {
                  // Check if user was found in the database
                  if (!user) {
                    res.json({ success: false, message: 'User not found.' }); // Return error message
                  } else {
                    // Add the new comment to the ticket post's array
                    ticket.comments.push({
                      comment: req.body.comment, // Comment field
                      commentator: user.username // Person who commented
                    });
                    // Save ticket post
                    ticket.save((err, ticketStored) => {
                      // Check if error was found
                      if (err) {
                        res.json({ success: false, message: 'Something went wrong.' }); // Return error message
                      } else {
                        res.json({ success: true, message: 'Comment saved' }); // Return success message
                      }
                    });
                  }
                }
              });
            }
          }
        });
      }
    }
  };
  
  Routes:
  api.post('/ticket', md_auth.ensureAuth, TicketController.saveTicket);
api.post('/tickets/comment/', md_auth.ensureAuth, TicketController.saveComment);

有人帮我吗? 桑塔纳·马科斯·拉加兹

最佳答案

看起来像是一个常见的 CORS 问题。如果您使用 Angular CLI(我猜是这样),那么您可能需要为从 dev-server 4200 端口到 api-server 3977 端口的 api 请求配置代理。官方文档是here 。按照它创建适当的配置文件,并将 --proxy-config 选项设置为 npm ngserve 脚本:

proxy.conf.json

{
  "/api": {
     "target": "http://localhost:3977",
     "secure": false
  }
}

package.json

"start": "ng serve --proxy-config proxy.conf.json"

来自前端(TicketService)的请求应如下所示

this.http.post('/api/tickets/comment', ...

以及后端的处理

api.post('/api/tickets/comment', ...

关于javascript - API 调用在 Angular 4 上不起作用。没有 'Access-Control-Allow-Origin' header ,400,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46737222/

相关文章:

javascript - 使用 jQuery 将表情符号插入 div 中

javascript - 如果表单中的任何输入或选择为空,如何删除表行?

javascript - 有没有办法获取 Javascript 和 JQuery 值并将它们导出为 PDF?

node.js - 如何避免在 MongoDB 中使用 db.insertMany() 在集合中插入重复值?

angular - 如何在 Angular2 中的模块加载时实例化单例服务

angular - 无法使用angular 4使用ng bootstrap modal获取多参数值

javascript - AngularJS 使用 $timeout 给出未定义的错误

angularjs - 未知错误 : Permission denied to access property "__raven__"

javascript - 云功能 |登录 Firebase 并返回访问 token

angular - 隐藏像 ngIf 这样的 Angular 2 Material 工具提示