How to use a single base URL for multiple services in big serverless applications — SAM, API gateway
Published: 2023-09-23 06:18:37

![A bridge to connect multiple path](https://cdn-images-1.medium.com/max/2048/1*APRBhwhnSCpRYY-MhGc2Pw.png)

When you are working on a big application, you may have to use multiple backend services like authentication, payment, access management, and so on. If your architectural design is based on microservices, then all these services will have their own URL link to connect. But think, what happens when you use those separate links in your frontend code? Then if you want to add one more service to your application, you have to change your frontend routing again. It will complicate your system and add extra hassle.

To solve this problem, you can add an Amazon API gateway proxy which helps you to connect all separate URLs using a single base URL.

Lets think you decide to make an e-commerce application where you will have product service, authentication service, cart management, payment service.

**Backend Services**:

 1. **Product service**: [https://product-service-url](https://product-service-url)

 2. **Authentication service**: [https://auth-service-url](https://product-service-url)

 3. **Cart management**: [https://cart-service-url](https://product-service-url)

 4. **Payment service**: [https://payment-service-url](https://product-service-url)

Now, you do not need to know or manage multiple URLs. API gateway will create a single base URL like **https://single-base-url/prod** and it will route other services with proxy. Create methods and resources for each services and create path like /product, /auth, /cart, /payment. When you use /product after base URL, it will route you to product service, same as for other services.

I created a [github repo](https://github.com/farzana-juthi/sam-nested-stack.git) for this. Follow the steps in README section to see how functionality in product services can be used through a single base URL. You can create other services like product service.

Here I describe what does mean each section of [template.yaml](https://github.com/farzana-juthi/sam-nested-stack/blob/d814c3474d4abe479f54f7f3842f0e7833b91f2e/template.yaml). To create a proxy for each service you need four section:

i) **Serverless application**: To check all syntax and properties of AWS::Serverless::Application, please check this [link](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-application.html).

      ProductStack:
        Type: AWS::Serverless::Application
        Properties:
          Location: product-stack/template.yaml
          Parameters:
            StageName: !Ref StageName 

Here in this section,

    1. ProductStack is logical id of this resource. If you want to create other 
       service you have to give a name of that service. Lets say, you will create 
       an application for auth service, you can name it Authstack. 
    2. Location: It will indicate the nested application code path. 
       You will give the location of your code.
    3. Parameters: If you want to pass any parameters to your cloudformation 
       parameter, then you can pass it here. Here, StageName used for making 
       different state of your project like developement, tesing, production etc. 
       You can pass more parameteres through this section to your nested stack.

ii) **API gateway resource for path**: To check all syntax and properties of AWS::ApiGateway::Resource, check this [link](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-resource.html).

      ProductStackApiResource:
        Type: AWS::ApiGateway::Resource
        Properties:
          ParentId: !GetAtt RootDefaultApi.RootResourceId
          RestApiId: !Ref RootDefaultApi
          PathPart: 'product'  

Here in this section,

    1. Type:AWS::ApiGateway::Resource mean it will create a resource in an API.
    2. ParentId: It will be the parent resource. As you want to use a single URL, 
       this will be that URL's resource ID. You have to use in all your 
       nexted stack to get signle URL.
    3. RestApiId: It will be identifier of associated RestApi
    4. PathPart: It is the last path segment of this resource. Here use "product" 
       for productStack. You can use your own name for your stack like "auth" for 
       AuthStack
    5. So, for your own nested stack, you have to change the value of ParentId,
       RestApiId and PathPart in this section

iii) **API gateway resource for proxy**: It is same as previous section. Just use proxy as PathPart.

      ProductStackProxyApiResource:
        Type: AWS::ApiGateway::Resource
        Properties:
          ParentId: !Ref ProductStackApiResource
          RestApiId: !Ref RootDefaultApi
          PathPart: '{proxy+}'

Here in this section,

    1. Here {proxy+} is used for routing dynamically. Lets say you want to use 
       base_url/product/{id}, base_url/product/users/{id} under same product rest 
       API. This proxy part allows you to make flexible API endpoint.
    2. To make your own nested stack, you have to change only these two
       ParentId, RestApiId in this section. Here your nested stack API gateway 
       resource will be ParentId and your base URL resource will be RestApiId.

iv) **API gateway method**: To check all syntax and property details, check this [link](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-apigateway-method.html).

      ProductStackProxyMethod:
        Type: AWS::ApiGateway::Method
        Properties:
          HttpMethod: ANY
          ResourceId: !Ref ProductStackProxyApiResource
          RestApiId: !Ref RootDefaultApi
          AuthorizationType: NONE
          RequestParameters:
            method.request.path.proxy: true
          Integration:
            CacheKeyParameters:
              - 'method.request.path.proxy'
            RequestParameters:
              integration.request.path.proxy: 'method.request.path.proxy'
            IntegrationHttpMethod: ANY
            Type: HTTP_PROXY
            Uri: !Sub "https://${ProductStack.Outputs.ProductStackApiId}.execute-api.${AWS::Region}.amazonaws.com/${StageName}/{proxy}"
            PassthroughBehavior: WHEN_NO_MATCH
            IntegrationResponses:
              - StatusCode: 200

Here in this section,

    1. You have to change the value of ResourceId, RestApiId and Uri. Keep all the 
       value as it is.
    2. Value of Uri will be made of the output of your nested stack. So make sure 
       that you export those values as output in nested stack. Otherwise you will 
       not get that value in root stack.

I have added my [git link](https://github.com/farzana-juthi/sam-nested-stack) in this post and [README](https://github.com/farzana-juthi/sam-nested-stack/blob/master/README.md) describes how you can run this project. Hope you enjoy it. If you have any question, ask me.

If you find this post helpful, please follow me to get more tutorials like this.