zuplo 6.67.32 → 6.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/docs/_index.md +44 -0
- package/docs/ai-gateway/apps.mdx +28 -0
- package/docs/ai-gateway/custom-providers.mdx +54 -0
- package/docs/ai-gateway/getting-started.mdx +224 -0
- package/docs/ai-gateway/guardrails.mdx +65 -0
- package/docs/ai-gateway/integrations/ai-sdk.mdx +109 -0
- package/docs/ai-gateway/integrations/claude-code.mdx +49 -0
- package/docs/ai-gateway/integrations/codex.mdx +78 -0
- package/docs/ai-gateway/integrations/goose.mdx +104 -0
- package/docs/ai-gateway/integrations/langchain.mdx +66 -0
- package/docs/ai-gateway/integrations/openai.mdx +99 -0
- package/docs/ai-gateway/introduction.mdx +85 -0
- package/docs/ai-gateway/managing-apps.mdx +46 -0
- package/docs/ai-gateway/managing-providers.mdx +66 -0
- package/docs/ai-gateway/managing-teams.mdx +63 -0
- package/docs/ai-gateway/policies/akamai-ai-firewall.mdx +125 -0
- package/docs/ai-gateway/policies/comet-opik-tracing.mdx +139 -0
- package/docs/ai-gateway/policies/galileo-tracing.mdx +147 -0
- package/docs/ai-gateway/providers.mdx +32 -0
- package/docs/ai-gateway/teams.mdx +38 -0
- package/docs/ai-gateway/universal-api.mdx +43 -0
- package/docs/ai-gateway/usage-limits.mdx +89 -0
- package/docs/api-management/introduction.md +127 -0
- package/docs/articles/accounts/audit-logs.mdx +227 -0
- package/docs/articles/accounts/billing.mdx +25 -0
- package/docs/articles/accounts/default-api-key.mdx +30 -0
- package/docs/articles/accounts/delete-account.mdx +36 -0
- package/docs/articles/accounts/enterprise-sso.mdx +116 -0
- package/docs/articles/accounts/managing-account-members.mdx +45 -0
- package/docs/articles/accounts/managing-project-members.mdx +37 -0
- package/docs/articles/accounts/members-and-roles.mdx +21 -0
- package/docs/articles/accounts/roles-and-permissions.mdx +115 -0
- package/docs/articles/accounts/zuplo-api-keys.mdx +94 -0
- package/docs/articles/add-api-to-backstage.mdx +216 -0
- package/docs/articles/advanced-path-matching.mdx +139 -0
- package/docs/articles/api-key-administration.mdx +47 -0
- package/docs/articles/api-key-api.mdx +220 -0
- package/docs/articles/api-key-authentication.mdx +195 -0
- package/docs/articles/api-key-buckets.mdx +61 -0
- package/docs/articles/api-key-end-users.mdx +52 -0
- package/docs/articles/api-key-leak-detection.mdx +75 -0
- package/docs/articles/api-key-management.mdx +100 -0
- package/docs/articles/api-key-react-component.mdx +90 -0
- package/docs/articles/api-key-service-limits.mdx +14 -0
- package/docs/articles/archiving-requests-to-storage.mdx +119 -0
- package/docs/articles/branch-based-deployments.mdx +184 -0
- package/docs/articles/bypass-policy-for-testing.mdx +117 -0
- package/docs/articles/check-ip-address.mdx +17 -0
- package/docs/articles/ci-cd-azure/basic-deployment.mdx +49 -0
- package/docs/articles/ci-cd-azure/deploy-and-test.mdx +47 -0
- package/docs/articles/ci-cd-azure/local-testing.mdx +59 -0
- package/docs/articles/ci-cd-azure/multi-stage-deployment.mdx +88 -0
- package/docs/articles/ci-cd-azure/pr-preview-environments.mdx +50 -0
- package/docs/articles/ci-cd-azure/tag-based-releases.mdx +37 -0
- package/docs/articles/ci-cd-bitbucket/basic-deployment.mdx +27 -0
- package/docs/articles/ci-cd-bitbucket/deploy-and-test.mdx +41 -0
- package/docs/articles/ci-cd-bitbucket/local-testing.mdx +34 -0
- package/docs/articles/ci-cd-bitbucket/multi-stage-deployment.mdx +52 -0
- package/docs/articles/ci-cd-bitbucket/pr-preview-environments.mdx +46 -0
- package/docs/articles/ci-cd-bitbucket/tag-based-releases.mdx +27 -0
- package/docs/articles/ci-cd-circleci/basic-deployment.mdx +34 -0
- package/docs/articles/ci-cd-circleci/deploy-and-test.mdx +44 -0
- package/docs/articles/ci-cd-circleci/local-testing.mdx +50 -0
- package/docs/articles/ci-cd-circleci/multi-stage-deployment.mdx +82 -0
- package/docs/articles/ci-cd-circleci/pr-preview-environments.mdx +47 -0
- package/docs/articles/ci-cd-circleci/tag-based-releases.mdx +38 -0
- package/docs/articles/ci-cd-github/basic-deployment.mdx +48 -0
- package/docs/articles/ci-cd-github/cleanup-on-branch-delete.mdx +123 -0
- package/docs/articles/ci-cd-github/deploy-and-test.mdx +82 -0
- package/docs/articles/ci-cd-github/local-testing.mdx +102 -0
- package/docs/articles/ci-cd-github/multi-stage-deployment.mdx +136 -0
- package/docs/articles/ci-cd-github/pr-preview-environments.mdx +106 -0
- package/docs/articles/ci-cd-github/tag-based-releases.mdx +99 -0
- package/docs/articles/ci-cd-gitlab/basic-deployment.mdx +28 -0
- package/docs/articles/ci-cd-gitlab/deploy-and-test.mdx +44 -0
- package/docs/articles/ci-cd-gitlab/local-testing.mdx +39 -0
- package/docs/articles/ci-cd-gitlab/mr-preview-environments.mdx +52 -0
- package/docs/articles/ci-cd-gitlab/multi-stage-deployment.mdx +64 -0
- package/docs/articles/ci-cd-gitlab/tag-based-releases.mdx +28 -0
- package/docs/articles/composite-policy-reference.mdx +284 -0
- package/docs/articles/configuring-auth0-for-mcp-auth.mdx +186 -0
- package/docs/articles/configuring-okta-for-mcp-auth.mdx +208 -0
- package/docs/articles/convert-urls-to-openapi.mdx +62 -0
- package/docs/articles/cors.mdx +447 -0
- package/docs/articles/custom-audit-log-policy.mdx +95 -0
- package/docs/articles/custom-ci-cd-azure.mdx +81 -0
- package/docs/articles/custom-ci-cd-bitbucket.mdx +80 -0
- package/docs/articles/custom-ci-cd-circleci.mdx +78 -0
- package/docs/articles/custom-ci-cd-github.mdx +99 -0
- package/docs/articles/custom-ci-cd-gitlab.mdx +79 -0
- package/docs/articles/custom-ci-cd.mdx +82 -0
- package/docs/articles/custom-code-patterns.md +418 -0
- package/docs/articles/custom-domains.mdx +258 -0
- package/docs/articles/custom-logging-example.mdx +139 -0
- package/docs/articles/ddos-protection.mdx +138 -0
- package/docs/articles/development-options.mdx +49 -0
- package/docs/articles/environment-variables.mdx +134 -0
- package/docs/articles/environments.mdx +143 -0
- package/docs/articles/fastly-zuplo-host-setup.mdx +41 -0
- package/docs/articles/github-deployment-testing.mdx +101 -0
- package/docs/articles/gke-with-upstream-auth-policy.mdx +192 -0
- package/docs/articles/graphql-security.mdx +180 -0
- package/docs/articles/handling-form-data.mdx +61 -0
- package/docs/articles/health-checks.mdx +109 -0
- package/docs/articles/hosting-options.mdx +70 -0
- package/docs/articles/lazy-load-configuration-into-cache.mdx +92 -0
- package/docs/articles/limits.mdx +98 -0
- package/docs/articles/local-development-debugging.mdx +44 -0
- package/docs/articles/local-development-env-variables.mdx +23 -0
- package/docs/articles/local-development-installing-packages.mdx +23 -0
- package/docs/articles/local-development-routes-designer.mdx +27 -0
- package/docs/articles/local-development-services.mdx +40 -0
- package/docs/articles/local-development-troubleshooting.mdx +56 -0
- package/docs/articles/local-development.mdx +81 -0
- package/docs/articles/log-plugin-aws-cloudwatch.mdx +83 -0
- package/docs/articles/log-plugin-datadog.mdx +84 -0
- package/docs/articles/log-plugin-dynatrace.mdx +75 -0
- package/docs/articles/log-plugin-gcp.mdx +75 -0
- package/docs/articles/log-plugin-loki.mdx +136 -0
- package/docs/articles/log-plugin-new-relic.mdx +84 -0
- package/docs/articles/log-plugin-splunk.mdx +104 -0
- package/docs/articles/log-plugin-sumo.mdx +73 -0
- package/docs/articles/log-plugin-vmware-log-insight.mdx +154 -0
- package/docs/articles/log-request-response-data.mdx +398 -0
- package/docs/articles/logging.mdx +115 -0
- package/docs/articles/manual-mcp-oauth-testing.mdx +193 -0
- package/docs/articles/mcp-quickstart.mdx +135 -0
- package/docs/articles/metrics-plugins.mdx +371 -0
- package/docs/articles/migrate-from-apigee.md +408 -0
- package/docs/articles/migrate-from-aws-api-gateway.md +248 -0
- package/docs/articles/migrate-from-azure-apim.md +292 -0
- package/docs/articles/migrate-from-kong.md +300 -0
- package/docs/articles/migration-overview.md +81 -0
- package/docs/articles/monetization/api-access.mdx +69 -0
- package/docs/articles/monetization/billing-models.md +520 -0
- package/docs/articles/monetization/developer-portal.md +167 -0
- package/docs/articles/monetization/features.mdx +98 -0
- package/docs/articles/monetization/index.mdx +113 -0
- package/docs/articles/monetization/meters.mdx +135 -0
- package/docs/articles/monetization/monetization-policy.md +314 -0
- package/docs/articles/monetization/plan-examples.mdx +366 -0
- package/docs/articles/monetization/plans.mdx +266 -0
- package/docs/articles/monetization/pricing-models.mdx +225 -0
- package/docs/articles/monetization/private-plans.md +154 -0
- package/docs/articles/monetization/quickstart.md +355 -0
- package/docs/articles/monetization/rate-cards.mdx +171 -0
- package/docs/articles/monetization/stripe-integration.md +195 -0
- package/docs/articles/monetization/subscription-lifecycle.md +298 -0
- package/docs/articles/monetization/tax-collection.md +166 -0
- package/docs/articles/monetization/troubleshooting.md +272 -0
- package/docs/articles/monetization-custom.mdx +71 -0
- package/docs/articles/monetization-integrations.mdx +104 -0
- package/docs/articles/monitoring-your-gateway.mdx +53 -0
- package/docs/articles/monorepo-deployment.mdx +350 -0
- package/docs/articles/multiple-auth-policies.mdx +81 -0
- package/docs/articles/non-standard-ports.mdx +30 -0
- package/docs/articles/oauth-authentication.mdx +54 -0
- package/docs/articles/openapi-server-urls.mdx +60 -0
- package/docs/articles/openapi.mdx +130 -0
- package/docs/articles/opentelemetry.mdx +250 -0
- package/docs/articles/per-user-rate-limits-using-db.mdx +112 -0
- package/docs/articles/performance-testing.mdx +304 -0
- package/docs/articles/plugin-akamai-api-security.mdx +76 -0
- package/docs/articles/plugin-azure-blob.mdx +73 -0
- package/docs/articles/plugin-azure-event-hubs.mdx +64 -0
- package/docs/articles/plugin-hydrolix-traffic-peak.mdx +147 -0
- package/docs/articles/policies.mdx +33 -0
- package/docs/articles/rename-or-move-project.mdx +39 -0
- package/docs/articles/rick-and-morty-api-developer-portal-example.mdx +23 -0
- package/docs/articles/routing.mdx +193 -0
- package/docs/articles/s3-signed-url-uploads.mdx +521 -0
- package/docs/articles/secure-tunnel.mdx +84 -0
- package/docs/articles/securing-backend-mtls.mdx +268 -0
- package/docs/articles/securing-your-backend.mdx +148 -0
- package/docs/articles/security.mdx +105 -0
- package/docs/articles/sharing-code-across-projects.mdx +412 -0
- package/docs/articles/source-control-setup-azure.mdx +13 -0
- package/docs/articles/source-control-setup-bitbucket.mdx +43 -0
- package/docs/articles/source-control-setup-github.mdx +172 -0
- package/docs/articles/source-control-setup-gitlab.mdx +12 -0
- package/docs/articles/source-control.mdx +80 -0
- package/docs/articles/step-1-setup-basic-gateway-local.mdx +136 -0
- package/docs/articles/step-1-setup-basic-gateway.mdx +118 -0
- package/docs/articles/step-2-add-rate-limiting-local.mdx +126 -0
- package/docs/articles/step-2-add-rate-limiting.mdx +82 -0
- package/docs/articles/step-3-add-api-key-auth-local.mdx +199 -0
- package/docs/articles/step-3-add-api-key-auth.mdx +166 -0
- package/docs/articles/step-4-deploying-to-the-edge.mdx +220 -0
- package/docs/articles/step-5-dynamic-rate-limiting.mdx +167 -0
- package/docs/articles/support.mdx +144 -0
- package/docs/articles/terraform.mdx +114 -0
- package/docs/articles/testing-graphql.mdx +34 -0
- package/docs/articles/testing.mdx +522 -0
- package/docs/articles/troubleshooting-slow-responses.mdx +301 -0
- package/docs/articles/troubleshooting.md +302 -0
- package/docs/articles/tsconfig.mdx +105 -0
- package/docs/articles/tunnel-setup.mdx +195 -0
- package/docs/articles/tunnel-troubleshooting.mdx +50 -0
- package/docs/articles/update-zup-in-github-action.mdx +110 -0
- package/docs/articles/use-openapi-extension-data.mdx +79 -0
- package/docs/articles/users/multifactor-authentication.mdx +64 -0
- package/docs/articles/users/profile.mdx +13 -0
- package/docs/articles/versioning-on-zuplo.mdx +89 -0
- package/docs/articles/waf-ddos-akamai.md +133 -0
- package/docs/articles/waf-ddos-aws-waf-shield.mdx +85 -0
- package/docs/articles/waf-ddos-fastly.mdx +251 -0
- package/docs/articles/waf-ddos.mdx +140 -0
- package/docs/articles/zuplo-waf.mdx +156 -0
- package/docs/ask.mdx +3 -0
- package/docs/cli/authentication.mdx +56 -0
- package/docs/cli/connectivity.mdx +38 -0
- package/docs/cli/create-zuplo-api.mdx +80 -0
- package/docs/cli/delete.mdx +79 -0
- package/docs/cli/deploy.mdx +156 -0
- package/docs/cli/deploy.partial.mdx +46 -0
- package/docs/cli/dev.mdx +115 -0
- package/docs/cli/docs.mdx +66 -0
- package/docs/cli/editor.mdx +50 -0
- package/docs/cli/global-options.mdx +19 -0
- package/docs/cli/init.mdx +74 -0
- package/docs/cli/link.mdx +74 -0
- package/docs/cli/list.mdx +55 -0
- package/docs/cli/mtls-certificate-create.mdx +94 -0
- package/docs/cli/mtls-certificate-delete.mdx +55 -0
- package/docs/cli/mtls-certificate-describe.mdx +55 -0
- package/docs/cli/mtls-certificate-disable.mdx +55 -0
- package/docs/cli/mtls-certificate-list.mdx +47 -0
- package/docs/cli/mtls-certificate-update.mdx +72 -0
- package/docs/cli/openapi-convert.mdx +111 -0
- package/docs/cli/openapi-merge.mdx +138 -0
- package/docs/cli/openapi-merge.partial.mdx +29 -0
- package/docs/cli/openapi-overlay.mdx +123 -0
- package/docs/cli/overview.mdx +78 -0
- package/docs/cli/project-create.mdx +43 -0
- package/docs/cli/source-migrate.mdx +18 -0
- package/docs/cli/source-upgrade.mdx +41 -0
- package/docs/cli/test.mdx +70 -0
- package/docs/cli/test.partial.mdx +7 -0
- package/docs/cli/tunnel-create.mdx +53 -0
- package/docs/cli/tunnel-create.partial.mdx +9 -0
- package/docs/cli/tunnel-delete.mdx +35 -0
- package/docs/cli/tunnel-delete.partial.mdx +9 -0
- package/docs/cli/tunnel-describe.mdx +45 -0
- package/docs/cli/tunnel-describe.partial.mdx +5 -0
- package/docs/cli/tunnel-list.mdx +35 -0
- package/docs/cli/tunnel-list.partial.mdx +9 -0
- package/docs/cli/tunnel-rate-token.partial.mdx +9 -0
- package/docs/cli/tunnel-rotate-token.mdx +39 -0
- package/docs/cli/tunnel-services-describe.mdx +45 -0
- package/docs/cli/tunnel-services-describe.partial.mdx +9 -0
- package/docs/cli/tunnel-services-update.mdx +48 -0
- package/docs/cli/variable-create.mdx +91 -0
- package/docs/cli/variable-create.partial.mdx +5 -0
- package/docs/cli/variable-update.mdx +75 -0
- package/docs/cli/variable-update.partial.mdx +5 -0
- package/docs/concepts/api-keys.md +146 -0
- package/docs/concepts/authentication.mdx +109 -0
- package/docs/concepts/how-zuplo-works.mdx +120 -0
- package/docs/concepts/project-structure.mdx +174 -0
- package/docs/concepts/rate-limiting.md +246 -0
- package/docs/concepts/request-lifecycle.mdx +56 -0
- package/docs/concepts/source-control-and-deployment.mdx +229 -0
- package/docs/conferences/conference-prize-terms.mdx +80 -0
- package/docs/dedicated/akamai/ai-powered-applications.mdx +223 -0
- package/docs/dedicated/akamai/architecture.mdx +280 -0
- package/docs/dedicated/akamai/caching.mdx +212 -0
- package/docs/dedicated/akamai/cdn.mdx +156 -0
- package/docs/dedicated/architecture.mdx +208 -0
- package/docs/dedicated/custom-domains.mdx +31 -0
- package/docs/dedicated/federated-gateways.mdx +80 -0
- package/docs/dedicated/networking.mdx +69 -0
- package/docs/dedicated/overview.mdx +80 -0
- package/docs/dedicated/source-control.mdx +63 -0
- package/docs/dev-portal/dev-portal-create-consumer-on-auth.mdx +134 -0
- package/docs/dev-portal/introduction.mdx +65 -0
- package/docs/dev-portal/local-development.mdx +72 -0
- package/docs/dev-portal/migration.mdx +526 -0
- package/docs/dev-portal/node-modules.mdx +45 -0
- package/docs/dev-portal/updating.mdx +28 -0
- package/docs/dev-portal/zudoku/components/alert.mdx +130 -0
- package/docs/dev-portal/zudoku/components/badge.mdx +70 -0
- package/docs/dev-portal/zudoku/components/button.mdx +132 -0
- package/docs/dev-portal/zudoku/components/callout.mdx +112 -0
- package/docs/dev-portal/zudoku/components/card.mdx +104 -0
- package/docs/dev-portal/zudoku/components/checkbox.mdx +72 -0
- package/docs/dev-portal/zudoku/components/client-only.mdx +79 -0
- package/docs/dev-portal/zudoku/components/code-tabs.mdx +179 -0
- package/docs/dev-portal/zudoku/components/dialog.mdx +167 -0
- package/docs/dev-portal/zudoku/components/head.mdx +199 -0
- package/docs/dev-portal/zudoku/components/icons.mdx +27 -0
- package/docs/dev-portal/zudoku/components/input.mdx +96 -0
- package/docs/dev-portal/zudoku/components/label.mdx +86 -0
- package/docs/dev-portal/zudoku/components/link.mdx +242 -0
- package/docs/dev-portal/zudoku/components/markdown.mdx +151 -0
- package/docs/dev-portal/zudoku/components/mermaid.mdx +81 -0
- package/docs/dev-portal/zudoku/components/playground.mdx +87 -0
- package/docs/dev-portal/zudoku/components/secret.mdx +78 -0
- package/docs/dev-portal/zudoku/components/select.mdx +176 -0
- package/docs/dev-portal/zudoku/components/shadcn.mdx +73 -0
- package/docs/dev-portal/zudoku/components/slider.mdx +108 -0
- package/docs/dev-portal/zudoku/components/slot.mdx +119 -0
- package/docs/dev-portal/zudoku/components/stepper.mdx +138 -0
- package/docs/dev-portal/zudoku/components/switch.mdx +96 -0
- package/docs/dev-portal/zudoku/components/syntax-highlight.mdx +602 -0
- package/docs/dev-portal/zudoku/components/textarea.mdx +78 -0
- package/docs/dev-portal/zudoku/components/tooltip.mdx +195 -0
- package/docs/dev-portal/zudoku/components/typography.mdx +61 -0
- package/docs/dev-portal/zudoku/configuration/ai-assistants.md +64 -0
- package/docs/dev-portal/zudoku/configuration/api-catalog.md +108 -0
- package/docs/dev-portal/zudoku/configuration/api-reference.md +397 -0
- package/docs/dev-portal/zudoku/configuration/authentication-auth0.md +173 -0
- package/docs/dev-portal/zudoku/configuration/authentication-azure-ad.md +238 -0
- package/docs/dev-portal/zudoku/configuration/authentication-clerk.md +110 -0
- package/docs/dev-portal/zudoku/configuration/authentication-firebase.md +61 -0
- package/docs/dev-portal/zudoku/configuration/authentication-pingfederate.md +136 -0
- package/docs/dev-portal/zudoku/configuration/authentication-supabase.md +225 -0
- package/docs/dev-portal/zudoku/configuration/authentication.md +199 -0
- package/docs/dev-portal/zudoku/configuration/build-configuration.mdx +147 -0
- package/docs/dev-portal/zudoku/configuration/docs.md +282 -0
- package/docs/dev-portal/zudoku/configuration/footer.mdx +214 -0
- package/docs/dev-portal/zudoku/configuration/llms.md +89 -0
- package/docs/dev-portal/zudoku/configuration/navigation.mdx +408 -0
- package/docs/dev-portal/zudoku/configuration/overview.md +380 -0
- package/docs/dev-portal/zudoku/configuration/protected-routes.md +149 -0
- package/docs/dev-portal/zudoku/configuration/search.md +169 -0
- package/docs/dev-portal/zudoku/configuration/sentry.mdx +44 -0
- package/docs/dev-portal/zudoku/configuration/site.md +124 -0
- package/docs/dev-portal/zudoku/configuration/slots.mdx +124 -0
- package/docs/dev-portal/zudoku/configuration/vite-config.md +18 -0
- package/docs/dev-portal/zudoku/custom-plugins.md +287 -0
- package/docs/dev-portal/zudoku/customization/colors-theme.mdx +275 -0
- package/docs/dev-portal/zudoku/customization/fonts.md +110 -0
- package/docs/dev-portal/zudoku/extending/events.md +124 -0
- package/docs/dev-portal/zudoku/guides/custom-pages.md +106 -0
- package/docs/dev-portal/zudoku/guides/environment-variables.md +99 -0
- package/docs/dev-portal/zudoku/guides/mermaid.mdx +70 -0
- package/docs/dev-portal/zudoku/guides/navigation-migration.md +87 -0
- package/docs/dev-portal/zudoku/guides/navigation-rules.mdx +197 -0
- package/docs/dev-portal/zudoku/guides/processors.mdx +234 -0
- package/docs/dev-portal/zudoku/guides/static-files.md +55 -0
- package/docs/dev-portal/zudoku/guides/transforming-examples.md +156 -0
- package/docs/dev-portal/zudoku/guides/using-multiple-apis.md +87 -0
- package/docs/dev-portal/zudoku/markdown/admonitions.md +128 -0
- package/docs/dev-portal/zudoku/markdown/code-blocks.md +196 -0
- package/docs/dev-portal/zudoku/markdown/frontmatter.md +172 -0
- package/docs/dev-portal/zudoku/markdown/mdx.md +68 -0
- package/docs/dev-portal/zudoku/markdown/overview.md +275 -0
- package/docs/dev-portal/zudoku/plugins.md +5 -0
- package/docs/dev-portal/zudoku/writing.mdx +72 -0
- package/docs/errors/bad-request.mdx +39 -0
- package/docs/errors/build-error.mdx +45 -0
- package/docs/errors/fatal-project-error.mdx +39 -0
- package/docs/errors/gateway-timeout.mdx +33 -0
- package/docs/errors/get-head-body-error.mdx +41 -0
- package/docs/errors/main-mod-error.mdx +40 -0
- package/docs/errors/no-project-set.mdx +41 -0
- package/docs/errors/not-found.mdx +43 -0
- package/docs/errors/rate-limit-exceeded.mdx +31 -0
- package/docs/errors/schema-validation-failed.mdx +51 -0
- package/docs/errors/system-configuration-error.mdx +44 -0
- package/docs/errors/unauthorized.mdx +50 -0
- package/docs/errors/unknown-error.mdx +42 -0
- package/docs/errors.mdx +14 -0
- package/docs/guides/canary-routing-for-employees.mdx +385 -0
- package/docs/guides/geolocation-backend-routing.mdx +404 -0
- package/docs/guides/modify-openapi-paths.mdx +371 -0
- package/docs/guides/openapi-overlays.mdx +492 -0
- package/docs/guides/overview.mdx +12 -0
- package/docs/guides/user-based-backend-routing.mdx +437 -0
- package/docs/handlers/aws-lambda.mdx +201 -0
- package/docs/handlers/custom-handler.mdx +112 -0
- package/docs/handlers/legacy-dev-portal-handler.mdx +135 -0
- package/docs/handlers/mcp-server.mdx +730 -0
- package/docs/handlers/openapi.mdx +78 -0
- package/docs/handlers/redirect.mdx +115 -0
- package/docs/handlers/system-handlers.mdx +41 -0
- package/docs/handlers/url-forward.mdx +204 -0
- package/docs/handlers/url-rewrite.mdx +224 -0
- package/docs/handlers/websocket-handler.mdx +154 -0
- package/docs/home.mdx +6 -0
- package/docs/managed-edge/overview.md +78 -0
- package/docs/mcp-server/configuration-migration-guide.mdx +344 -0
- package/docs/mcp-server/custom-tools.mdx +487 -0
- package/docs/mcp-server/graphql.mdx +241 -0
- package/docs/mcp-server/introduction.mdx +122 -0
- package/docs/mcp-server/openai-apps-sdk.mdx +160 -0
- package/docs/mcp-server/prompts.mdx +283 -0
- package/docs/mcp-server/resources.mdx +288 -0
- package/docs/mcp-server/testing.mdx +53 -0
- package/docs/mcp-server/tools.mdx +306 -0
- package/docs/policies/_index.md +92 -0
- package/docs/policies/ab-test-inbound/intro.md +8 -0
- package/docs/policies/ab-test-inbound/policy.ts +14 -0
- package/docs/policies/ab-test-inbound/schema.json +27 -0
- package/docs/policies/ab-test-outbound/intro.md +8 -0
- package/docs/policies/ab-test-outbound/policy.ts +26 -0
- package/docs/policies/ab-test-outbound/schema.json +27 -0
- package/docs/policies/acl-policy-inbound/intro.md +5 -0
- package/docs/policies/acl-policy-inbound/policy.ts +32 -0
- package/docs/policies/acl-policy-inbound/schema.json +52 -0
- package/docs/policies/akamai-ai-firewall/schema.json +98 -0
- package/docs/policies/amberflo-metering-inbound/doc.md +183 -0
- package/docs/policies/amberflo-metering-inbound/intro.md +20 -0
- package/docs/policies/amberflo-metering-inbound/schema.json +108 -0
- package/docs/policies/api-key-inbound/doc.md +77 -0
- package/docs/policies/api-key-inbound/intro.md +30 -0
- package/docs/policies/api-key-inbound/schema.json +84 -0
- package/docs/policies/archive-request-aws-s3-inbound/intro.md +4 -0
- package/docs/policies/archive-request-aws-s3-inbound/policy.ts +58 -0
- package/docs/policies/archive-request-aws-s3-inbound/schema.json +68 -0
- package/docs/policies/archive-request-azure-storage-inbound/doc.md +31 -0
- package/docs/policies/archive-request-azure-storage-inbound/intro.md +4 -0
- package/docs/policies/archive-request-azure-storage-inbound/policy.ts +54 -0
- package/docs/policies/archive-request-azure-storage-inbound/schema.json +53 -0
- package/docs/policies/archive-request-gcp-storage-inbound/doc.md +63 -0
- package/docs/policies/archive-request-gcp-storage-inbound/intro.md +4 -0
- package/docs/policies/archive-request-gcp-storage-inbound/policy.ts +68 -0
- package/docs/policies/archive-request-gcp-storage-inbound/schema.json +47 -0
- package/docs/policies/archive-response-aws-s3-outbound/intro.md +2 -0
- package/docs/policies/archive-response-aws-s3-outbound/policy.ts +59 -0
- package/docs/policies/archive-response-aws-s3-outbound/schema.json +68 -0
- package/docs/policies/archive-response-azure-storage-outbound/doc.md +31 -0
- package/docs/policies/archive-response-azure-storage-outbound/intro.md +3 -0
- package/docs/policies/archive-response-azure-storage-outbound/policy.ts +54 -0
- package/docs/policies/archive-response-azure-storage-outbound/schema.json +53 -0
- package/docs/policies/audit-log-inbound/doc.md +78 -0
- package/docs/policies/audit-log-inbound/intro.md +10 -0
- package/docs/policies/audit-log-inbound/schema.json +81 -0
- package/docs/policies/auth0-jwt-auth-inbound/doc.md +125 -0
- package/docs/policies/auth0-jwt-auth-inbound/intro.md +17 -0
- package/docs/policies/auth0-jwt-auth-inbound/schema.json +74 -0
- package/docs/policies/authzen-inbound/doc.md +24 -0
- package/docs/policies/authzen-inbound/intro.md +31 -0
- package/docs/policies/authzen-inbound/schema.json +126 -0
- package/docs/policies/axiomatics-authz-inbound/doc.md +144 -0
- package/docs/policies/axiomatics-authz-inbound/intro.md +11 -0
- package/docs/policies/axiomatics-authz-inbound/schema.json +161 -0
- package/docs/policies/basic-auth-inbound/intro.md +9 -0
- package/docs/policies/basic-auth-inbound/schema.json +99 -0
- package/docs/policies/bot-detection-inbound/intro.md +4 -0
- package/docs/policies/bot-detection-inbound/schema.json +56 -0
- package/docs/policies/brownout-inbound/doc.md +55 -0
- package/docs/policies/brownout-inbound/intro.md +12 -0
- package/docs/policies/brownout-inbound/schema.json +115 -0
- package/docs/policies/caching-inbound/doc.md +209 -0
- package/docs/policies/caching-inbound/intro.md +23 -0
- package/docs/policies/caching-inbound/schema.json +98 -0
- package/docs/policies/change-method-inbound/schema.json +56 -0
- package/docs/policies/clear-headers-inbound/schema.json +59 -0
- package/docs/policies/clear-headers-outbound/schema.json +59 -0
- package/docs/policies/clerk-jwt-auth-inbound/doc.md +85 -0
- package/docs/policies/clerk-jwt-auth-inbound/intro.md +4 -0
- package/docs/policies/clerk-jwt-auth-inbound/schema.json +68 -0
- package/docs/policies/cognito-jwt-auth-inbound/intro.md +7 -0
- package/docs/policies/cognito-jwt-auth-inbound/schema.json +74 -0
- package/docs/policies/comet-opik-tracing-inbound/schema.json +65 -0
- package/docs/policies/complex-rate-limit-inbound/doc.md +20 -0
- package/docs/policies/complex-rate-limit-inbound/intro.md +23 -0
- package/docs/policies/complex-rate-limit-inbound/schema.json +142 -0
- package/docs/policies/composite-inbound/doc.md +69 -0
- package/docs/policies/composite-inbound/intro.md +15 -0
- package/docs/policies/composite-inbound/schema.json +59 -0
- package/docs/policies/composite-outbound/intro.md +6 -0
- package/docs/policies/composite-outbound/schema.json +59 -0
- package/docs/policies/curity-phantom-token-inbound/doc.md +109 -0
- package/docs/policies/curity-phantom-token-inbound/intro.md +3 -0
- package/docs/policies/curity-phantom-token-inbound/schema.json +68 -0
- package/docs/policies/custom-code-inbound/doc.md +267 -0
- package/docs/policies/custom-code-inbound/intro.md +2 -0
- package/docs/policies/custom-code-inbound/schema.json +48 -0
- package/docs/policies/custom-code-outbound/doc.md +235 -0
- package/docs/policies/custom-code-outbound/intro.md +2 -0
- package/docs/policies/custom-code-outbound/schema.json +43 -0
- package/docs/policies/firebase-jwt-inbound/intro.md +6 -0
- package/docs/policies/firebase-jwt-inbound/schema.json +68 -0
- package/docs/policies/formdata-to-json-inbound/schema.json +60 -0
- package/docs/policies/galileo-tracing-inbound/schema.json +65 -0
- package/docs/policies/geo-filter-inbound/doc.md +33 -0
- package/docs/policies/geo-filter-inbound/schema.json +108 -0
- package/docs/policies/graphql-complexity-limit-inbound/doc.md +48 -0
- package/docs/policies/graphql-complexity-limit-inbound/intro.md +2 -0
- package/docs/policies/graphql-complexity-limit-inbound/schema.json +90 -0
- package/docs/policies/graphql-disable-introspection-inbound/doc.md +66 -0
- package/docs/policies/graphql-disable-introspection-inbound/intro.md +15 -0
- package/docs/policies/graphql-disable-introspection-inbound/schema.json +48 -0
- package/docs/policies/graphql-introspection-filter-outbound/doc.md +148 -0
- package/docs/policies/graphql-introspection-filter-outbound/schema.json +79 -0
- package/docs/policies/hmac-auth-inbound/doc.md +30 -0
- package/docs/policies/hmac-auth-inbound/intro.md +10 -0
- package/docs/policies/hmac-auth-inbound/policy.ts +70 -0
- package/docs/policies/hmac-auth-inbound/schema.json +53 -0
- package/docs/policies/http-deprecation-outbound/doc.md +73 -0
- package/docs/policies/http-deprecation-outbound/schema.json +83 -0
- package/docs/policies/ip-restriction-inbound/intro.md +8 -0
- package/docs/policies/ip-restriction-inbound/policy.ts +40 -0
- package/docs/policies/ip-restriction-inbound/schema.json +58 -0
- package/docs/policies/jwt-scopes-inbound/schema.json +59 -0
- package/docs/policies/ldap-auth-inbound/schema.json +56 -0
- package/docs/policies/mock-api-inbound/schema.json +72 -0
- package/docs/policies/moesif-inbound/doc.md +44 -0
- package/docs/policies/moesif-inbound/intro.md +6 -0
- package/docs/policies/moesif-inbound/schema.json +68 -0
- package/docs/policies/monetization-inbound/doc.md +87 -0
- package/docs/policies/monetization-inbound/intro.md +6 -0
- package/docs/policies/monetization-inbound/schema.json +102 -0
- package/docs/policies/mtls-auth-inbound/intro.md +6 -0
- package/docs/policies/mtls-auth-inbound/schema.json +68 -0
- package/docs/policies/okta-fga-authz-inbound/doc.md +181 -0
- package/docs/policies/okta-fga-authz-inbound/intro.md +20 -0
- package/docs/policies/okta-fga-authz-inbound/schema.json +104 -0
- package/docs/policies/okta-jwt-auth-inbound/intro.md +7 -0
- package/docs/policies/okta-jwt-auth-inbound/schema.json +74 -0
- package/docs/policies/open-id-jwt-auth-inbound/doc.md +58 -0
- package/docs/policies/open-id-jwt-auth-inbound/intro.md +30 -0
- package/docs/policies/open-id-jwt-auth-inbound/schema.json +128 -0
- package/docs/policies/openfga-authz-inbound/doc.md +207 -0
- package/docs/policies/openfga-authz-inbound/intro.md +17 -0
- package/docs/policies/openfga-authz-inbound/schema.json +191 -0
- package/docs/policies/openmeter-inbound/doc.md +163 -0
- package/docs/policies/openmeter-inbound/intro.md +18 -0
- package/docs/policies/openmeter-inbound/schema.json +183 -0
- package/docs/policies/prompt-injection-outbound/doc.md +106 -0
- package/docs/policies/prompt-injection-outbound/intro.md +4 -0
- package/docs/policies/prompt-injection-outbound/schema.json +74 -0
- package/docs/policies/propel-auth-jwt-inbound/doc.md +88 -0
- package/docs/policies/propel-auth-jwt-inbound/intro.md +4 -0
- package/docs/policies/propel-auth-jwt-inbound/schema.json +74 -0
- package/docs/policies/query-param-to-header-inbound/doc.md +70 -0
- package/docs/policies/query-param-to-header-inbound/intro.md +5 -0
- package/docs/policies/query-param-to-header-inbound/schema.json +74 -0
- package/docs/policies/quota-inbound/doc.md +235 -0
- package/docs/policies/quota-inbound/intro.md +7 -0
- package/docs/policies/quota-inbound/schema.json +133 -0
- package/docs/policies/rate-limit-inbound/doc.md +78 -0
- package/docs/policies/rate-limit-inbound/intro.md +30 -0
- package/docs/policies/rate-limit-inbound/schema.json +134 -0
- package/docs/policies/rbac-policy-inbound/intro.md +3 -0
- package/docs/policies/rbac-policy-inbound/policy.ts +42 -0
- package/docs/policies/rbac-policy-inbound/schema.json +52 -0
- package/docs/policies/readme-metrics-inbound/doc.md +1 -0
- package/docs/policies/readme-metrics-inbound/intro.md +3 -0
- package/docs/policies/readme-metrics-inbound/schema.json +84 -0
- package/docs/policies/remove-headers-inbound/schema.json +59 -0
- package/docs/policies/remove-headers-outbound/schema.json +59 -0
- package/docs/policies/remove-query-params-inbound/schema.json +59 -0
- package/docs/policies/replace-string-outbound/schema.json +69 -0
- package/docs/policies/request-size-limit-inbound/schema.json +60 -0
- package/docs/policies/request-validation-inbound/doc.md +72 -0
- package/docs/policies/request-validation-inbound/intro.md +24 -0
- package/docs/policies/request-validation-inbound/schema.json +98 -0
- package/docs/policies/require-origin-inbound/intro.md +12 -0
- package/docs/policies/require-origin-inbound/schema.json +65 -0
- package/docs/policies/secret-masking-outbound/doc.md +41 -0
- package/docs/policies/secret-masking-outbound/intro.md +13 -0
- package/docs/policies/secret-masking-outbound/schema.json +65 -0
- package/docs/policies/semantic-cache-inbound/doc.md +63 -0
- package/docs/policies/semantic-cache-inbound/intro.md +4 -0
- package/docs/policies/semantic-cache-inbound/schema.json +179 -0
- package/docs/policies/set-body-inbound/intro.md +7 -0
- package/docs/policies/set-body-inbound/schema.json +56 -0
- package/docs/policies/set-headers-inbound/doc.md +41 -0
- package/docs/policies/set-headers-inbound/intro.md +2 -0
- package/docs/policies/set-headers-inbound/schema.json +83 -0
- package/docs/policies/set-headers-outbound/schema.json +83 -0
- package/docs/policies/set-query-params-inbound/schema.json +83 -0
- package/docs/policies/set-status-outbound/schema.json +62 -0
- package/docs/policies/sleep-inbound/schema.json +56 -0
- package/docs/policies/stripe-webhook-verification-inbound/intro.md +2 -0
- package/docs/policies/stripe-webhook-verification-inbound/schema.json +60 -0
- package/docs/policies/supabase-jwt-auth-inbound/doc.md +29 -0
- package/docs/policies/supabase-jwt-auth-inbound/intro.md +12 -0
- package/docs/policies/supabase-jwt-auth-inbound/schema.json +86 -0
- package/docs/policies/transform-body-inbound/intro.md +8 -0
- package/docs/policies/transform-body-inbound/policy.ts +16 -0
- package/docs/policies/transform-body-inbound/schema.json +27 -0
- package/docs/policies/transform-body-outbound/intro.md +8 -0
- package/docs/policies/transform-body-outbound/policy.ts +19 -0
- package/docs/policies/transform-body-outbound/schema.json +27 -0
- package/docs/policies/upstream-azure-ad-service-auth-inbound/doc.md +82 -0
- package/docs/policies/upstream-azure-ad-service-auth-inbound/intro.md +20 -0
- package/docs/policies/upstream-azure-ad-service-auth-inbound/schema.json +84 -0
- package/docs/policies/upstream-firebase-admin-auth-inbound/intro.md +10 -0
- package/docs/policies/upstream-firebase-admin-auth-inbound/schema.json +68 -0
- package/docs/policies/upstream-firebase-user-auth-inbound/intro.md +2 -0
- package/docs/policies/upstream-firebase-user-auth-inbound/schema.json +113 -0
- package/docs/policies/upstream-gcp-federated-auth-inbound/doc.md +139 -0
- package/docs/policies/upstream-gcp-federated-auth-inbound/intro.md +21 -0
- package/docs/policies/upstream-gcp-federated-auth-inbound/schema.json +96 -0
- package/docs/policies/upstream-gcp-jwt-inbound/intro.md +10 -0
- package/docs/policies/upstream-gcp-jwt-inbound/schema.json +62 -0
- package/docs/policies/upstream-gcp-service-auth-inbound/doc.md +132 -0
- package/docs/policies/upstream-gcp-service-auth-inbound/intro.md +25 -0
- package/docs/policies/upstream-gcp-service-auth-inbound/schema.json +95 -0
- package/docs/policies/upstream-zuplo-jwt-auth-inbound/doc.md +213 -0
- package/docs/policies/upstream-zuplo-jwt-auth-inbound/intro.md +16 -0
- package/docs/policies/upstream-zuplo-jwt-auth-inbound/schema.json +101 -0
- package/docs/policies/validate-json-schema-inbound/doc.md +129 -0
- package/docs/policies/validate-json-schema-inbound/intro.md +7 -0
- package/docs/policies/validate-json-schema-inbound/schema.json +56 -0
- package/docs/policies/web-bot-auth-inbound/doc.md +104 -0
- package/docs/policies/web-bot-auth-inbound/intro.md +16 -0
- package/docs/policies/web-bot-auth-inbound/schema.json +76 -0
- package/docs/policies/xml-to-json-outbound/doc.md +71 -0
- package/docs/policies/xml-to-json-outbound/intro.md +4 -0
- package/docs/policies/xml-to-json-outbound/schema.json +117 -0
- package/docs/programmable-api/audit-log.mdx +74 -0
- package/docs/programmable-api/background-dispatcher.mdx +124 -0
- package/docs/programmable-api/background-loader.mdx +104 -0
- package/docs/programmable-api/cache.mdx +186 -0
- package/docs/programmable-api/compatibility-dates.mdx +201 -0
- package/docs/programmable-api/console-logging.mdx +48 -0
- package/docs/programmable-api/context-data.mdx +127 -0
- package/docs/programmable-api/custom-cors-policy.mdx +64 -0
- package/docs/programmable-api/environment.mdx +328 -0
- package/docs/programmable-api/hooks.mdx +569 -0
- package/docs/programmable-api/http-problems.mdx +385 -0
- package/docs/programmable-api/jwt-service-plugin.mdx +420 -0
- package/docs/programmable-api/logger.mdx +223 -0
- package/docs/programmable-api/memory-zone-read-through-cache.mdx +96 -0
- package/docs/programmable-api/node-modules.mdx +67 -0
- package/docs/programmable-api/not-found-handler.mdx +47 -0
- package/docs/programmable-api/oauth-protected-resource-plugin.mdx +46 -0
- package/docs/programmable-api/overview.mdx +213 -0
- package/docs/programmable-api/problem-response-formatter.mdx +183 -0
- package/docs/programmable-api/request-user.mdx +289 -0
- package/docs/programmable-api/reusing-code.mdx +26 -0
- package/docs/programmable-api/route-raw.mdx +55 -0
- package/docs/programmable-api/runtime-behaviors.mdx +25 -0
- package/docs/programmable-api/runtime-errors.mdx +246 -0
- package/docs/programmable-api/runtime-extensions.mdx +340 -0
- package/docs/programmable-api/safely-clone-a-request-or-response.mdx +57 -0
- package/docs/programmable-api/streaming-zone-cache.mdx +155 -0
- package/docs/programmable-api/web-crypto-apis.mdx +219 -0
- package/docs/programmable-api/web-standard-apis.mdx +109 -0
- package/docs/programmable-api/zone-cache.mdx +131 -0
- package/docs/programmable-api/zp-body-removed.mdx +32 -0
- package/docs/programmable-api/zuplo-context.mdx +414 -0
- package/docs/programmable-api/zuplo-id-token.mdx +90 -0
- package/docs/programmable-api/zuplo-json.mdx +91 -0
- package/docs/programmable-api/zuplo-request.mdx +200 -0
- package/docs/sample-apis.mdx +78 -0
- package/docs/self-hosted/overview.md +60 -0
- package/package.json +6 -5
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Testing GitHub Deployments
|
|
3
|
+
sidebar_label: Testing Deployments
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Run your test suite automatically after every Zuplo deployment without replacing
|
|
7
|
+
the built-in GitHub integration. This approach uses GitHub's `deployment_status`
|
|
8
|
+
event to trigger tests after Zuplo finishes deploying.
|
|
9
|
+
|
|
10
|
+
## Why This Approach?
|
|
11
|
+
|
|
12
|
+
Zuplo's GitHub integration already handles deployments perfectly — every push
|
|
13
|
+
deploys automatically with status checks in GitHub. Rather than replacing this
|
|
14
|
+
with custom CI/CD, you can extend it by running tests after each deployment
|
|
15
|
+
completes.
|
|
16
|
+
|
|
17
|
+
This gives you:
|
|
18
|
+
|
|
19
|
+
- **Automatic deployments** — Keep the built-in integration
|
|
20
|
+
- **Post-deploy testing** — Run tests against the live environment
|
|
21
|
+
- **PR checks** — Tests block merging until they pass
|
|
22
|
+
- **No duplicate deploys** — Tests run after Zuplo deploys, not instead of
|
|
23
|
+
|
|
24
|
+
## Setup
|
|
25
|
+
|
|
26
|
+
Create a workflow that triggers on the `deployment_status` event:
|
|
27
|
+
|
|
28
|
+
```yaml title=".github/workflows/test.yaml"
|
|
29
|
+
name: Test Deployment
|
|
30
|
+
|
|
31
|
+
on:
|
|
32
|
+
deployment_status:
|
|
33
|
+
|
|
34
|
+
jobs:
|
|
35
|
+
test:
|
|
36
|
+
# Only run when Zuplo deployment succeeds
|
|
37
|
+
if: |
|
|
38
|
+
github.event.deployment_status.state == 'success' &&
|
|
39
|
+
github.event.deployment_status.environment_url != ''
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
|
|
44
|
+
- uses: actions/setup-node@v4
|
|
45
|
+
with:
|
|
46
|
+
node-version: 20
|
|
47
|
+
|
|
48
|
+
- name: Install dependencies
|
|
49
|
+
run: npm install
|
|
50
|
+
|
|
51
|
+
- name: Run tests
|
|
52
|
+
run:
|
|
53
|
+
npx zuplo test --endpoint ${{
|
|
54
|
+
github.event.deployment_status.environment_url }}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## How It Works
|
|
58
|
+
|
|
59
|
+
1. You push code to GitHub
|
|
60
|
+
2. Zuplo's integration deploys automatically
|
|
61
|
+
3. Zuplo reports deployment status back to GitHub
|
|
62
|
+
4. The `deployment_status` event triggers your workflow
|
|
63
|
+
5. Your tests run against the deployed environment URL
|
|
64
|
+
6. Test results appear as a check on the commit/PR
|
|
65
|
+
|
|
66
|
+
The `environment_url` from the deployment status contains your Zuplo environment
|
|
67
|
+
URL, so tests always run against the correct environment.
|
|
68
|
+
|
|
69
|
+
## Filtering by Environment
|
|
70
|
+
|
|
71
|
+
To only test specific environments (like staging or production):
|
|
72
|
+
|
|
73
|
+
```yaml
|
|
74
|
+
jobs:
|
|
75
|
+
test:
|
|
76
|
+
if: |
|
|
77
|
+
github.event.deployment_status.state == 'success' &&
|
|
78
|
+
github.event.deployment_status.environment == 'production'
|
|
79
|
+
# ...
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Adding to PR Checks
|
|
83
|
+
|
|
84
|
+
GitHub automatically shows deployment status checks on pull requests. Your test
|
|
85
|
+
workflow results appear alongside them, giving reviewers confidence that both
|
|
86
|
+
deployment and tests succeeded.
|
|
87
|
+
|
|
88
|
+
## When to Use Custom CI/CD Instead
|
|
89
|
+
|
|
90
|
+
This approach works great when you want to:
|
|
91
|
+
|
|
92
|
+
- Keep automatic deployments
|
|
93
|
+
- Run tests after deploy
|
|
94
|
+
- Add PR checks
|
|
95
|
+
|
|
96
|
+
Consider [custom GitHub Actions](./custom-ci-cd-github.mdx) if you need:
|
|
97
|
+
|
|
98
|
+
- Approval gates before production
|
|
99
|
+
- Multi-stage deployments (staging → production)
|
|
100
|
+
- Tests that must pass before any deployment
|
|
101
|
+
- Tag-based or release-based deployments
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Secure a GCP Backend with Zuplo Upstream Auth
|
|
3
|
+
sidebar_label: GCP Backend with Upstream Auth
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
When using any API gateway as your API's entry point, it's critical that only
|
|
7
|
+
traffic that originates from the Gateway is allowed to call your backend. There
|
|
8
|
+
are [many way to this](./securing-your-backend.mdx) depending on your
|
|
9
|
+
requirements and how your backend is hosted. This article will explain how to
|
|
10
|
+
use Google IAM to secure a GKE cluster so that only requests made through your
|
|
11
|
+
Zuplo API Gateway will be allowed to call your GKE ingress.
|
|
12
|
+
|
|
13
|
+
Using GCP IAM to authorize your Zuplo Gateway to make requests to your backend
|
|
14
|
+
utilizes Googles core IAM system known as
|
|
15
|
+
"[Identity Aware Proxy](https://cloud.google.com/iap)" to secure public IP
|
|
16
|
+
address from unauthorized access. When correctly configured, this will ensure
|
|
17
|
+
that no unauthorized access makes it to your application.
|
|
18
|
+
|
|
19
|
+
While it's also possible to enforce authorization within your application
|
|
20
|
+
itself - for example using JWT Authentication. The key difference is that by
|
|
21
|
+
using your Cloud providers identity and authorization system, you are ensuring
|
|
22
|
+
that unauthorized requests are blocked before they even touch your backend. This
|
|
23
|
+
provides protection from any potential security vulnerabilities in your core,
|
|
24
|
+
web server, or operating system.
|
|
25
|
+
|
|
26
|
+
:::note
|
|
27
|
+
|
|
28
|
+
This article uses GKE as the example backend, but any GCP service that can be
|
|
29
|
+
set up behind an HTTP Load Balancer can be used.
|
|
30
|
+
|
|
31
|
+
:::
|
|
32
|
+
|
|
33
|
+
The diagram below shows how the end-to-end system interacts. The important steps
|
|
34
|
+
to this process are:
|
|
35
|
+
|
|
36
|
+
1. The client makes a request to your Zuplo API Gateway
|
|
37
|
+
1. The Zuplo API Gateway enforces any policies (for example authentication,
|
|
38
|
+
authorization, rate limiting)
|
|
39
|
+
1. The Zuplo API Gateway proxies the request to the public IP address of your
|
|
40
|
+
GCP Load Balancer. Zuplo adds authorization information to the request that
|
|
41
|
+
identify the request as coming from Zuplo
|
|
42
|
+
1. GCP Identity Aware proxy validates that the request comes from an authorized
|
|
43
|
+
Service Account identity. Unauthorized requests are rejected.
|
|
44
|
+
1. Authorized requests are forwarded on through your GKE ingress to your
|
|
45
|
+
backend.
|
|
46
|
+
|
|
47
|
+

