Http POST-запрос из приложения Angular 6 с использованием Sendgrid и NodeJs Google Cloud Function - Ошибка 405 - PullRequest
0 голосов
/ 21 декабря 2018

Я пытаюсь увидеть электронное письмо с использованием Sendgrid из приложения Angular 6 с минимальной полезной нагрузкой.Используя функцию Google Cloud при отправке запроса, я получаю сообщение об ошибке 405 из браузера:

https://MyCloudFunctions/httpEmail 405

Доступ к XMLHttpRequest по адресу https://MyCloudFunctions/httpEmail' from origin 'http://localhost:4200' заблокировано политикой CORS: Ответ на запрос предполетной проверки не проходит проверку контроля доступа: в запрошенном ресурсе отсутствует заголовок' Access-Control-Allow-Origin '.

Журнал облачных функций показывает:

Ошибка: только запросы POST принимаются на Promise.resolve.then (/user_code/index.js:26:23) в process._tickDomainCallback(internal / process / next_tick.js: 135: 7)

Код функции облака

const sendgrid = require('sendgrid');
const client = sendgrid("MyAPI_KEY");

function parseBody(body) {
  var helper = sendgrid.mail;
  var fromEmail = new helper.Email(body.from);
  var toEmail = new helper.Email(body.to);
  var subject = body.subject;
  var content = new helper.Content('text/html', body.content);
  var mail = new helper.Mail(fromEmail, subject, toEmail, content);
  return  mail.toJSON();
}

exports.sendgridEmail = (req, res) => {
    res.setHeader("Access-Control-Allow-Origin", "*");
    res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    res.setHeader("Content-Type", "application/json");
  return Promise.resolve()
    .then(() => {
      if (req.method !== 'POST') {
        const error = new Error('Only POST requests are accepted');
        error.code = 405;
        throw error;
      }

      // Build the SendGrid request to send email
      const request = client.emptyRequest({
        method: 'POST',
        path: '/v3/mail/send',
        body: getPayload(req.body),
      });

      // Make the request to SendGrid's API
      console.log(`Sending email to: ${req.body.to}`);
      return client.API(request);
    })
    .then(response => {
      if (response.statusCode < 200 || response.statusCode >= 400) {
        const error = Error(response.body);
        error.code = response.statusCode;
        throw error;
      }

      console.log(`Email sent to: ${req.body.to}`);

      // Forward the response back to the requester
      res.status(response.statusCode);
      if (response.headers['content-type']) {
        res.set('content-type', response.headers['content-type']);
      }
      if (response.headers['content-length']) {
        res.set('content-length', response.headers['content-length']);
      }
      if (response.body) {
        res.send(response.body);
      } else {
        res.end();
      }
    })
    .catch(err => {
      console.error(err);
      const code =
        err.code || (err.response ? err.response.statusCode : 500) || 500;
      res.status(code).send(err);
      return Promise.reject(err);
    });
}

** Обновление: упрощенный файл TS ** угловой файл TS

    import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';
import { Router } from '@angular/router';

@Component({
  selector: 'app-contact',
  templateUrl: './contact.component.html',
  styleUrls: ['./contact.component.css']
})
export class ContactComponent implements OnInit {

  //constructor(private sendgridService: SendgridService){}
  constructor(private _http: HttpClient, private router: Router) { }
  ngOnInit() { }

  sendEmail() {

    let url = `https://us-central1-probalance-214005.cloudfunctions.net/httpEmail?sg_key=MY_API_KEY`
    let body = {
      "personalizations": [
        {
          "to": [
            {
              "email": "myemail@example.com",
              "name": "Postman"
            }
          ],
          "subject": "Success"
        }
      ],
      "from": {
        "email": "myemail2@example.com",
        "name": "Angular App"
      },
      "reply_to": {
        "email": "myemail@example.com",
        "name": "Test"
      },
      "content": [
        {
          "type": "text/plain",
          "value": "Request Successful 001!"
        }
      ]
    };

    let httpOptions = {
      headers: new HttpHeaders({
        'Content-Type': 'application/json',
      })
    };
    console.log("Payload:")
    console.log(url)
    console.log(body);
    console.log(httpOptions.headers)

    return this._http.post(url, body, httpOptions)
      .toPromise()
      .then(res => {
        console.log(res)
      })
      .catch(err => {
        console.log(err)
      })

  }
}

угловой файл HTML

<button type="submit" id="submit" class="btn btn-primary (click)="sendEmail()">Sendgrid </button>

1 Ответ

0 голосов
/ 07 января 2019

Несколько вещей:

  • Access-Control-Allow-Origin - заголовок ответа.Таким образом, это должно быть установлено в коде сервера, а не в коде клиента, написанном на Angular.
  • Поскольку вы установили Content-Type, браузер отправляет запрос OPTIONS вместо POST.Поэтому убедитесь, что тип запроса OPTIONS включен, а Content-Type разрешен в Access-Control-Allow-Headers на сервере.

Подробнее о проблеме CORS можно узнать здесь: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

...