[{"content":"Several years ago I was tinkering with AWS API Gateway and reading through the documentation on the Apache Velocity Template Language (VTL) that is used for data transformations. I noticed that one of the built-in variables was $context.identity.sourceIp which contained the client\u0026rsquo;s IP address.1 It occurred to me that I could make one of those \u0026ldquo;what\u0026rsquo;s my IP\u0026rdquo; services by pointing the root of the API gateway at a MOCK integration with a response of type text/plain containing only that variable. No Lambda function was needed. I tried it and it worked as expected. It has been running in one of my accounts for years and I use it in many of my build scripts (there isn\u0026rsquo;t much point to this since AWS has their own at https://checkip.amazonaws.com/).\nIn Terraform (or OpenTofu), the relevant resources look like this:\n# Return caller IP as plain text via API Gateway (no backend) resource \u0026#34;aws_api_gateway_rest_api\u0026#34; \u0026#34;ip\u0026#34; { name = \u0026#34;ip\u0026#34; description = \u0026#34;My IP\u0026#34; endpoint_configuration { types = [\u0026#34;REGIONAL\u0026#34;] } } resource \u0026#34;aws_api_gateway_method\u0026#34; \u0026#34;ip_method_get\u0026#34; { rest_api_id = aws_api_gateway_rest_api.ip.id resource_id = aws_api_gateway_rest_api.ip.root_resource_id http_method = \u0026#34;GET\u0026#34; authorization = \u0026#34;NONE\u0026#34; } resource \u0026#34;aws_api_gateway_integration\u0026#34; \u0026#34;ip_get_integration\u0026#34; { rest_api_id = aws_api_gateway_rest_api.ip.id resource_id = aws_api_gateway_rest_api.ip.root_resource_id http_method = aws_api_gateway_method.ip_method_get.http_method type = \u0026#34;MOCK\u0026#34; passthrough_behavior = \u0026#34;WHEN_NO_MATCH\u0026#34; request_templates = { \u0026#34;application/json\u0026#34; = \u0026#34;{ \\\u0026#34;statusCode\\\u0026#34;: 200 }\u0026#34; \u0026#34;application/xml\u0026#34; = \u0026#34;{ \\\u0026#34;statusCode\\\u0026#34;: 200 }\u0026#34; \u0026#34;application/x-www-form-urlencoded\u0026#34; = \u0026#34;{ \\\u0026#34;statusCode\\\u0026#34;: 200 }\u0026#34; \u0026#34;text/plain\u0026#34; = \u0026#34;{ \\\u0026#34;statusCode\\\u0026#34;: 200 }\u0026#34; } } resource \u0026#34;aws_api_gateway_method_response\u0026#34; \u0026#34;ip_get_method_response_200\u0026#34; { rest_api_id = aws_api_gateway_rest_api.ip.id resource_id = aws_api_gateway_rest_api.ip.root_resource_id http_method = aws_api_gateway_method.ip_method_get.http_method status_code = 200 response_models = { \u0026#34;text/plain\u0026#34; = \u0026#34;Empty\u0026#34; } response_parameters = { \u0026#34;method.response.header.Content-Type\u0026#34; = true } } resource \u0026#34;aws_api_gateway_integration_response\u0026#34; \u0026#34;ip_get_integration_response_200\u0026#34; { rest_api_id = aws_api_gateway_rest_api.ip.id resource_id = aws_api_gateway_rest_api.ip.root_resource_id http_method = aws_api_gateway_method.ip_method_get.http_method status_code = aws_api_gateway_method_response.ip_get_method_response_200.status_code response_templates = { \u0026#34;text/plain\u0026#34; = \u0026#34;$context.identity.sourceIp\\n\u0026#34; } response_parameters = { \u0026#34;method.response.header.Content-Type\u0026#34; = \u0026#34;\u0026#39;text/plain\u0026#39;\u0026#34; } } The IP example is trivial, but the underlying pattern is more broadly useful. API gateway’s mapping layer can read request metadata and generate responses without a backend. In the spirit of serverless computing, I called this computeless servering.2 There are probably a lot of opportunities to provide similarly trivial but useful services using only the intermediary building blocks in various cloud services.\nFrom the perspective of the gateway, not necessarily its real original IP address.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\nYes, technically there is a compute layer. There are servers in serverless computing too.\u0026#160;\u0026#x21a9;\u0026#xfe0e;\n","permalink":"https://absolutereason.io/blog/posts/computeless-servering/","summary":"\u003cp\u003eSeveral years ago I was tinkering with \u003ca href=\"https://aws.amazon.com/api-gateway/\"\u003eAWS API Gateway\u003c/a\u003e and reading through the documentation on the \u003ca href=\"https://velocity.apache.org/engine/2.0/vtl-reference.html\"\u003eApache Velocity Template Language (VTL)\u003c/a\u003e that is used for data transformations. I noticed that one of the \u003ca href=\"https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html\"\u003ebuilt-in variables\u003c/a\u003e was \u003ccode\u003e$context.identity.sourceIp\u003c/code\u003e which contained the client\u0026rsquo;s IP address.\u003csup id=\"fnref:1\"\u003e\u003ca href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\"\u003e1\u003c/a\u003e\u003c/sup\u003e It occurred to me that I could make one of those \u0026ldquo;what\u0026rsquo;s my IP\u0026rdquo; services by pointing the root of the API gateway at a \u003ccode\u003eMOCK\u003c/code\u003e integration with a response of type \u003ccode\u003etext/plain\u003c/code\u003e containing only that variable. No \u003ca href=\"https://aws.amazon.com/lambda/\"\u003eLambda\u003c/a\u003e function was needed. I tried it and it worked as expected. It has been running in one of my accounts for years and I use it in many of my build scripts (there isn\u0026rsquo;t much point to this since AWS has their own at \u003ca href=\"https://checkip.amazonaws.com/)\"\u003ehttps://checkip.amazonaws.com/)\u003c/a\u003e.\u003c/p\u003e","title":"Computeless Servering"}]