{"componentChunkName":"component---src-templates-blog-detail-tsx","path":"/blog/2018-01-16-cors-api-gateway-survival-guide","result":{"data":{"currentBlog":{"id":"5928eee6-9546-5603-ad61-a9688dbafd02","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/20191231/1577795409089-CORS_principle.png","authors":["AlexDeBrie"],"categories":["guides-and-tutorials","operations-and-observability"],"date":"2018-01-16T00:00:00.000Z","title":"生存指南之 CORS + API Gateway","description":"本文介绍了跨域资源共享的基本知识，以及如何避免云函数上 Serverless web API 的问题","authorslink":["https://serverless.com/author/alexdebrie/"],"translators":["Aceyclee"],"translatorslink":["https://www.zhihu.com/people/Aceyclee"],"tags":["CORS","API 网关"],"keywords":"CORS,API Gateway,Serverless web API","outdated":null},"wordCount":{"words":237,"sentences":40,"paragraphs":40},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-01-16-cors-api-gateway-survival-guide.md","fields":{"slug":"/blog/2018-01-16-cors-api-gateway-survival-guide/","keywords":["go","java","serverless","云函数","Access","Allow","Control","headers","product","response","event","Origin"]},"html":"<p>构建 Web API 是 Serverless 应用中最流行的用例之一，您能在不增加其他操作开销的情况下，获得简单、可扩展的后端优势。</p>\n<p>然而，如果您的网页正在调用后端 API，那么必须处理 <a href=\"https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS\">跨域资源共享 (CORS)</a> 的问题 ，如果您的网页向与您当前所在域的不同域发出 HTTP 请求，则它必须是 CORS 友好的。</p>\n<p>如果您发现以下错误：</p>\n<blockquote>\n<p>No 'Access-Control-Allow-Origin' header is present on the requested resource</p>\n</blockquote>\n<p>那么本文可能对您有所帮助。</p>\n<p>接下来，我们将介绍 Serverless + CORS 的相关信息，目录如下：</p>\n<ul>\n<li><a href=\"#cors-preflight-requests\">预检请求 (Preflight requests)</a></li>\n<li><a href=\"#cors-response-headers\">响应头 (Response headers)</a></li>\n<li><a href=\"#cors-with-cookie-credentials\">CORS with cookie credentials</a></li>\n</ul>\n<h2 id=\"tldr\"><a href=\"#tldr\" aria-label=\"tldr permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>TL;DR</h2>\n<p>快速开始 🔜 如果您想快速解决 Serverless 应用中的 CORS，可以执行以下操作：</p>\n<ol>\n<li>要处理 <a href=\"#cors-preflight-requests\">preflight requests</a>，在每个 HTTP 端点中添加 <code class=\"language-text\">enableCORS: true</code> 和  <code class=\"language-text\">integratedResponse: true</code> 标记：</li>\n</ol>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"577093050782262500\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`# serverless.yml\nservice: products-service\n\nprovider:\n  name: tencent\n  region: ap-guangzhou\n  runtime: Nodejs8.9 # Nodejs8.9 or Nodejs6.10\n\nplugins:\n  - serverless-tencent-scf\n\nfunctions:\n  getProduct:\n    handler: handler.getProduct\n    events:\n      - apigw:\n          name: api\n          parameters:\n            path: /product\n            stageName: release\n            # 修改成你的 API 服务 ID\n            serviceId: service-xxx\n            httpMethod: GET\n            # 开启集成相应，这里必须开启，才能自定义响应 headers\n            integratedResponse: true,\n            # 开启 CORS\n            enableCORS: true\n  createProduct:\n    handler: handler.createProduct\n    events:\n      - apigw:\n          name: api\n          parameters:\n            path: /product\n            stageName: release\n            # 修改成你的 API 服务 ID\n            serviceId: service-xxx\n            httpMethod: POST\n            # 开启集成相应，这里必须开启，才能自定义响应 headers\n            integratedResponse: true,\n            # 开启 CORS\n            enableCORS: false`, `577093050782262500`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"yml\"><pre class=\"language-yml\"><code class=\"language-yml\"><span class=\"token comment\"># serverless.yml</span>\n<span class=\"token key atrule\">service</span><span class=\"token punctuation\">:</span> products<span class=\"token punctuation\">-</span>service\n\n<span class=\"token key atrule\">provider</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> tencent\n  <span class=\"token key atrule\">region</span><span class=\"token punctuation\">:</span> ap<span class=\"token punctuation\">-</span>guangzhou\n  <span class=\"token key atrule\">runtime</span><span class=\"token punctuation\">:</span> Nodejs8.9 <span class=\"token comment\"># Nodejs8.9 or Nodejs6.10</span>\n\n<span class=\"token key atrule\">plugins</span><span class=\"token punctuation\">:</span>\n  <span class=\"token punctuation\">-</span> serverless<span class=\"token punctuation\">-</span>tencent<span class=\"token punctuation\">-</span>scf\n\n<span class=\"token key atrule\">functions</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">getProduct</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">handler</span><span class=\"token punctuation\">:</span> handler.getProduct\n    <span class=\"token key atrule\">events</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">apigw</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> api\n          <span class=\"token key atrule\">parameters</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">path</span><span class=\"token punctuation\">:</span> /product\n            <span class=\"token key atrule\">stageName</span><span class=\"token punctuation\">:</span> release\n            <span class=\"token comment\"># 修改成你的 API 服务 ID</span>\n            <span class=\"token key atrule\">serviceId</span><span class=\"token punctuation\">:</span> service<span class=\"token punctuation\">-</span>xxx\n            <span class=\"token key atrule\">httpMethod</span><span class=\"token punctuation\">:</span> GET\n            <span class=\"token comment\"># 开启集成相应，这里必须开启，才能自定义响应 headers</span>\n            <span class=\"token key atrule\">integratedResponse</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span><span class=\"token punctuation\">,</span>\n            <span class=\"token comment\"># 开启 CORS</span>\n            <span class=\"token key atrule\">enableCORS</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n  <span class=\"token key atrule\">createProduct</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">handler</span><span class=\"token punctuation\">:</span> handler.createProduct\n    <span class=\"token key atrule\">events</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">apigw</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> api\n          <span class=\"token key atrule\">parameters</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">path</span><span class=\"token punctuation\">:</span> /product\n            <span class=\"token key atrule\">stageName</span><span class=\"token punctuation\">:</span> release\n            <span class=\"token comment\"># 修改成你的 API 服务 ID</span>\n            <span class=\"token key atrule\">serviceId</span><span class=\"token punctuation\">:</span> service<span class=\"token punctuation\">-</span>xxx\n            <span class=\"token key atrule\">httpMethod</span><span class=\"token punctuation\">:</span> POST\n            <span class=\"token comment\"># 开启集成相应，这里必须开启，才能自定义响应 headers</span>\n            <span class=\"token key atrule\">integratedResponse</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span><span class=\"token punctuation\">,</span>\n            <span class=\"token comment\"># 开启 CORS</span>\n            <span class=\"token key atrule\">enableCORS</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span></code></pre></div>\n<ol start=\"2\">\n<li>要处理 <a href=\"#cors-response-headers\">CORS headers</a>，请在响应中返回 CORS headers。主要标头是 <code class=\"language-text\">Access-Control-Allow-Origin</code> 和 <code class=\"language-text\">Access-Control-Allow-Credentials</code>。示例如下：</li>\n</ol>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"42322916826022120000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`'use strict';\n\n// mock function\nfunction retrieveProduct(event) {\n  return {\n    id: 1,\n    name: 'good1',\n    price: 10,\n  };\n}\n\n// mock function\nfunction createProduct(event) {\n  const { queryString } = event;\n  return {\n    id: Number(queryString.id),\n    name: 'good1',\n    price: 10,\n  };\n}\n\nmodule.exports.getProduct = (event, context, callback) => {\n  const product = retrieveProduct(event);\n\n  const response = {\n    statusCode: 200,\n    headers: {\n      'Access-Control-Allow-Origin': '*',\n      'Access-Control-Allow-Credentials': true,\n    },\n    body: JSON.stringify({\n      product: product,\n    }),\n  };\n\n  callback(null, response);\n};\n\nmodule.exports.createProduct = (event, context, callback) => {\n  // Do work to create Product\n  const product = createProduct(event);\n\n  const response = {\n    statusCode: 200,\n    headers: {\n      'Access-Control-Allow-Origin': '*',\n      'Access-Control-Allow-Credentials': true,\n    },\n    body: JSON.stringify({\n      product: product,\n    }),\n  };\n\n  callback(null, response);\n};`, `42322916826022120000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token string\">'use strict'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// mock function</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">retrieveProduct</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span>\n    id<span class=\"token punctuation\">:</span> <span class=\"token number\">1</span><span class=\"token punctuation\">,</span>\n    name<span class=\"token punctuation\">:</span> <span class=\"token string\">'good1'</span><span class=\"token punctuation\">,</span>\n    price<span class=\"token punctuation\">:</span> <span class=\"token number\">10</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token comment\">// mock function</span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">createProduct</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> queryString <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> event<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span>\n    id<span class=\"token punctuation\">:</span> <span class=\"token function\">Number</span><span class=\"token punctuation\">(</span>queryString<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n    name<span class=\"token punctuation\">:</span> <span class=\"token string\">'good1'</span><span class=\"token punctuation\">,</span>\n    price<span class=\"token punctuation\">:</span> <span class=\"token number\">10</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\nmodule<span class=\"token punctuation\">.</span>exports<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">getProduct</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> product <span class=\"token operator\">=</span> <span class=\"token function\">retrieveProduct</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    statusCode<span class=\"token punctuation\">:</span> <span class=\"token number\">200</span><span class=\"token punctuation\">,</span>\n    headers<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'*'</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">'Access-Control-Allow-Credentials'</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    body<span class=\"token punctuation\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      product<span class=\"token punctuation\">:</span> product<span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> response<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span>exports<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">createProduct</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Do work to create Product</span>\n  <span class=\"token keyword\">const</span> product <span class=\"token operator\">=</span> <span class=\"token function\">createProduct</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    statusCode<span class=\"token punctuation\">:</span> <span class=\"token number\">200</span><span class=\"token punctuation\">,</span>\n    headers<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'*'</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">'Access-Control-Allow-Credentials'</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    body<span class=\"token punctuation\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      product<span class=\"token punctuation\">:</span> product<span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> response<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h2 id=\"cors-preflight-requests\"><a href=\"#cors-preflight-requests\" aria-label=\"cors preflight requests permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>CORS preflight requests</h2>\n<p>如果您不是在进行「simple request」，那么浏览器会用  <code class=\"language-text\">OPTIONS</code> 方法，发送 <strong>preflight\nrequest</strong> 到资源里，您请求的资源将使用 安全发送到资源 的方法返回，并且可以选择返回有效发送的标头。</p>\n<p>我们拆开来看看：</p>\n<h3 id=\"浏览器什么时候发送-preflight-requests\"><a href=\"#%E6%B5%8F%E8%A7%88%E5%99%A8%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E5%8F%91%E9%80%81-preflight-requests\" aria-label=\"浏览器什么时候发送 preflight requests permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>浏览器什么时候发送 preflight requests?</h3>\n<p>您的浏览器会对几乎所有的跨域请求发送一个 preflight requests。（例外是「simple requests」，但这只是请求的一小部分）。大体上看，一个简单请求只是一个 <code class=\"language-text\">GET</code> request 或者 <code class=\"language-text\">POST</code> request，如果您不在此范围内，则需要进行预检。</p>\n<h3 id=\"对-preflight-requests-的响应是什么？\"><a href=\"#%E5%AF%B9-preflight-requests-%E7%9A%84%E5%93%8D%E5%BA%94%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F\" aria-label=\"对 preflight requests 的响应是什么？ permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>对 preflight requests 的响应是什么？</h3>\n<p>对一个 preflight requests 的 响应包括其允许访问的资源，它允许在该资源的方法，如 <code class=\"language-text\">GET</code>, <code class=\"language-text\">POST</code>,\n<code class=\"language-text\">PUT</code> 等。还可以包括被允许在该资源标头，如 <code class=\"language-text\">Authentication</code>。</p>\n<h3 id=\"如何处理-serverless-中的-preflight-requests\"><a href=\"#%E5%A6%82%E4%BD%95%E5%A4%84%E7%90%86-serverless-%E4%B8%AD%E7%9A%84-preflight-requests\" aria-label=\"如何处理 serverless 中的 preflight requests permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>如何处理 Serverless 中的 preflight requests?</h3>\n<p>要设置 preflight requests，您只需要在 API Gateway 的端点上配置一个 <code class=\"language-text\">OPTIONS</code> 。幸运的是，你可以非常简单地使用 Serverless Framework 来完成。</p>\n<p>只需要在 <code class=\"language-text\">serverless.yml</code> 添加设置 <code class=\"language-text\">enableCORS: true</code>：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"53951396274905480000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`# serverless.yml\n\nservice: products-service\n\nprovider:\n  name: tencent\n  region: ap-guangzhou\n  runtime: Nodejs8.9 # Nodejs8.9 or Nodejs6.10\n\nplugins:\n  - serverless-tencent-scf\n\nfunctions:\n  getProduct:\n    handler: handler.getProduct\n    events:\n      - apigw:\n          name: api\n          parameters:\n            path: /product\n            stageName: release\n            serviceId: service-lanyfiga\n            httpMethod: GET\n            # 开启集成相应，这里必须开启，才能自定义响应 headers\n            integratedResponse: true,\n            # 开启 CORS\n            enableCORS: true\n  createProduct:\n    handler: handler.createProduct\n    events:\n      - apigw:\n          name: api\n          parameters:\n            path: /product\n            stageName: release\n            serviceId: service-lanyfiga\n            httpMethod: POST\n            # 开启集成相应，这里必须开启，才能自定义响应 headers\n            integratedResponse: true,\n            # 开启 CORS\n            enableCORS: false`, `53951396274905480000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"yml\"><pre class=\"language-yml\"><code class=\"language-yml\"><span class=\"token comment\"># serverless.yml</span>\n\n<span class=\"token key atrule\">service</span><span class=\"token punctuation\">:</span> products<span class=\"token punctuation\">-</span>service\n\n<span class=\"token key atrule\">provider</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> tencent\n  <span class=\"token key atrule\">region</span><span class=\"token punctuation\">:</span> ap<span class=\"token punctuation\">-</span>guangzhou\n  <span class=\"token key atrule\">runtime</span><span class=\"token punctuation\">:</span> Nodejs8.9 <span class=\"token comment\"># Nodejs8.9 or Nodejs6.10</span>\n\n<span class=\"token key atrule\">plugins</span><span class=\"token punctuation\">:</span>\n  <span class=\"token punctuation\">-</span> serverless<span class=\"token punctuation\">-</span>tencent<span class=\"token punctuation\">-</span>scf\n\n<span class=\"token key atrule\">functions</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">getProduct</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">handler</span><span class=\"token punctuation\">:</span> handler.getProduct\n    <span class=\"token key atrule\">events</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">apigw</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> api\n          <span class=\"token key atrule\">parameters</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">path</span><span class=\"token punctuation\">:</span> /product\n            <span class=\"token key atrule\">stageName</span><span class=\"token punctuation\">:</span> release\n            <span class=\"token key atrule\">serviceId</span><span class=\"token punctuation\">:</span> service<span class=\"token punctuation\">-</span>lanyfiga\n            <span class=\"token key atrule\">httpMethod</span><span class=\"token punctuation\">:</span> GET\n            <span class=\"token comment\"># 开启集成相应，这里必须开启，才能自定义响应 headers</span>\n            <span class=\"token key atrule\">integratedResponse</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span><span class=\"token punctuation\">,</span>\n            <span class=\"token comment\"># 开启 CORS</span>\n            <span class=\"token key atrule\">enableCORS</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span>\n  <span class=\"token key atrule\">createProduct</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">handler</span><span class=\"token punctuation\">:</span> handler.createProduct\n    <span class=\"token key atrule\">events</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token key atrule\">apigw</span><span class=\"token punctuation\">:</span>\n          <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> api\n          <span class=\"token key atrule\">parameters</span><span class=\"token punctuation\">:</span>\n            <span class=\"token key atrule\">path</span><span class=\"token punctuation\">:</span> /product\n            <span class=\"token key atrule\">stageName</span><span class=\"token punctuation\">:</span> release\n            <span class=\"token key atrule\">serviceId</span><span class=\"token punctuation\">:</span> service<span class=\"token punctuation\">-</span>lanyfiga\n            <span class=\"token key atrule\">httpMethod</span><span class=\"token punctuation\">:</span> POST\n            <span class=\"token comment\"># 开启集成相应，这里必须开启，才能自定义响应 headers</span>\n            <span class=\"token key atrule\">integratedResponse</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">true</span><span class=\"token punctuation\">,</span>\n            <span class=\"token comment\"># 开启 CORS</span>\n            <span class=\"token key atrule\">enableCORS</span><span class=\"token punctuation\">:</span> <span class=\"token boolean important\">false</span></code></pre></div>\n<h2 id=\"cors-response-headers\"><a href=\"#cors-response-headers\" aria-label=\"cors response headers permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>CORS Response Headers</h2>\n<p>尽管 preflight request 仅适用于某些跨域请求，但每个跨域请求中都必须存在 CORS Response Headers，这意味着您必须将 <code class=\"language-text\">Access-Control-Allow-Origin</code> 添加进 handlers 的响应中。</p>\n<p>如果您使用 cookies，还需要添加 <code class=\"language-text\">Access-Control-Allow-Credentials</code>。</p>\n<p>要与上面的 <code class=\"language-text\">serverless.yml</code> 匹配，<code class=\"language-text\">handler.js</code> 文件应该如下设置：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"44144032294620406000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// handler.js\n\n'use strict';\n\nmodule.exports.getProduct = (event, context, callback) => {\n  // Do work to retrieve Product\n  const product = retrieveProduct(event);\n\n  const response = {\n    statusCode: 200,\n    headers: {\n      'Access-Control-Allow-Origin': '*',\n      'Access-Control-Allow-Credentials': true,\n    },\n    body: JSON.stringify({\n      product: product,\n    }),\n  };\n\n  callback(null, response);\n};\n\nmodule.exports.createProduct = (event, context, callback) => {\n  // Do work to create Product\n  const product = createProduct(event);\n\n  const response = {\n    statusCode: 200,\n    headers: {\n      'Access-Control-Allow-Origin': '*',\n      'Access-Control-Allow-Credentials': true,\n    },\n    body: JSON.stringify({\n      product: product,\n    }),\n  };\n\n  callback(null, response);\n};`, `44144032294620406000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// handler.js</span>\n\n<span class=\"token string\">'use strict'</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span>exports<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">getProduct</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Do work to retrieve Product</span>\n  <span class=\"token keyword\">const</span> product <span class=\"token operator\">=</span> <span class=\"token function\">retrieveProduct</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    statusCode<span class=\"token punctuation\">:</span> <span class=\"token number\">200</span><span class=\"token punctuation\">,</span>\n    headers<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'*'</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">'Access-Control-Allow-Credentials'</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    body<span class=\"token punctuation\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      product<span class=\"token punctuation\">:</span> product<span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> response<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span>exports<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">createProduct</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Do work to create Product</span>\n  <span class=\"token keyword\">const</span> product <span class=\"token operator\">=</span> <span class=\"token function\">createProduct</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    statusCode<span class=\"token punctuation\">:</span> <span class=\"token number\">200</span><span class=\"token punctuation\">,</span>\n    headers<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'*'</span><span class=\"token punctuation\">,</span>\n      <span class=\"token string\">'Access-Control-Allow-Credentials'</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    body<span class=\"token punctuation\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      product<span class=\"token punctuation\">:</span> product<span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> response<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>这里需要注意 <code class=\"language-text\">response</code> 的 <code class=\"language-text\">headers</code> 属性，其中包含 <code class=\"language-text\">Access-Control-Allow-Origin</code> 和 <code class=\"language-text\">Access-Control-Allow-Credentials</code>。</p>\n<p>下面是一个简单的示例：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"52301056621546070000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// hello.js\n\nconst middy = require('middy');\nconst { cors } = require('middy/middlewares');\n\n// This is your common handler, no way different than what you are used to do every day\nconst hello = (event, context, callback) => {\n  const response = {\n    statusCode: 200,\n    body: 'Hello, world!',\n  };\n\n  return callback(null, response);\n};\n\n// Let's &quot;middyfy&quot; our handler, then we will be able to attach middlewares to it\nconst handler = middy(hello).use(cors()); // Adds CORS headers to responses\n\nmodule.exports = { handler };`, `52301056621546070000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// hello.js</span>\n\n<span class=\"token keyword\">const</span> middy <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'middy'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> <span class=\"token punctuation\">{</span> cors <span class=\"token punctuation\">}</span> <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'middy/middlewares'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// This is your common handler, no way different than what you are used to do every day</span>\n<span class=\"token keyword\">const</span> <span class=\"token function-variable function\">hello</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    statusCode<span class=\"token punctuation\">:</span> <span class=\"token number\">200</span><span class=\"token punctuation\">,</span>\n    body<span class=\"token punctuation\">:</span> <span class=\"token string\">'Hello, world!'</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> response<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token comment\">// Let's \"middyfy\" our handler, then we will be able to attach middlewares to it</span>\n<span class=\"token keyword\">const</span> handler <span class=\"token operator\">=</span> <span class=\"token function\">middy</span><span class=\"token punctuation\">(</span>hello<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">use</span><span class=\"token punctuation\">(</span><span class=\"token function\">cors</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Adds CORS headers to responses</span>\n\nmodule<span class=\"token punctuation\">.</span>exports <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> handler <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<h2 id=\"cors-with-cookie-credentials\"><a href=\"#cors-with-cookie-credentials\" aria-label=\"cors with cookie credentials permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>CORS with Cookie credentials</h2>\n<p>在上面的示例中，我们给定了 \"*\" 作为 <code class=\"language-text\">Access-Control-Allow-Origin</code> 的值。但是，如果您使用 <a href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#Requests_with_credentials\">request using credentials</a> 则不被允许。为了使浏览器能够响应，<code class=\"language-text\">Access-Control-Allow-Origin</code> 需要包含发出请求的特定来源。有两种方法可以解决。</p>\n<p>首先，如果只有一个发出请求的原始网站，则可以将其硬编码到云函数的响应中：</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"37969072983685220000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// handler.js\n\n'use strict';\n\nmodule.exports.getProduct = (event, context, callback) => {\n  // Do work to retrieve Product\n  const product = retrieveProduct(event);\n\n  const response = {\n    statusCode: 200,\n    headers: {\n      'Access-Control-Allow-Origin': 'https://myorigin.com', // <-- Add your specific origin here\n      'Access-Control-Allow-Credentials': true,\n    },\n    body: JSON.stringify({\n      product: product,\n    }),\n  };\n\n  callback(null, response);\n};`, `37969072983685220000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// handler.js</span>\n\n<span class=\"token string\">'use strict'</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span>exports<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">getProduct</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Do work to retrieve Product</span>\n  <span class=\"token keyword\">const</span> product <span class=\"token operator\">=</span> <span class=\"token function\">retrieveProduct</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    statusCode<span class=\"token punctuation\">:</span> <span class=\"token number\">200</span><span class=\"token punctuation\">,</span>\n    headers<span class=\"token punctuation\">:</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'https://myorigin.com'</span><span class=\"token punctuation\">,</span> <span class=\"token comment\">// &lt;-- Add your specific origin here</span>\n      <span class=\"token string\">'Access-Control-Allow-Credentials'</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n    body<span class=\"token punctuation\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      product<span class=\"token punctuation\">:</span> product<span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> response<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>如果有多个原始网站使用您的 API，那么需要采用一种更加动态的方法。你可以检查 <code class=\"language-text\">origin</code> header 看看是否在被批准的来源列表中，如果是，则在 <code class=\"language-text\">Access-Control-Allow-Origin</code> 返回原点值。</p>\n<div\n              class=\"gatsby-code-button-container\"\n              data-toaster-id=\"9954468033366438000\"\n              data-toaster-class=\"gatsby-code-button-toaster\"\n              data-toaster-text-class=\"gatsby-code-button-toaster-text\"\n              data-toaster-text=\"代码复制成功\"\n              data-toaster-duration=\"3500\"\n              onClick=\"copyToClipboard(`// handler.js\n\n'use strict';\n\nconst ALLOWED_ORIGINS = [\n\t'https://myfirstorigin.com',\n\t'https://mysecondorigin.com'\n];\n\nmodule.exports.getProduct = (event, context, callback) => {\n\n  const origin = event.headers.origin;\n  let headers;\n\n  if (ALLOWED_ORIGINS.includes(origin) {\n    headers = {\n      'Access-Control-Allow-Origin': origin,\n      'Access-Control-Allow-Credentials': true,\n    },\n  } else {\n    headers = {\n      'Access-Control-Allow-Origin': '*',\n    },\n  }\n\n  // Do work to retrieve Product\n  const product = retrieveProduct(event);\n\n  const response = {\n    isBase64Encoded: false,\n    statusCode: 200,\n    headers\n    body: JSON.stringify({\n      product: product\n    }),\n  };\n\n  callback(null, response);\n};`, `9954468033366438000`)\"\n            >\n              <div\n                class=\"gatsby-code-button\"\n                data-tooltip=\"\"\n              >\n                复制代码<svg class=\"gatsby-code-button-icon\" xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"><path fill=\"none\" d=\"M0 0h24v24H0V0z\"/><path d=\"M16 1H2v16h2V3h12V1zm-1 4l6 6v12H6V5h9zm-1 7h5.5L14 6.5V12z\"/></svg>\n              </div>\n            </div>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token comment\">// handler.js</span>\n\n<span class=\"token string\">'use strict'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">const</span> <span class=\"token constant\">ALLOWED_ORIGINS</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span>\n\t<span class=\"token string\">'https://myfirstorigin.com'</span><span class=\"token punctuation\">,</span>\n\t<span class=\"token string\">'https://mysecondorigin.com'</span>\n<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n\nmodule<span class=\"token punctuation\">.</span>exports<span class=\"token punctuation\">.</span><span class=\"token function-variable function\">getProduct</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">event<span class=\"token punctuation\">,</span> context<span class=\"token punctuation\">,</span> callback</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n\n  <span class=\"token keyword\">const</span> origin <span class=\"token operator\">=</span> event<span class=\"token punctuation\">.</span>headers<span class=\"token punctuation\">.</span>origin<span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">let</span> headers<span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token constant\">ALLOWED_ORIGINS</span><span class=\"token punctuation\">.</span><span class=\"token function\">includes</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">origin</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    headers <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">:</span> origin<span class=\"token punctuation\">,</span>\n      <span class=\"token string\">'Access-Control-Allow-Credentials'</span><span class=\"token punctuation\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n    headers <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token string\">'Access-Control-Allow-Origin'</span><span class=\"token punctuation\">:</span> <span class=\"token string\">'*'</span><span class=\"token punctuation\">,</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token comment\">// Do work to retrieve Product</span>\n  <span class=\"token keyword\">const</span> product <span class=\"token operator\">=</span> <span class=\"token function\">retrieveProduct</span><span class=\"token punctuation\">(</span>event<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span>\n    isBase64Encoded<span class=\"token punctuation\">:</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">,</span>\n    statusCode<span class=\"token punctuation\">:</span> <span class=\"token number\">200</span><span class=\"token punctuation\">,</span>\n    headers\n    body<span class=\"token punctuation\">:</span> <span class=\"token constant\">JSON</span><span class=\"token punctuation\">.</span><span class=\"token function\">stringify</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>\n      product<span class=\"token punctuation\">:</span> product\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token function\">callback</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">,</span> response<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>在这个示例中，我们检查 <code class=\"language-text\">origin</code> header 是否匹配。如果匹配，我们会在 <code class=\"language-text\">Access-Control-Allow-Origin</code> 包含特定来源，并声明 <code class=\"language-text\">Access-Control-Allow-Credentials</code> 允许的来源。如果 <code class=\"language-text\">origin</code> 不是我们允许的来源之一，则我们将包含标准 headers，如果来源尝试进行凭据请求，则将被拒绝。</p>\n<h2 id=\"小结\"><a href=\"#%E5%B0%8F%E7%BB%93\" aria-label=\"小结 permalink\" class=\"anchor\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>小结</h2>\n<p>处理 CORS 确实是一件麻烦的事情，但是使用 Serverless Framework 会让处理步骤变得简单得多！而这也就意味着再也不会出现 <code class=\"language-text\">No &#39;Access-Control-Allow-Origin&#39; header is present on the requested resource</code> 这样的错误啦！👋</p>\n<blockquote>\n<p>参考：</p>\n<ul>\n<li><a href=\"www.serverless.com\">Serverless Framework - 产品官网</a> </li>\n<li><a href=\"https://github.com/serverless/serverless/blob/master/README_CN.md\">Serverless Framework - GitHub</a> </li>\n</ul>\n</blockquote>\n<p>欢迎访问：<a href=\"https://serverlesscloud.cn/\">Serverless 中文技术社区</a>，您可以在 <a href=\"https://serverlesscloud.cn/best-practice\">最佳实践</a> 里体验更多关于 Serverless 应用的开发！</p>","tableOfContents":"<ul>\n<li><a href=\"/blog/2018-01-16-cors-api-gateway-survival-guide/#tldr\">TL;DR</a></li>\n<li>\n<p><a href=\"/blog/2018-01-16-cors-api-gateway-survival-guide/#cors-preflight-requests\">CORS preflight requests</a></p>\n<ul>\n<li><a href=\"/blog/2018-01-16-cors-api-gateway-survival-guide/#%E6%B5%8F%E8%A7%88%E5%99%A8%E4%BB%80%E4%B9%88%E6%97%B6%E5%80%99%E5%8F%91%E9%80%81-preflight-requests\">浏览器什么时候发送 preflight requests?</a></li>\n<li><a href=\"/blog/2018-01-16-cors-api-gateway-survival-guide/#%E5%AF%B9-preflight-requests-%E7%9A%84%E5%93%8D%E5%BA%94%E6%98%AF%E4%BB%80%E4%B9%88%EF%BC%9F\">对 preflight requests 的响应是什么？</a></li>\n<li><a href=\"/blog/2018-01-16-cors-api-gateway-survival-guide/#%E5%A6%82%E4%BD%95%E5%A4%84%E7%90%86-serverless-%E4%B8%AD%E7%9A%84-preflight-requests\">如何处理 Serverless 中的 preflight requests?</a></li>\n</ul>\n</li>\n<li><a href=\"/blog/2018-01-16-cors-api-gateway-survival-guide/#cors-response-headers\">CORS Response Headers</a></li>\n<li><a href=\"/blog/2018-01-16-cors-api-gateway-survival-guide/#cors-with-cookie-credentials\">CORS with Cookie credentials</a></li>\n<li><a href=\"/blog/2018-01-16-cors-api-gateway-survival-guide/#%E5%B0%8F%E7%BB%93\">小结</a></li>\n</ul>"},"previousBlog":{"id":"5a5e479a-32eb-589a-bc25-3a1a3b6e0126","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/inclusion/serverless-tech-inclusion1.jpg","authors":["CharmmieHendon"],"categories":["engineering-culture"],"date":"2018-01-24T00:00:00.000Z","title":"融入所处环境：科技领域的包容性和多元化","description":"我是 Charmmie Hendon，非常热衷于促进科技领域的包容性和多元化。以下是我的一些个人经历以及您如何带来改变。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":222,"sentences":37,"paragraphs":36},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-07-16-get-in-where-you-fit-in-inclusion-diversity-tech.md","fields":{"slug":"/blog/2018-07-16-get-in-where-you-fit-in-inclusion-diversity-tech/","keywords":["Javascript","serverless","行业","Serverless","serverless","偏见","多元化","inclusion"]}},"nextBlog":{"id":"4300b21c-7209-5256-86ff-0d38e3daec9b","frontmatter":{"thumbnail":"https://main.qcloudimg.com/raw/14f1c8eed372e76c1b139703b2f6d0fa.jpg","authors":["KieranMcCarthy"],"categories":["user-stories","engineering-culture"],"date":"2018-01-09T00:00:00.000Z","title":"我是如何在四年时间里，从厨师转行为 Serverless 应用开发者","description":"我是厨师出身，现在成为了一名 Serverless 应用开发者。","authorslink":["https://serverless.com/author/kieranmccarthy/"],"translators":["Aceyclee"],"translatorslink":["https://www.zhihu.com/people/Aceyclee"],"tags":["应用开发","Serverless"],"keywords":"Serverless 应用开发,Serverless 管理,厨师转行为 Serverless 应用开发者","outdated":null},"wordCount":{"words":285,"sentences":38,"paragraphs":36},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-01-09-from-chef-to-serverless-developer-in-4-years.md","fields":{"slug":"/blog/2018-01-09-from-chef-to-serverless-developer-in-4-years/","keywords":["无服务器","无服务器开发","云函数","学习","Serverless","构建","Framework","开发者","服务器","应用","学位","简历"]}},"recommendBlogs":{"edges":[{"node":{"id":"665f9ce2-4451-59fd-bf98-1861789d3b3b","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/Serverless_logo.png","authors":["AndreaPasswater"],"categories":["guides-and-tutorials","engineering-culture"],"date":"2018-03-19T00:00:00.000Z","title":"如何为无服务器开放源代码项目做贡献","description":"想要为无服务器开放源代码项目做贡献？您可以遵循下面的指南。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":96,"sentences":36,"paragraphs":36},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-03-19-how-contribute-to-serverless-open-source.md","fields":{"slug":"/blog/2018-03-19-how-contribute-to-serverless-open-source/","keywords":["serverless","无服务器","serverless","github","插件","服务器","贡献","示例","blog","contribute"]}}},{"node":{"id":"a3e92579-65c3-5159-937c-32d18c5df7d7","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/why-not/why-not-header.png","authors":["AndreaPasswater"],"categories":["guides-and-tutorials","operations-and-observability","engineering-culture"],"date":"2018-03-21T00:00:00.000Z","title":"不适合选择无服务器的情境及原因","description":"无服务器既有优点也有缺点。那么，哪些情境下不适合选择无服务器？原因又是什么呢？","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":163,"sentences":43,"paragraphs":43},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-03-21-when-why-not-use-serverless.md","fields":{"slug":"/blog/2018-03-21-when-why-not-use-serverless/","keywords":["faas","react","serverless","spa","无服务器","无服务器函数","无服务器架构","无服务器开发","服务器","twitter","serverless","blockquote","lang","script","en"]}}},{"node":{"id":"6a16520b-7886-582e-9182-64e50712d486","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/vendor+choice/serverless-data-portability.jpg","authors":["NickGottlieb"],"categories":["engineering-culture","guides-and-tutorials"],"date":"2018-06-20T00:00:00.000Z","title":"浅谈无服务器、数据锁定和供应商选择","description":"供应商选择是如今 IT 领导者需要考虑的最重要事项，而这一点可利用数据可移植性来实现。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":205,"sentences":33,"paragraphs":33},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-06-20-data-lockin-vendor-choice-portability.md","fields":{"slug":"/blog/2018-06-20-data-lockin-vendor-choice-portability/","keywords":["go","serverless","无服务器","无服务器架构","供应商","serverless","开发人员","数据","锁定","选择","服务"]}}},{"node":{"id":"94741abb-10ba-5db1-9756-cd1d573473fa","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/webstorm-ide/streamline-webstorm-serverless2.jpg","authors":["EslamHefnawy"],"categories":["guides-and-tutorials","engineering-culture"],"date":"2018-08-15T00:00:00.000Z","title":"如何使用 WebStorm 简化无服务器工作流程","description":"在本文中，我将和您分享如何使用 WebStorm 进行无服务器特定的 IDE 设置以及如何利用它来极大地加快无服务器工作流程。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":234,"sentences":54,"paragraphs":54},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-08-15-streamline-serverless-workflow-webstorm.md","fields":{"slug":"/blog/2018-08-15-streamline-serverless-workflow-webstorm/","keywords":["nodejs","serverless","无服务器","无服务器开发","serverless","WebStorm","webstorm","服务器","blog","assets"]}}},{"node":{"id":"713a0563-4bf9-5721-bacb-3b4ef609fe4a","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/camp-fire/camp-fire-housing-thumb.jpg","authors":["EricWyne"],"categories":["guides-and-tutorials","user-stories"],"date":"2018-12-05T00:00:00.000Z","title":"Serverless Twitter 机器人帮助为坎普山火受灾者安置住房","description":"加利福尼亚州的坎普山火致使数千人流离失所，为此，我构建了一个简单的 Serverless Twitter 机器人来帮助将受灾者安置在临时住房！","authorslink":["https://serverless.com/author/ericwyne/"],"translators":["Aceyclee"],"translatorslink":["zhihu.com/people/Aceyclee"],"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":157,"sentences":26,"paragraphs":26},"fileAbsolutePath":"/opt/build/repo/content/blog/2018-12-05-serverless-twitter-camp-fire.md","fields":{"slug":"/blog/2018-12-05-serverless-twitter-camp-fire/","keywords":["serverless","无服务器","云函数","Serverless","org","住房","Twitter","函数","受灾","机器人","山火"]}}},{"node":{"id":"17c972d9-0583-51f6-9d5d-c2ba5f21b6a3","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/20191227/1577409288454-v2-577c2b21d600e3ea07f156f3e9d2d6b8_1200x500.jpg","authors":["Alfred Huang"],"categories":["guides-and-tutorials"],"date":"2019-08-21T00:00:00.000Z","title":"Serverless 的运行原理与组件架构","description":"本文重点探讨下开发者使用 Serverless 时经常遇到的一些问题，以及如何解决","authorslink":["https://zhuanlan.zhihu.com/ServerlessGo"],"translators":null,"translatorslink":null,"tags":["运行原理","serverless"],"keywords":"Serverless 运行原理,Serverless 组件架构","outdated":null},"wordCount":{"words":236,"sentences":33,"paragraphs":33},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-08-21-serverless-operation-architecture.md","fields":{"slug":"/blog/2019-08-21-serverless-operation-architecture/","keywords":["koa","serverless","云函数","Serverless","用户","函数","请求","实例","形态","业务","serverlesscloud"]}}},{"node":{"id":"ae4fd2f8-515c-5aec-b584-38427ef33f7e","frontmatter":{"thumbnail":"https://img.serverlesscloud.cn/2020114/1578989800047-part-00492-780.jpg","authors":["Anycodes"],"categories":["guides-and-tutorials","user-stories"],"date":"2019-09-16T00:00:00.000Z","title":"突破传统 OJ 瓶颈，「判题姬」接入云函数","description":"通过 Serverless 实现在线编程","authorslink":["https://www.zhihu.com/people/liuyu-43-97"],"translators":null,"translatorslink":null,"tags":["在线编程","云函数"],"keywords":"Serverless 在线编程,Serverless OJ","outdated":null},"wordCount":{"words":169,"sentences":30,"paragraphs":30},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-09-16-online-Judge.md","fields":{"slug":"/blog/2019-09-16-online-Judge/","keywords":["python","serverless","云函数","代码","函数","serverless"]}}},{"node":{"id":"545ab3d2-e14e-5cc2-8548-0e863eac942b","frontmatter":{"thumbnail":"https://s3-us-west-2.amazonaws.com/assets.blog.serverless.com/2019-10-deployment-best-practices/safeguard-header.png","authors":["FernandoMedinaCorey"],"categories":["guides-and-tutorials"],"date":"2019-10-14T00:00:00.000Z","title":"无服务器部署最佳实践","description":"了解部署无服务器应用时的一些最佳实践。","authorslink":null,"translators":null,"translatorslink":null,"tags":null,"keywords":null,"outdated":null},"wordCount":{"words":221,"sentences":46,"paragraphs":46},"fileAbsolutePath":"/opt/build/repo/content/blog/2019-10-14-serverless-deployment-best-practices.md","fields":{"slug":"/blog/2019-10-14-serverless-deployment-best-practices/","keywords":["serverless","无服务器","serverless","部署","服务器","开发人员","应用","安全措施","使用","函数"]}}}],"totalCount":31}},"pageContext":{"isCreatedByStatefulCreatePages":false,"blogId":"5928eee6-9546-5603-ad61-a9688dbafd02","previousBlogId":"5a5e479a-32eb-589a-bc25-3a1a3b6e0126","nextBlogId":"4300b21c-7209-5256-86ff-0d38e3daec9b","categories":["guides-and-tutorials","operations-and-observability"]}}}