如何在无头 wordpress 环境中确保图像请求的 CORS?

Posted

技术标签:

【中文标题】如何在无头 wordpress 环境中确保图像请求的 CORS?【英文标题】:How do I ensure CORS for image requests in a headless wordpress env? 【发布时间】:2019-04-03 23:35:45 【问题描述】:

从 Headless Wordpress Starter Kit 开始,我从 Wordpress 媒体库中获取两张图片,并将它们绘制到 html5 画布元素上,我需要人们能够将其保存为图片。

由于头部的域与背部的域不同,我会得到污染的跨域请求的错误。所以我将crossOrigin 设置为anonymous。这是我将图像绘制到画布的代码。

徽标

const image = new Image();
image.setAttribute("crossOrigin", "anonymous");
image.width = logo[size].width;
image.height = logo[size].height;
image.src = `$logo[size].source_url`;
image.onload = () => 
  const x = (this.width - image.width) / 2;
  this._ctx.drawImage(image, x, x, image.width, image.height);
;

背景图片

const image = new Image(this.width, this.height);
image.setAttribute("crossOrigin", "anonymous");
image.src = backgroundImage[size].source_url;
image.onload = () => 
  const x = image.width / 2;
  this._ctx.drawImage(image, -x, 0);
;

服务器/后端

我没有编辑入门工具包中提供的主题设置的 CORS。

wp-content/themes/postlight-headless-wp/inc/cors.php

remove_filter( 'rest_pre_serve_request', 'rest_send_cors_headers' );

add_filter( 'rest_pre_serve_request', function ( $value ) 
    header( 'Access-Control-Allow-Origin: ' . get_frontend_origin() );
    header( 'Access-Control-Allow-Methods: GET' );
    header( 'Access-Control-Allow-Credentials: true' );
    return $value;
);

我认为由于我是直接请求文件,因此服务器不应调用此脚本。

相反,我设置了几个 docker 容器来运行灯堆栈。这是docker-compose.yaml

version: "2"

services:
  db:
    container_name: database
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    ports: # Set up ports exposed for other containers to connect to
      - "3306:3306"
    environment: # Set up mysql database name and password
      MYSQL_ROOT_PASSWORD: **********
      MYSQL_DATABASE: **********
      MYSQL_USER: **********
      MYSQL_PASSWORD: **********
  wordpress:
    build: .
    container_name: wordpress
    depends_on:
      - db
    ports:
      - "4000:80"
    volumes:
      - ./html:/var/www/html
    links:
      - db
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_PASSWORD: **********
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: phpmyadmin
    depends_on:
      - db
    restart: always
    ports:
      - "8080:80"
    environment:
      - PMA_ARBITRARY=1
volumes:
  db_data:

我在 html 文件夹的根目录添加了.htaccess 文件。

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %REQUEST_FILENAME !-f
RewriteCond %REQUEST_FILENAME !-d
RewriteRule . /index.php [L]
</IfModule>

<IfModule mod_setenvif.c>
  <IfModule mod_headers.c>
    <FilesMatch "\.(bmp|cur|gif|ico|jpe?g|png|svgz?|webp)$">
      SetEnvIf Origin ":" IS_CORS
      Header set Access-Control-Allow-Origin "*" env=IS_CORS
    </FilesMatch>
  </IfModule>
</IfModule>
# END WordPress

有了这一切,我希望我不会有问题。但是我在这里,我已经输入了所有这些,所以,是的,我有一个问题。背景图片可以完美运行,而徽标图片则不行。

Chrome 70 - 不。

Access to image at 'http://localhost:4000/wp-content/uploads/2018/10/paintWithNoBackground-1-150x150.png' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Safari 12 - 不。

[Error] Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin.
[Error] Cannot load image http://localhost:4000/wp-content/uploads/2018/10/paintWithNoBackground-1-150x150.png due to access control checks.
[Error] Failed to load resource: Origin http://localhost:3000 is not allowed by Access-Control-Allow-Origin. (paintWithNoBackground-1-150x150.png, line 0)

Firefox 63 - 是的,它在这里工作

No errors.

在所有浏览器中,背景图像都可以正常工作。我不知道为什么一个可以工作而另一个不行,然后为什么它可以在 Firefox 中工作,而不是 Chrome 或 Safari。如果您需要任何其他信息,请告诉我。

【问题讨论】:

方法get_frontend_origin()返回什么?您可以尝试将该标题更改为'Access-Control-Allow-Origin: "*"'。我也会考虑将OPTIONS 添加到允许的方法中。 get_frontend_origin() 返回前端的 FQDN。我会尝试你的两个建议。非常感谢。 查看 .htaccess 中设置了标头的 &lt;FilesMatch "\.(bmp|cur|gif|ico|jpe?g|png|svgz?|webp)$"&gt;,看起来您只在包含这些文件类型的响应对象上传递了 cors 标头。但选项响应也需要此标头通过飞行前。 【参考方案1】:

好的,所以我认为这是可能的。我在这里遇到的问题是..缓存。浏览器缓存了没有“origin”标头的调用,这基本上使服务器在没有 CORS 标头的情况下进行响应。见:https://***.com/a/17570351/3391743

添加后<IfModule mod_setenvif.c> <IfModule mod_headers.c> <FilesMatch "\.(bmp|cur|gif|ico|jpe?g|png|svgz?|webp)$"> SetEnvIf Origin ":" IS_CORS Header set Access-Control-Allow-Origin "*" env=IS_CORS </FilesMatch> </IfModule> </IfModule> 并清理它开始正常工作的缓存,显示图像而不污染我正在写入图像的画布。耶!

【讨论】:

【参考方案2】:

你没有。这是不可能的。两个代码库必须托管在同一个域下。我在解决这个问题几天后才这么说。

如果有人(不是我)想通了,我将不做标记。

【讨论】:

以上是关于如何在无头 wordpress 环境中确保图像请求的 CORS?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Windows 7 上关闭无头图形环境

如何删除从 wordpress 上的图像附件生成的页面?

带有反应的无头 WordPress - 后端和前端的样式古腾堡

试图让一个无头 WordPress 在纱线启动命令上进行热重载

如何允许在我的图像上查看替代文本(wordpress 主题 kallyas)

无头 cms 访问 wp-admin(nuxt.js + wordpress)