【问题标题】:Form submission to Mailchimp using Vue.js and Axios results in CORS error使用 Vue.js 和 Axios 向 Mailchimp 提交表单会导致 CORS 错误
【发布时间】:2018-07-20 11:35:20
【问题描述】:

我的 Vue.js 应用程序中有一个组件,它使用 Axios 将电子邮件从表单提交到 Mailchimp。

我已经读到要绕过 Mailchimp 的帖子 URL 中的 CORS,我需要使用 post-json 版本并将 &c=? 添加到 URL 的末尾。我还将我的请求方法从 POST 更新为 GET 并序列化了我的表单输入。

Component.vue

<mailchimp-subscribe action="https://example.us15.list-manage.com/subscribe/
post-json?u=xxx&amp;id=xxx&amp;c=?"></mailchimp-subscribe>

MailchimpSubscribe.vue

<template>
  <form @submit.prevent="subscribe">
    <input v-model="email" type="email" name="EMAIL" value="" placeholder="Email Address" required>
    <input class="button" type="submit" value="Subscribe">
  </form>
</template>

<script>
  import axios from 'axios'

  export default {
    name: 'MailchimpSubscribe',
    props: {
      action: {}
    },
    data: () => ({
      email: '',
      response: {}
    }),
    methods: {
      subscribe: function (event) {
        axios({
          method: 'get',
          url: this.action,
          data: JSON.stringify(this.email),
          cache: false,
          dataType: 'json',
          contentType: 'application/json; charset=utf-8'
        })
        .then(response => {
          console.log(response)
        })
        .catch(error => {
          console.log(error)
        })
      }
    }
  }
</script>

使用上面的代码,我仍然得到以下错误:

无法加载https://example.us15.list-manage.com/subscribe/post-json?u=xxx&id=xxx&c=?:请求的资源上不存在“Access-Control-Allow-Origin”标头。 Origin 'http://localhost:8080' 因此不允许访问。

有没有我遗漏的步骤?

【问题讨论】:

  • 不,没有任何遗漏。将 URL 提交到您的服务器,然后使用服务器端 HTTP 客户端将请求发布到 Mailchimp。不能这样做。
  • @Ohgodwhy 你知道为什么它不再可能这样吗?我看过一些通过 $.ajax 提交到 mailchimp 的例子,我很好奇为什么我不能对 axios 做同样的事情。
  • @cul8r 因为$.ajax 支持jsonp (like this answer) 和axios does not support jsonp

标签: json forms vue.js axios mailchimp


【解决方案1】:

您的服务器(后端)必须使用完全相同的标头进行响应。

即:https://developer.mozilla.org/ru/docs/Web/HTTP/Headers/Access-Control-Allow-Origin

例如 Axios 获取/发布(没关系):

const configAxios = {
  headers: {
    'Content-Type': 'application/json',
  },
};
axios.post('api/categories', configAxios)
  .then((res) => {
    this.categories = res.data;
    console.log(res);
  })
  .catch((err) => {
    console.warn('error during http call', err);
  });

例如服务器端。我喜欢 Symfony4,它被使用了NelmioCorsBundle,看看allow_origin: ['*']。如果你使用 Symfony,这很简单。

nelmio_cors:
    defaults:
        allow_credentials: false
        allow_origin: ['*']
        allow_headers: ['Content-Type']
        allow_methods: []
        expose_headers: []
        max_age: 0
        hosts: []
        origin_regex: false
        forced_allow_origin_value: ~
    paths:
        '^/api/':
            allow_origin: ['*']
            allow_headers: ['X-Custom-Auth', 'Content-Type', 'Authorization']
            allow_methods: ['POST', 'PUT', 'GET', 'DELETE']
            max_age: 3600
        '^/':
            origin_regex: true
            allow_origin: ['^http://localhost:[0-9]+']
            allow_headers: ['X-Custom-Auth', 'Content-Type']
            allow_methods: ['POST', 'PUT', 'GET', 'DELETE']
            max_age: 3600
            hosts: ['^api\.']

如果您不直接使用服务器,请咨询您的供应商以了解此细微差别。

这个标头也可以通过例如 Nginx 传输,这不是最好的主意。

例如,看看:

add_header Access-Control-Allow-Origin *;

server {
    listen 8080;
    server_name site.local;
    root /var/www/site/public;

    location / {
	      add_header Access-Control-Allow-Origin *;

        # try to serve file directly, fallback to index.php
        try_files $uri /index.php$is_args$args;	
    }

    location ~ ^/index\.php(/|$) {
        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        # When you are using symlinks to link the document root to the
        # current version of your application, you should pass the real
        # application path instead of the path to the symlink to PHP
        # FPM.
        # Otherwise, PHP's OPcache may not properly detect changes to
        # your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
        # for more information).
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        # Prevents URIs that include the front controller. This will 404:
        # http://domain.tld/index.php/some-path
        # Remove the internal directive to allow URIs like this
        internal;
    }

    # return 404 for all other php files not matching the front controller
    # this prevents access to other php files you don't want to be accessible.
    location ~ \.php$ {
        return 404;
    }

    error_log /var/log/nginx/project_error.log;
    access_log /var/log/nginx/project_access.log;
}

值得注意的是,如果没有数据传递它会删除 Content-Type。数据必须始终传输或为null。这很奇怪,而且具有误导性。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 2020-03-05
    • 2018-08-16
    • 1970-01-01
    • 2020-03-08
    • 2011-03-19
    • 1970-01-01
    相关资源
    最近更新 更多