3

我有一个页面,用于amp-list使用 JSON 文件动态列出产品。我的目录结构如下:*root*/amp/product-name/然后在product-name目录中我有一个index.html带有 AMP HTML 和一个products.json包含我在页面上显示的产品数据的目录。如果我直接访问该页面,一切都会按预期工作: https ://example.com/amp/product-name/

当我从 ampproject.org CDN 访问时,问题就出现了。

这是实际页面,如果您访问控制台,您会看到 CORS 错误。我该如何处理?文档不清楚如何准确处理,只是一个非常模糊的概述,所以对于新手来说这对我来说没有意义,我不能凭直觉知道如何去做。我知道我需要某种类型的请求处理程序,这部分是通过从 AMP 自己的 app.js 中复制代码来完成的,它们链接到他们的文档中。内amp-list我之前让 src 直接指向 JSON 文件的元素中,但现在我看到我需要指向一个处理程序(如 JS 文件),然后让处理程序设置请求标头,然后输出正确的 JSON .

这是我为请求处理程序提供的内容:

/**
 * @param {string} url
 * @param {string} param
 * @param {*} value
 * @return {string}
 */
function addQueryParam(url, param, value) {
  const paramValue = encodeURIComponent(param) + '=' + encodeURIComponent(value);
  if (!url.includes('?')) {
    url += '?' + paramValue;
  } else {
    url += '&' + paramValue;
  }
  return url;
}

function enableCors(req, res, origin, opt_exposeHeaders) {
  res.setHeader('Access-Control-Allow-Credentials', 'true');
  res.setHeader('Access-Control-Allow-Origin', origin);
  res.setHeader('Access-Control-Allow-Origin', 'https://www-perfectimprints-com.cdn.ampproject.org');
  res.setHeader('Access-Control-Expose-Headers', ['AMP-Access-Control-Allow-Source-Origin'].concat(opt_exposeHeaders || []).join(', '));
  if (req.query.__amp_source_origin) {
    res.setHeader('AMP-Access-Control-Allow-Source-Origin', req.query.__amp_source_origin);
  }
}

function assertCors(req, res, opt_validMethods, opt_exposeHeaders, opt_ignoreMissingSourceOrigin) {
  // Allow disable CORS check (iframe fixtures have origin 'about:srcdoc').
  if (req.query.cors == '0') {
    return;
  }
  const validMethods = opt_validMethods || ['GET', 'POST', 'OPTIONS'];
  const invalidMethod = req.method + ' method is not allowed. Use POST.';
  const invalidOrigin = 'Origin header is invalid.';
  const invalidSourceOrigin = '__amp_source_origin parameter is invalid.';
  const unauthorized = 'Unauthorized Request';
  let origin;
  if (validMethods.indexOf(req.method) == -1) {
    res.statusCode = 405;
    res.end(JSON.stringify({
      message: invalidMethod
    }));
    throw invalidMethod;
  }
  if (req.headers.origin) {
    origin = req.headers.origin;
    if (!ORIGIN_REGEX.test(req.headers.origin)) {
      res.statusCode = 500;
      res.end(JSON.stringify({
        message: invalidOrigin
      }));
      throw invalidOrigin;
    }
    if (!opt_ignoreMissingSourceOrigin && !SOURCE_ORIGIN_REGEX.test(req.query.__amp_source_origin)) {
      res.statusCode = 500;
      res.end(JSON.stringify({
        message: invalidSourceOrigin
      }));
      throw invalidSourceOrigin;
    }
  } else if (req.headers['amp-same-origin'] == 'true') {
    origin = getUrlPrefix(req);
  } else {
    res.statusCode = 401;
    res.end(JSON.stringify({
      message: unauthorized
    }));
    throw unauthorized;
  }
  enableCors(req, res, origin, opt_exposeHeaders);
}

这就是我用于 HTML 的内容。

<amp-list credentials="include" width="auto" height="1500" layout="fixed-height" src="https://perfectimprints.com/amp/handle-amp-requests.js" class="m1">
      <template type="amp-mustache" id="amp-template-id">
        <div class="product" style="padding-top: 1em;">
          <a class="wrapper-link" href="{{ link }}">
            <amp-img alt="{{ title }}" width="1000" height="1000" src="{{ src }}" layout="responsive"></amp-img>
            <h3 class="product-name text-centered">
              {{title}}
            </h3>
            <h4 class="text-centered sku margin-minus-1">{{ sku }}</h4>
            <div class="text-centered get-price">
              <a class="text-centered get-price-link" href="{{ link }}">Get pricing now</a>
            </div>
          </a>
        </div>
      </template>
      <div overflow role="button" aria-label="Show more">
        Show more
       </div>
    </amp-list>

https://www-perfectimprints-com.cdn.ampproject.org/c/s/www.perfectimprints.com/amp/trick-or-treat-bags/index.html

4

3 回答 3

5

这是对我有用的解决方案。

Header set Access-Control-Allow-Credentials "true"
Header set Access-Control-Allow-Origin "https://example-com.cdn.ampproject.org"
Header set Access-Control-Allow-Source-Origin "https://example.com"
Header set Access-Control-Expose-Headers AMP-Access-Control-Allow-Source-Origin
Header set AMP-Access-Control-Allow-Source-Origin "https://example.com"

感谢@Craig Scott 提示帮助我解决问题。

不幸的是,处理 AMP 页面的可怜、缺乏经验的人。

于 2018-08-25T04:05:38.073 回答
1

假设您在 Apache 服务器上,您可以在 htaccess 文件中设置 CORS 标头,如下所示:

Header set Access-Control-Allow-Origin "https://www-perfectimprints-com.cdn.ampproject.org"
Header set Access-Control-Allow-Origin "https://www-perfectimprints-com.amp.cloudflare.com"

然后确保您的 htaccess 文件已上传到包含您的网站 HTML 的目录。这就是它在我管理的网站上的设置方式,一切都对我们有用。

于 2018-08-24T19:01:16.057 回答
0

对于使用 nodejs 的人,语法如下:

        res.set('AMP-Redirect-To', encodedUrl);
        res.set('Access-Control-Allow-Origin', websiteHostname);
        res.set('AMP-Access-Control-Allow-Source-Origin', websiteHostname);
        res.set('Access-Control-Expose-Headers', [
            'AMP-Access-Control-Allow-Source-Origin',
            'AMP-Redirect-To',
        ]);
        res.set('Access-Control-Allow-Credentials', 'true');

ِ另一种解决方案是使用该amp-toolbox-cors库并将其verifyOrigin选项设置为false.

import ampCors from 'amp-toolbox-cors';

app.use(
    ampCors({
        verifyOrigin: false,
    }),
);

请注意,所有来源都是这样允许的。实际上,您应该只允许两个。

希望它可以节省将来某人的时间!

于 2021-10-04T07:05:33.493 回答