amplify-hosting icon indicating copy to clipboard operation
amplify-hosting copied to clipboard

DNS Resolution Issue with API Requests in Next.js App on AWS Amplify

Open mustafadalga opened this issue 2 years ago • 0 comments

Before opening, please confirm:

  • [X] I have checked to see if my question is addressed in the FAQ.
  • [X] I have searched for duplicate or closed issues.
  • [X] I have read the guide for submitting bug reports.
  • [X] I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
  • [X] I have removed any sensitive information from my code snippets and submission.

App Id

arn:aws:amplify:eu-central-1:392145163496:apps/du9vxmpr1v1e5

AWS Region

us-east-1

Amplify Hosting feature

Build settings, Custom build image, Custom headers, Deployments, Frontend builds

Frontend framework

Next.js

Next.js version

13.5.5

Next.js router

App Router

Describe the bug

I am experiencing an issue with my Next.js application hosted on AWS Amplify where API requests to https://api-test.example.com/login fail due to a DNS resolution error (getaddrinfo ENOTFOUND). This issue does not occur in my local environment or in vercel.com, suggesting it's specific to the Amplify environment.

Expected behavior

  • The API request should successfully resolve the DNS and connect to the external service without encountering a getaddrinfo ENOTFOUND error and fetch response.

  • The API requests should consistently succeed without encountering 408 errors, similar to how they function in local and Vercel environments.

Reproduction steps

  1. Host a Next.js application on AWS Amplify.
  2. Make a POST request to an external API (https://api-test.example.com/login) from the application.
  3. Observe the error in the response.

Build Settings

version: 1
frontend:
  phases:
    preBuild:
      commands:
        - npm ci
    build:
      commands:
        - npm run build
  artifacts:
    baseDirectory: .next
    files:
      - '**/*'

  cache:
    paths:
      - node_modules/**/*

Log output


The API request fails with the following error:

{
    "message": "Please try again!",
    "details": {
        "method": "POST",
        "url": "https://api-test.example.com/login",
        "message": "getaddrinfo ENOTFOUND api-test.example.com"
    }
}

Additional information

Troubleshooting Steps Undertaken

  1. Dynamic Routing Configuration:

    • Tried both with and without force-dynamic in the API route configuration. The issue persists regardless of this setting.
  2. Build Image Changes:

    • Switched the build image to Amazon Linux 2023 and also tried a custom image (public.ecr.aws/docker/library/node:18.17.0). Neither change resolved the issue.
  3. Custom HTTP Configuration:

    • Removed the custom HTTP configuration (customHttp.yml) to check its impact. The issue still occurred without this configuration.
  4. Intermittent Behavior:

    • The API sometimes works but often returns a 408 timeout error. This behavior is inconsistent and only observed in the Amplify environment, not locally or on Vercel.
  5. Build Image for Unit Tests:

    • Using Amazon Linux 2023 and the custom Node.js image was necessary for running unit tests, as they do not work with the default image.

Custom HTTP Configuration (customHttp.yml):

customHeaders:
  - pattern: '**/*'
    headers:
      - key: Cache-Control
        value: no-store
      - key: Pragma
        value: no-cache
      - key: Expires
        value: '0'

Api Route

import { NextResponse } from "next/server";
import api from "@/_services/loginApiService";
import handleAxiosError from "@/_utilities/handleAxiosError";

export const dynamic = "force-dynamic"


export async function POST(request: Request) {
    const body = await request.json();
    const {
        username,
        password,
    } = body;

    try {
        const response = await api.post(“my-api/login”, {
            username,
            password,
        });

        const { access_token: jwt, exp: jwtExpirationTime } = response.data.data;

        return createNextResponse({ jwt, jwtExpirationTime }, 200);

    } catch (error) {
        const {
            message,
            status,
            details
        } = handleAxiosError(error, "Please try again!");
        return createNextResponse({ message, details }, status);
    }
}


function createNextResponse(data: Record<string, any>, status: number): NextResponse {
    const nextResponse = NextResponse.json(data, { status });
    nextResponse.headers.set('Cache-Control', 'no-store, max-age=0');
    return nextResponse;
}

mustafadalga avatar Dec 21 '23 08:12 mustafadalga