{"id":54522,"date":"2025-12-18T04:46:17","date_gmt":"2025-12-18T04:46:17","guid":{"rendered":"https:\/\/www.devopsschool.com\/blog\/?p=54522"},"modified":"2025-12-18T04:46:17","modified_gmt":"2025-12-18T04:46:17","slug":"google-cloud-api-gateway-basic-tutorials","status":"publish","type":"post","link":"https:\/\/www.devopsschool.com\/blog\/google-cloud-api-gateway-basic-tutorials\/","title":{"rendered":"Google Cloud: API Gateway Basic Tutorials"},"content":{"rendered":"\n<p>Below is a practical, step-by-step <strong>Google Cloud API Gateway<\/strong> setup using a <strong>dummy backend on Cloud Run<\/strong> (hello service), then testing via <strong>curl<\/strong>. This follows Google\u2019s official \u201cAPI Gateway + Cloud Run\u201d flow. (<a href=\"https:\/\/docs.cloud.google.com\/api-gateway\/docs\/get-started-cloud-run?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">Google Cloud Documentation<\/a>)<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">0) Prereqs<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A Google Cloud project + billing enabled<\/li>\n\n\n\n<li>Google Cloud SDK (<code>gcloud<\/code>) installed and logged in<\/li>\n<\/ul>\n\n\n\n<p>Set variables (edit these 4 lines):<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">export<\/span> PROJECT_ID=<span class=\"hljs-string\">\"YOUR_PROJECT_ID\"<\/span>\n<span class=\"hljs-keyword\">export<\/span> REGION=<span class=\"hljs-string\">\"us-central1\"<\/span>\n<span class=\"hljs-keyword\">export<\/span> API_ID=<span class=\"hljs-string\">\"demo-api\"<\/span>\n<span class=\"hljs-keyword\">export<\/span> GATEWAY_ID=<span class=\"hljs-string\">\"demo-gw\"<\/span>\ngcloud config <span class=\"hljs-keyword\">set<\/span> project \"$PROJECT_ID\"\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">1) Enable required APIs<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">gcloud<\/span> <span class=\"hljs-selector-tag\">services<\/span> <span class=\"hljs-selector-tag\">enable<\/span> \\\n  <span class=\"hljs-selector-tag\">apigateway<\/span><span class=\"hljs-selector-class\">.googleapis<\/span><span class=\"hljs-selector-class\">.com<\/span> \\\n  <span class=\"hljs-selector-tag\">cloudbuild<\/span><span class=\"hljs-selector-class\">.googleapis<\/span><span class=\"hljs-selector-class\">.com<\/span> \\\n  <span class=\"hljs-selector-tag\">run<\/span><span class=\"hljs-selector-class\">.googleapis<\/span><span class=\"hljs-selector-class\">.com<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>(API Gateway requires its service enabled; Cloud Run\/Cloud Build are used for the dummy backend.) (<a href=\"https:\/\/docs.cloud.google.com\/api-gateway\/docs\/get-started-cloud-run?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">Google Cloud Documentation<\/a>)<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">2) Deploy a dummy backend on Cloud Run<\/h2>\n\n\n\n<p>Deploy a public \u201chello\u201d container:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">gcloud run deploy hello-backend \\\n  --image gcr.io\/cloudrun\/hello \\\n  --region <span class=\"hljs-string\">\"$REGION\"<\/span> \\\n  --allow-unauthenticated\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Get the Cloud Run URL:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">export BACKEND_URL=<span class=\"hljs-string\">\"$(gcloud run services describe hello-backend --region \"<\/span>$REGION<span class=\"hljs-string\">\" --format='value(status.url)')\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"$BACKEND_URL\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Quick test the backend directly:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">curl -i <span class=\"hljs-string\">\"$BACKEND_URL\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">3) Create an OpenAPI spec for API Gateway<\/h2>\n\n\n\n<p>Create a file <code>openapi.yaml<\/code> (Swagger\/OpenAPI 2.0) like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">swagger: <span class=\"hljs-string\">\"2.0\"<\/span>\ninfo:\n  title: <span class=\"hljs-string\">\"Demo API Gateway\"<\/span>\n  description: <span class=\"hljs-string\">\"API Gateway -&gt; Cloud Run dummy backend\"<\/span>\n  version: <span class=\"hljs-string\">\"1.0.0\"<\/span>\n\nschemes:\n  - https\n\nproduces:\n  - application\/json\n\npaths:\n  \/hello:\n    get:\n      operationId: hello\n      x-google-backend:\n        address: BACKEND_URL_REPLACE_ME\n      responses:\n        <span class=\"hljs-string\">\"200\"<\/span>:\n          description: OK\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Replace <code>BACKEND_URL_REPLACE_ME<\/code> with your Cloud Run URL:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">sed -i.bak <span class=\"hljs-string\">\"s|BACKEND_URL_REPLACE_ME|$BACKEND_URL|g\"<\/span> openapi.yaml\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Why this works: API Gateway reads <code>x-google-backend<\/code> to know where to route requests. (<a href=\"https:\/\/docs.cloud.google.com\/api-gateway\/docs\/oasv2-extensions?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">Google Cloud Documentation<\/a>)<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">4) Create an API config (uploads your OpenAPI to API Gateway)<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">export<\/span> API_CONFIG_ID=<span class=\"hljs-string\">\"demo-config-v1\"<\/span>\n\ngcloud api-gateway api-configs create <span class=\"hljs-string\">\"$API_CONFIG_ID\"<\/span> \\\n  --api=<span class=\"hljs-string\">\"$API_ID\"<\/span> \\\n  --openapi-spec=openapi.yaml \\\n  --project=<span class=\"hljs-string\">\"$PROJECT_ID\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Creating an API config is the \u201cupload the definition\u201d step. (<a href=\"https:\/\/docs.cloud.google.com\/api-gateway\/docs\/creating-api-config?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">Google Cloud Documentation<\/a>)<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">5) Create a Gateway and deploy the config<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">gcloud api-gateway gateways create <span class=\"hljs-string\">\"$GATEWAY_ID\"<\/span> \\\n  --api=<span class=\"hljs-string\">\"$API_ID\"<\/span> \\\n  --api-config=<span class=\"hljs-string\">\"$API_CONFIG_ID\"<\/span> \\\n  --location=<span class=\"hljs-string\">\"$REGION\"<\/span> \\\n  --project=<span class=\"hljs-string\">\"$PROJECT_ID\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This deploys the API config to a gateway. (<a href=\"https:\/\/docs.cloud.google.com\/api-gateway\/docs\/deploying-api?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">Google Cloud Documentation<\/a>)<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">6) Get the Gateway URL and test<\/h2>\n\n\n\n<p>Fetch the gateway\u2019s default hostname:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">export GATEWAY_HOST=<span class=\"hljs-string\">\"$(gcloud api-gateway gateways describe \"<\/span>$GATEWAY_ID<span class=\"hljs-string\">\" --location \"<\/span>$REGION<span class=\"hljs-string\">\" --format='value(defaultHostname)')\"<\/span>\n<span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"$GATEWAY_HOST\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Call your API through API Gateway:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">curl -i <span class=\"hljs-string\">\"https:\/\/${GATEWAY_HOST}\/hello\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>You should see a response coming from the Cloud Run hello backend (but accessed via the gateway).<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Optional: Require an API Key (simple protection)<\/h1>\n\n\n\n<p>API Gateway can enforce API keys using security definitions. (<a href=\"https:\/\/docs.cloud.google.com\/api-gateway\/docs\/authenticate-api-keys?utm_source=chatgpt.com\" target=\"_blank\" rel=\"noopener\">Google Cloud Documentation<\/a>)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">A) Update <code>openapi.yaml<\/code> to require API key<\/h3>\n\n\n\n<p>Add these blocks:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">securityDefinitions:\n  api_key:\n    type: <span class=\"hljs-string\">\"apiKey\"<\/span>\n    <span class=\"hljs-attr\">name<\/span>: <span class=\"hljs-string\">\"key\"<\/span>\n    <span class=\"hljs-attr\">in<\/span>: <span class=\"hljs-string\">\"query\"<\/span>\n\n<span class=\"hljs-attr\">security<\/span>:\n  - api_key: &#91;]\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>(Keep your <code>\/hello<\/code> path the same.)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">B) Create a NEW config and deploy it<\/h3>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">export<\/span> API_CONFIG_ID=<span class=\"hljs-string\">\"demo-config-v2\"<\/span>\n\ngcloud api-gateway api-configs create <span class=\"hljs-string\">\"$API_CONFIG_ID\"<\/span> \\\n  --api=<span class=\"hljs-string\">\"$API_ID\"<\/span> \\\n  --openapi-spec=openapi.yaml\n\ngcloud api-gateway gateways update <span class=\"hljs-string\">\"$GATEWAY_ID\"<\/span> \\\n  --location <span class=\"hljs-string\">\"$REGION\"<\/span> \\\n  --api=<span class=\"hljs-string\">\"$API_ID\"<\/span> \\\n  --api-config=<span class=\"hljs-string\">\"$API_CONFIG_ID\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\">C) Create an API key in Google Cloud Console and test<\/h3>\n\n\n\n<p>Call without key (should fail), then with key:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">curl -i <span class=\"hljs-string\">\"https:\/\/${GATEWAY_HOST}\/hello?key=YOUR_API_KEY\"<\/span>\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Cleanup (avoid charges)<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">gcloud api-gateway gateways <span class=\"hljs-keyword\">delete<\/span> <span class=\"hljs-string\">\"$GATEWAY_ID\"<\/span> --location <span class=\"hljs-string\">\"$REGION\"<\/span> -q\ngcloud api-gateway api-configs <span class=\"hljs-keyword\">delete<\/span> demo-config-v1 --api <span class=\"hljs-string\">\"$API_ID\"<\/span> -q || <span class=\"hljs-literal\">true<\/span>\ngcloud api-gateway api-configs <span class=\"hljs-keyword\">delete<\/span> demo-config-v2 --api <span class=\"hljs-string\">\"$API_ID\"<\/span> -q || <span class=\"hljs-literal\">true<\/span>\ngcloud api-gateway apis <span class=\"hljs-keyword\">delete<\/span> <span class=\"hljs-string\">\"$API_ID\"<\/span> -q\ngcloud run services <span class=\"hljs-keyword\">delete<\/span> hello-backend --region <span class=\"hljs-string\">\"$REGION\"<\/span> -q\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Below is a practical, step-by-step Google Cloud API Gateway setup using a dummy backend on Cloud Run (hello service), then testing via curl. This follows Google\u2019s official \u201cAPI Gateway +&#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_joinchat":[],"footnotes":""},"categories":[11138],"tags":[],"class_list":["post-54522","post","type-post","status-publish","format-standard","hentry","category-best-tools"],"_links":{"self":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/54522","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/comments?post=54522"}],"version-history":[{"count":1,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/54522\/revisions"}],"predecessor-version":[{"id":54523,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/posts\/54522\/revisions\/54523"}],"wp:attachment":[{"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/media?parent=54522"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/categories?post=54522"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.devopsschool.com\/blog\/wp-json\/wp\/v2\/tags?post=54522"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}