|
|
48
|
+
|
|
49
|
+
## Zuplo Gateway Identity
|
|
50
|
+
|
|
51
|
+
Requests that are proxied from Zuplo to your GCP Load Balancer use the
|
|
52
|
+
[Upstream GCP Service Auth Policy](../policies/upstream-gcp-service-auth-inbound.mdx)
|
|
53
|
+
to authenticate the request via a
|
|
54
|
+
[GCP Service Account](https://cloud.google.com/iam/docs/service-account-overview).
|
|
55
|
+
The policy appends an `authorization` header to the request that the GCP
|
|
56
|
+
Identity Aware Proxy uses to determine if the request is authorized or not.
|
|
57
|
+
|
|
58
|
+
Using this system means that you can uniquely identify requests that come from
|
|
59
|
+
Zuplo as a their own identity. This means all request logs can be identified by
|
|
60
|
+
their source - for example your Zuplo Gateway, another system also using a GCP
|
|
61
|
+
Service account, a developer testing an internal system, etc.
|
|
62
|
+
|
|
63
|
+
:::tip{title="Multiple Service Account"}
|
|
64
|
+
|
|
65
|
+
While not normally needed, it's possible to configure multiple Upstream GCP
|
|
66
|
+
Service Auth Inbound policies in order to provide fine-grain authorization to
|
|
67
|
+
your internal resources by Service Account. For example, if you had two Zuplo
|
|
68
|
+
projects - one for external users and one for internal users - each could use
|
|
69
|
+
its own identity.
|
|
70
|
+
|
|
71
|
+
:::
|
|
72
|
+
|
|
73
|
+
For instructions on how to configure upstream GCP IAM auth, see the
|
|
74
|
+
[Upstream GCP Service Auth Policy document](../policies/upstream-gcp-service-auth-inbound.mdx)
|
|
75
|
+
|
|
76
|
+
## GCP Configuration
|
|
77
|
+
|
|
78
|
+
Documentation on configuring GCP Identity Aware Proxy can be found on Google's
|
|
79
|
+
documentation. Below are a few links on how to configure the proxy with several
|
|
80
|
+
common backends.
|
|
81
|
+
|
|
82
|
+
- [Enabling IAP for Compute Engine](https://cloud.google.com/iap/docs/enabling-compute-howto)
|
|
83
|
+
- [Enabling IAP for GKE](https://cloud.google.com/iap/docs/enabling-kubernetes-howto)
|
|
84
|
+
- [Enabling IAP for Cloud Run](https://cloud.google.com/iap/docs/enabling-cloud-run)
|
|
85
|
+
|
|
86
|
+
:::tip{title="Cloud Run"}
|
|
87
|
+
|
|
88
|
+
Cloud Run doesn't need to use IAP in all cases. It's possible to restrict Cloud
|
|
89
|
+
Run to
|
|
90
|
+
[require IAM authentication in order to invoke the service](https://cloud.google.com/run/docs/securing/managing-access).
|
|
91
|
+
|
|
92
|
+
:::
|
|
93
|
+
|
|
94
|
+
## Example
|
|
95
|
+
|
|
96
|
+
To see how this works in action, follow the steps in Google's document
|
|
97
|
+
_[Set up an external Application Load Balancer with Ingress](https://cloud.google.com/kubernetes-engine/docs/tutorials/http-balancer)_.
|
|
98
|
+
This will configure a GKE cluster with a simple "hello world" web application
|
|
99
|
+
behind an HTTP Load Balancer. At the end of the tutorial, you should have a
|
|
100
|
+
public IP address that serves a simple web application.
|
|
101
|
+
|
|
102
|
+
You can test the request with a simple curl command.
|
|
103
|
+
|
|
104
|
+
```shell
|
|
105
|
+
curl http://34.111.91.10/
|
|
106
|
+
Hello, world!
|
|
107
|
+
Version: 1.0.0
|
|
108
|
+
Hostname: web-58756b54cc-7hdcw
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
In order to securely proxy traffic from Zuplo to GCP, you'll need to secure your
|
|
112
|
+
traffic over an SSL connection. Navigate to the GCP portal to manage your
|
|
113
|
+
[load balancer](https://console.cloud.google.com/net-services/loadbalancing/list/loadBalancers)
|
|
114
|
+
and select the load balancer that was created previously. Click, **Edit** on the
|
|
115
|
+
load balancer.
|
|
116
|
+
|
|
117
|
+

|
|
118
|
+
|
|
119
|
+
Next, click **ADD FRONTEND IP AND PORT**. Enter the name and select **HTTPS** as
|
|
120
|
+
the protocol.
|
|
121
|
+
|
|
122
|
+

|
|
123
|
+
|
|
124
|
+
Then click **Add a Certificate**. Select Google-managed Certificate and enter
|
|
125
|
+
your domain name.
|
|
126
|
+
|
|
127
|
+

|
|
128
|
+
|
|
129
|
+
Next, select **Host and path rules** and enter the domain and associate it with
|
|
130
|
+
the backend.
|
|
131
|
+
|
|
132
|
+

|
|
133
|
+
|
|
134
|
+
Click **Done** and then **Update** to update your Load Balancer. It will take a
|
|
135
|
+
few minutes to issue the SSL certificate for the domain.
|
|
136
|
+
|
|
137
|
+
After the Load Balancer updates you should be able to request your site using
|
|
138
|
+
the configured domain via HTTPS.
|
|
139
|
+
|
|
140
|
+
```shell
|
|
141
|
+
curl https://api.example.com
|
|
142
|
+
Hello, world!
|
|
143
|
+
Version: 1.0.0
|
|
144
|
+
Hostname: web-58756b54cc-7hdcw
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
:::tip{title="Checkpoint"}
|
|
148
|
+
|
|
149
|
+
At this point, your backend on GKE is exposed on the public internet via a GCP
|
|
150
|
+
HTTP Load Balancer via HTTP and HTTPS. For this demo, we won't go through the
|
|
151
|
+
changes, but in production you shouldn't expose an HTTP endpoint on your API.
|
|
152
|
+
|
|
153
|
+
:::
|
|
154
|
+
|
|
155
|
+
### Enabling Identity Aware Proxy
|
|
156
|
+
|
|
157
|
+
To enable Identity Aware Proxy on your Load Balancer, follow googles document
|
|
158
|
+
_[Enabling IAP for GKE](https://cloud.google.com/iap/docs/enabling-kubernetes-howto)_
|
|
159
|
+
|
|
160
|
+
After you have enabled IAP, if you try to open your example API in the browser
|
|
161
|
+
you will now be prompted to authenticate using your Google Account. If you do so
|
|
162
|
+
you be shown a screen that blocks access to the application.
|
|
163
|
+
|
|
164
|
+

|
|
165
|
+
|
|
166
|
+
Your API is now completely inaccessible to unauthorized requests.
|
|
167
|
+
|
|
168
|
+
In order to allow your Zuplo Gateway access you need to
|
|
169
|
+
[grant its service account permission](https://cloud.google.com/iap/docs/managing-access)
|
|
170
|
+
to call the IAP protected API.
|
|
171
|
+
|
|
172
|
+

|
|
173
|
+
|
|
174
|
+
### Authorize Zuplo to Call the API
|
|
175
|
+
|
|
176
|
+
The last thing required is to configure Zuplo with a service account and policy
|
|
177
|
+
so that it can securely call your API. Follow the instructions on the
|
|
178
|
+
[Upstream GCP Service Auth Policy document](../policies/upstream-gcp-service-auth-inbound.mdx)
|
|
179
|
+
to set up the policy.
|
|
180
|
+
|
|
181
|
+
With the policy setup, create a route in your Zuplo portal that points to your
|
|
182
|
+
API. When you make a request you will once again see a successful response.
|
|
183
|
+
|
|
184
|
+
```shell
|
|
185
|
+
curl https://zuplo-gateway.example.com
|
|
186
|
+
Hello, world!
|
|
187
|
+
Version: 1.0.0
|
|
188
|
+
Hostname: web-58756b54cc-7hdcw
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
You can now add additional policies on Zuplo in order to authenticate requests,
|
|
192
|
+
add rate limiting, etc.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Secure your GraphQL API with Zuplo
|
|
3
|
+
sidebar_label: Secure your GraphQL API
|
|
4
|
+
description:
|
|
5
|
+
Learn how to secure your GraphQL API using Zuplo's security policies to
|
|
6
|
+
prevent DoS attacks and protect schema information.
|
|
7
|
+
tags:
|
|
8
|
+
- authentication
|
|
9
|
+
- backends
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
**Secure your GraphQL API with Zuplo**
|
|
13
|
+
|
|
14
|
+
GraphQL is a powerful query language for your APIs. While it offers great
|
|
15
|
+
flexibility for clients, it also exposes potential security risks. Fortunately,
|
|
16
|
+
with Zuplo, you can secure your GraphQL API by implementing various policies.
|
|
17
|
+
This article walks you through our security policies:
|
|
18
|
+
[GraphQL Complexity Limit](/docs/policies/graphql-complexity-limit-inbound), and
|
|
19
|
+
[GraphQL Disable Introspection](/docs/policies/graphql-disable-introspection-inbound).
|
|
20
|
+
|
|
21
|
+
## 1. Understanding the Risks
|
|
22
|
+
|
|
23
|
+
### a. Deeply Nested Queries
|
|
24
|
+
|
|
25
|
+
Without restrictions, a client can send deeply nested queries that could
|
|
26
|
+
potentially overwhelm your server, resulting in a Denial of Service (DoS)
|
|
27
|
+
attack. This is because deeply nested queries can cause the server to process a
|
|
28
|
+
huge amount of data and operations. While this might be a planned attack, it
|
|
29
|
+
could also be a mistake by a client who is unaware of the query depth limit.
|
|
30
|
+
|
|
31
|
+
### b. Query Complexity
|
|
32
|
+
|
|
33
|
+
Even without deep nesting, a query can be crafted to be very complex. This could
|
|
34
|
+
force your server to execute resource-intensive operations, potentially slowing
|
|
35
|
+
down the system or causing a DoS.
|
|
36
|
+
|
|
37
|
+
### c. Introspection
|
|
38
|
+
|
|
39
|
+
GraphQL allows clients to introspect your schema. While this is beneficial
|
|
40
|
+
during development, it can expose detailed schema information to potential
|
|
41
|
+
attackers in production.
|
|
42
|
+
|
|
43
|
+
## 2. Add your GraphQL API & setting up Policies
|
|
44
|
+
|
|
45
|
+
### Set Up POST Endpoint
|
|
46
|
+
|
|
47
|
+
If you didn't already do so, you need to set up a POST endpoint in your API.
|
|
48
|
+
This endpoint will be used to send the GraphQL queries to your API. The
|
|
49
|
+
urlRewriteHandler to rewrite the request to your GraphQL API. For this example
|
|
50
|
+
let's assume your GraphQL API is hosted at `https://api.example.com/graphql`.
|
|
51
|
+
|
|
52
|
+
To do so, add the following to your `config/routes.oas.json`
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"post": {
|
|
57
|
+
"summary": "GraphQL Query",
|
|
58
|
+
"description": "The endpoint for GraphQL queries.",
|
|
59
|
+
"x-zuplo-route": {
|
|
60
|
+
"corsPolicy": "none",
|
|
61
|
+
"handler": {
|
|
62
|
+
"export": "urlRewriteHandler",
|
|
63
|
+
"module": "$import(@zuplo/runtime)",
|
|
64
|
+
"options": {
|
|
65
|
+
"rewritePattern": "https://api.example.com/graphql"
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"policies": {
|
|
69
|
+
"inbound": [
|
|
70
|
+
"graphql-complexity-limit-policy",
|
|
71
|
+
"graphql-disable-introspection-policy"
|
|
72
|
+
]
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
"operationId": "52bdf225-eaa7-441c-afb9-b7df046a142e"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
For all the risks mentioned above, Zuplo offers policies that can be configured
|
|
81
|
+
to protect your GraphQL API. These policies can be configured for Zuplo. We'll
|
|
82
|
+
create the configuration for the three policies `graphql-depth-limit`,
|
|
83
|
+
`graphql-complexity-points` and `graphql-disable-introspection-policy` next.
|
|
84
|
+
|
|
85
|
+
### a. GraphQL Depth Limit
|
|
86
|
+
|
|
87
|
+
This policy limits how deep a query can be nested. Check our
|
|
88
|
+
[detailed policy documentation](/docs/policies/graphql-complexity-limit-inbound)
|
|
89
|
+
for more information.
|
|
90
|
+
|
|
91
|
+
Add this into your `config/policies.json`
|
|
92
|
+
|
|
93
|
+
```json
|
|
94
|
+
{
|
|
95
|
+
"policies": [
|
|
96
|
+
{
|
|
97
|
+
"name": "graphql-complexity-limit-policy",
|
|
98
|
+
"policyType": "graphql-complexity-limit-inbound",
|
|
99
|
+
"handler": {
|
|
100
|
+
"export": "GraphQLComplexityLimitInboundPolicy",
|
|
101
|
+
"module": "$import(@zuplo/graphql)",
|
|
102
|
+
"options": {
|
|
103
|
+
"useDepthLimit": {
|
|
104
|
+
"depthLimit": 20
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
By limiting the query depth, you prevent malicious or mistakenly deep queries
|
|
114
|
+
from consuming excessive server resources.
|
|
115
|
+
|
|
116
|
+
### b. GraphQL Complexity Limit
|
|
117
|
+
|
|
118
|
+
We can extend the same policy to also check for complexity. By defining a max
|
|
119
|
+
for each type of operation, and then it limits the total complexity a query can
|
|
120
|
+
have. In order to use the Complexity Limit you need to allow introspection in
|
|
121
|
+
your GraphQL API.
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"policies": [
|
|
126
|
+
{
|
|
127
|
+
"name": "graphql-complexity-limit-policy",
|
|
128
|
+
"policyType": "graphql-complexity-limit-inbound",
|
|
129
|
+
"handler": {
|
|
130
|
+
"export": "GraphQLComplexityLimitInboundPolicy",
|
|
131
|
+
"module": "$import(@zuplo/graphql)",
|
|
132
|
+
"options": {
|
|
133
|
+
"useDepthLimit": {
|
|
134
|
+
"depthLimit": 20
|
|
135
|
+
},
|
|
136
|
+
"useComplexityLimit": {
|
|
137
|
+
"complexityLimit": 50,
|
|
138
|
+
"endpointUrl": "https://api.example.com/graphql"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The complexity limit ensures that a potential attacker can't overload the system
|
|
148
|
+
by sending overly complicated queries.
|
|
149
|
+
|
|
150
|
+
### c. GraphQL Disable Introspection
|
|
151
|
+
|
|
152
|
+
Disable introspection in production environments to hide schema details.
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"policies": [
|
|
157
|
+
{
|
|
158
|
+
"name": "graphql-disable-introspection-policy",
|
|
159
|
+
"policyType": "graphql-disable-introspection-inbound",
|
|
160
|
+
"handler": {
|
|
161
|
+
"export": "GraphQLDisableIntrospectionInboundPolicy",
|
|
162
|
+
"module": "$import(@zuplo/graphql)",
|
|
163
|
+
"options": {}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
]
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
By disabling introspection in production, you prevent attackers from gaining
|
|
171
|
+
insights into your GraphQL schema, thereby reducing potential attack vectors.
|
|
172
|
+
|
|
173
|
+
## 4. Example Repository
|
|
174
|
+
|
|
175
|
+
For those who prefer a hands-on approach or wish to see these configurations in
|
|
176
|
+
action, there is a GitHub repository with everything set up. This repository
|
|
177
|
+
offers a comprehensive example of how to configure and secure a GraphQL API
|
|
178
|
+
using Zuplo. Check out the
|
|
179
|
+
[GraphQL API with Zuplo example repository](https://github.com/zuplo/zuplo-graphql-example)
|
|
180
|
+
to dive deeper.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Handling FormData
|
|
3
|
+
description:
|
|
4
|
+
Learn how to parse multipart/form-data uploads and process file content in
|
|
5
|
+
Zuplo runtime using function handlers.
|
|
6
|
+
tags:
|
|
7
|
+
- request-handling
|
|
8
|
+
- backends
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Zuplo supports working with `FormData` including `multipart/form-data`. In this
|
|
12
|
+
simple example we show how you can parse a multipart entry and read the stream
|
|
13
|
+
into memory for use in the Zuplo runtime.
|
|
14
|
+
|
|
15
|
+
In this case, we upload a JSON file as a multipart/form-data entry using
|
|
16
|
+
Insomnia, with a key `foo`
|
|
17
|
+
|
|
18
|
+

|
|
19
|
+
|
|
20
|
+
We can then handle this programmatically inside Zuplo using a function handler.
|
|
21
|
+
We also modify the JSON before forwarding on to the target backend server.
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { ZuploContext, ZuploRequest } from "@zuplo/runtime";
|
|
25
|
+
|
|
26
|
+
// FormData can return different types in different circumstances
|
|
27
|
+
// use this function to convert both to strings
|
|
28
|
+
async function readFileOrStringContent(data: unknown) {
|
|
29
|
+
if (data.constructor.name === "File") {
|
|
30
|
+
return await (data as File).text();
|
|
31
|
+
}
|
|
32
|
+
return data as string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default async function (request: ZuploRequest, context: ZuploContext) {
|
|
36
|
+
const formData = await request.formData();
|
|
37
|
+
|
|
38
|
+
// read the form-data entry as a 'Blob' type
|
|
39
|
+
const blob = formData.get("foo");
|
|
40
|
+
|
|
41
|
+
// stream the body into memory
|
|
42
|
+
const json = await readFileOrStringContent(blob);
|
|
43
|
+
|
|
44
|
+
// parse the JSON document
|
|
45
|
+
const object = JSON.parse(json);
|
|
46
|
+
|
|
47
|
+
// Modify the document somehow before forwarding on to the backend
|
|
48
|
+
object.newKey = "newValue";
|
|
49
|
+
|
|
50
|
+
// Make a standard POST to a backend with a JSON body
|
|
51
|
+
const response = fetch("https://backend-origin.com/example", {
|
|
52
|
+
method: "POST",
|
|
53
|
+
headers: {
|
|
54
|
+
"content-type": "application/json",
|
|
55
|
+
},
|
|
56
|
+
body: JSON.stringify(object, null, 2),
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return response;
|
|
60
|
+
}
|
|
61
|
+
```
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Health Check Handler
|
|
3
|
+
sidebar_label: Health Checks
|
|
4
|
+
description:
|
|
5
|
+
Learn how to set up health check endpoints to monitor your API Gateway and
|
|
6
|
+
backend services.
|
|
7
|
+
tags:
|
|
8
|
+
- observability
|
|
9
|
+
- backends
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Part of running a reliable API Gateway is ensuring that the service is healthy
|
|
13
|
+
and available. With Zuplo, it's easy to set up a health check endpoint that can
|
|
14
|
+
be used to ensure the health of both your Zuplo Gateway and your backend (as
|
|
15
|
+
well as the connectivity between them).
|
|
16
|
+
|
|
17
|
+
A typical health check endpoint on your API Gateway will exercise some of the
|
|
18
|
+
most important policies (such as authentication) and then make a simple request
|
|
19
|
+
to your backend to ensure that it's reachable and functioning.
|
|
20
|
+
|
|
21
|
+
## Setting up a Health Check Handler
|
|
22
|
+
|
|
23
|
+
To set up a health check handler, you will need to create a new route in your
|
|
24
|
+
Zuplo Gateway. This route will be used to handle health check requests.
|
|
25
|
+
|
|
26
|
+
You'll create a new route with the path `/health` and the method `GET`. In your
|
|
27
|
+
OpenAPI file this would look like:
|
|
28
|
+
|
|
29
|
+
```json title="config/routes.oas.json"
|
|
30
|
+
{
|
|
31
|
+
"paths": {
|
|
32
|
+
"/health": {
|
|
33
|
+
"get": {
|
|
34
|
+
"summary": "Health Check",
|
|
35
|
+
"description": "Checks the health of the API Gateway and backend.",
|
|
36
|
+
"responses": {
|
|
37
|
+
"200": {
|
|
38
|
+
"description": "OK"
|
|
39
|
+
},
|
|
40
|
+
"503": {
|
|
41
|
+
"description": "Service Unavailable"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"x-zuplo-route": {
|
|
45
|
+
"corsPolicy": "anything-goes",
|
|
46
|
+
"handler": {
|
|
47
|
+
"export": "default",
|
|
48
|
+
"module": "$import(./modules/health)"
|
|
49
|
+
},
|
|
50
|
+
"policies": {
|
|
51
|
+
"inbound": ["my-auth-policy"]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Next, you'll create a custom handler module that will be used to process the
|
|
61
|
+
health check requests. This module will make a simple request to your backend to
|
|
62
|
+
ensure that it's reachable and functioning. If you have multiple backend
|
|
63
|
+
services you can check each of them.
|
|
64
|
+
|
|
65
|
+
```ts title="modules/health.ts"
|
|
66
|
+
import { ZuploContext, ZuploRequest, ZuploResponse } from "@zuplo/runtime";
|
|
67
|
+
|
|
68
|
+
export default async function handler(
|
|
69
|
+
request: ZuploRequest,
|
|
70
|
+
context: ZuploContext,
|
|
71
|
+
): Promise<ZuploResponse> {
|
|
72
|
+
try {
|
|
73
|
+
// Make a simple request to the backend to check its health
|
|
74
|
+
const responses = await Promise.allSettled([
|
|
75
|
+
fetch("https://backend-1.example.com/health", {
|
|
76
|
+
method: "GET",
|
|
77
|
+
headers: {
|
|
78
|
+
"Content-Type": "application/json",
|
|
79
|
+
},
|
|
80
|
+
}),
|
|
81
|
+
fetch("https://backend-2.example.com/health", {
|
|
82
|
+
method: "GET",
|
|
83
|
+
headers: {
|
|
84
|
+
"Content-Type": "application/json",
|
|
85
|
+
},
|
|
86
|
+
}),
|
|
87
|
+
]);
|
|
88
|
+
const backendResponse = responses.find(
|
|
89
|
+
(res) => res.status === "fulfilled",
|
|
90
|
+
) as PromiseFulfilledResult<Response> | undefined;
|
|
91
|
+
if (!backendResponse) {
|
|
92
|
+
context.log.error("All backend health checks failed", { responses });
|
|
93
|
+
return new ZuploResponse("Service Unavailable", { status: 503 });
|
|
94
|
+
} else {
|
|
95
|
+
const failedResponses = responses.filter(
|
|
96
|
+
(res) => res.status === "rejected",
|
|
97
|
+
) as PromiseRejectedResult[];
|
|
98
|
+
context.log.error("Backend health check failed", {
|
|
99
|
+
statuses: failedResponses.map((res) => res.reason.status),
|
|
100
|
+
statusText: failedResponses.map((res) => res.reason.statusText),
|
|
101
|
+
});
|
|
102
|
+
return new ZuploResponse("Service Unavailable", { status: 503 });
|
|
103
|
+
}
|
|
104
|
+
} catch (error) {
|
|
105
|
+
context.log.error("Error during health check", { error });
|
|
106
|
+
return new ZuploResponse("Service Unavailable", { status: 503 });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|