Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

503 Error when invoking NextJS API Route from Client #936

Closed
felixs8696 opened this issue Mar 9, 2021 · 24 comments
Closed

503 Error when invoking NextJS API Route from Client #936

felixs8696 opened this issue Mar 9, 2021 · 24 comments

Comments

@felixs8696
Copy link

felixs8696 commented Mar 9, 2021

Describe the bug

I am using Amplify's API functionality to invoke an AppSync GraphQL endpoint to resolve my API calls. But, I'm getting a GraphQL error message in my Lambda@Edge CloudWatch logs when trying to invoke my API in my application from the client side.

Error: No credentials
    at GraphQLAPIClass.<anonymous> (/var/task/pages/api/users/[username].js:163397:35)
    at step (/var/task/pages/api/users/[username].js:163243:23)
    at Object.next (/var/task/pages/api/users/[username].js:163224:53)
    at fulfilled (/var/task/pages/api/users/[username].js:163215:58)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)

The weird thing is that when I try to execute the API's internal logic on the server side, everything works properly. So, this correctly retrieves and display all data in my application.

# pages/index.js
export const getServerSideProps = async ({ req, res }) => {
  const response = await API.graphql(graphqlOperation(UserQueries.GetUser, <username>))
  
  return {
    props: {
      user: response.data,
    },
  };
};

However, if if I invoke this api route, by going to <app_id>.cloudfront.net/api/users/[username], I get the result under "Actual behavior".

# pages/api/users/[username]/index.js

const handler = async (req, res) => {
  const { username } = req.query.username;
  const response = await API.graphql(graphqlOperation(UserQueries.GetUser, <username>))
  res.status(200).json(response.data);
};

This tells me that I have set up my Cognito and identity pools correctly. For now I am just developing using an API Key, so I expect there to be no permissions barriers.

Actual behavior

If I go to <app_id>.cloudfront.net/api/users/[username] I receive the following error page:

503 Error Message from Application

Expected behavior

API query response should be returned when invoked client side.

Steps to reproduce

  1. Deploy a GraphQL API using CDK (separately, not using Amplify)
  2. Create. NextJS application (https://nextjs.org/docs/getting-started)
  3. Put the AppSync Endpoint URL in the config and set up a custom "_app.js" file using Amplify.configure(config);
  4. Add an API Route to the NextJS Application using the instructions here: https://nextjs.org/docs/api-routes/introduction.
  5. Handle the API route by using Amplify's API client: const response = await API.graphql(graphqlOperation(operation, params))
  6. Add a serverless.yaml at the root of the project with the following content:
# serverless.yml
App:
  component: "@sls-next/[email protected]"
  1. Deploy the application by running the command serverless. See: https://github.com/serverless-nextjs/serverless-next.js
  2. Go to https://<app_id>.cloudfront.net/api/<path_to_your_api_route>.

This will result in the 503 error above.

Screenshots/Code/Logs

CloudWatch Log Stack Trace

# serverless.yml
App:
  component: "@sls-next/[email protected]"

Versions

  • OS/Environment: MacOS Catalina v10.15.6
  • @sls-next/serverless-component version: "@sls-next/[email protected]"
  • Next.js version: 10.0.8

Additional context

@felixs8696 felixs8696 changed the title Permissions Error when invoking NextJS API Route from Client GraphQL Error when invoking NextJS API Route from Client Mar 9, 2021
@felixs8696
Copy link
Author

This may be related to these issues, but none of these solutions work for me:

#819
#935
#181
#222

I've tried increasing the lambda timeout, deleting node_modules and package-lock.json and reinstalling, upgrading all npm packages, using the latest serverless nextjs component.

@felixs8696 felixs8696 changed the title GraphQL Error when invoking NextJS API Route from Client 503 Error when invoking NextJS API Route from Client Mar 11, 2021
@felixs8696
Copy link
Author

Also, this all works fine on my local development server. This only happens when I deploy via serverless.

@mcnamara-charles
Copy link

So, Felix I'm experiencing the same issue and opened up another report. Your serverless.yml is super small so my guess is that you're suffering from a misconfiguration error. But I have no advice beyond that since I'm suffering from the same.

@felixs8696
Copy link
Author

Thanks Charles, hopefully we can get some visibility on this issue from the devs

@jonahallibone
Copy link

Check out the releases page and try some of the newer alpha versions to see if this remedies any of your issues. I see you're using 1.18.0, which lacks support for quite a few features afaik

@mcnamara-charles
Copy link

@felixs8696 I will fill you out on what happened with mine. At some point or another I deleted my dynamodb tables. I repopulated them and it failed to do that without telling me so I was asking my API to populate nothing.

@felixs8696
Copy link
Author

Thanks @jonahallibone I tried the latest alpha version @sls-next/[email protected] and it didn't work

@felixs8696
Copy link
Author

@mcnamara-charles So it worked after your recreated your dynamo tables?

@felixs8696
Copy link
Author

I added reproduction steps above, but I'll copy them here if someone has the same issue

  1. Deploy a GraphQL API using CDK (separately, not using Amplify)
  2. Create a NextJS application (https://nextjs.org/docs/getting-started)
  3. Put the AppSync Endpoint URL in the config and set up a custom "_app.js" file using Amplify.configure(config);
  4. Add an API Route to the NextJS Application using the instructions here: https://nextjs.org/docs/api-routes/introduction.
  5. Handle the API route by using Amplify's API client: const response = await API.graphql(graphqlOperation(operation, params))
  6. Add a serverless.yaml at the root of the project with the following content:
# serverless.yml
App:
  component: "@sls-next/[email protected]"
  1. Deploy the application by running the command serverless. See: https://github.com/serverless-nextjs/serverless-next.js
  2. Go to https://<app_id>.cloudfront.net/api/<path_to_your_api_route>.

This will result in the 503 error above.

@mcnamara-charles
Copy link

@mcnamara-charles So it worked after your recreated your dynamo tables?

Everytime you update how your tables function and what type if data they hold, for example if i changed pass to password for the name of a field, you'd want to update your deployed tables. So go to aws and your dynamodb console and look for your tables. If they exist, delete them (make sure you chanfe regions and delete every table) then reupload them

@mcnamara-charles
Copy link

So I've got some good advice but it might take a while to write down. Basically I repurposed one of the examples "dynomodb-crud" but it sounds like this is a permissions issue. Did you give your api lambda full permissions?

@kato-takaomi-ams
Copy link

kato-takaomi-ams commented Mar 18, 2021

!Edited!
I misunderstood. I don't think the following has anything to do with this issue.
I commented again.


I had a similar issue in that it worked locally, but not in the cloud.

In my case, the 503 error occurred when I tried to use JWT with HTTP.GET.
I had JWT set to headers.Authorization,

      axios
        .get(`https://${API_HOST}/api/verifyToken`,
          { headers: { Authorization: `Bearer ${jwt}` } }
        )

but CloudFront didn't forward this header to lambda.

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/RequestAndResponseBehaviorCustomOrigin.html#request-custom-headers-behavior

The solution I found is one of the following:

  • Use HTTP.POST instead of HTTP.GET

or

  • CloudFront Distributions > [Distribution]
    Behaviors
    2 api/* -> Edit
    Settings for cloudfront to forward Authorization header to lambda
    pic

@mcnamara-charles
Copy link

Okay @kato-takaomi-ams in your serverless.yml there should be a way to rewrite your default API Lambda to use post. Other than that I'm unable to provide guidance as I use Iron Sessions to store my session and cookie data

@kato-takaomi-ams
Copy link

@felixs8696 Does your aws-exports.js define a hosted URL for NextJS-API?
If it is not defined, I don't think you can call NextJS-API with Amplify.configure(config).

Maybe your project has URLs like this:

NextJS-API-URL:
https://<app_id>.cloudfront.net/api/<path_to_your_api_route>.

AppSync-Graphql-EndPoint:
https://<app_id>.appsync-api.<region>.amazonaws.com/graphql

If you want to call NextJS-API, I think you should call the URL of cloudfront with axios etc.

@felixs8696
Copy link
Author

@kato-takaomi-ams

Thanks, but whitelisting the authorization headers didn't work for me.
Where do you define a hosted URL? Also, how do I call the URL of cloudfront with axios? If I directly go to https://<app_id>.cloudfront.net/api/<path_to_your_api_route>, this is what shows the 503 error.

This is the config I am currently using

const AMPLIFY_CONFIG ={
   // API Settings
   aws_appsync_graphqlEndpoint: process.env.NEXT_PUBLIC_GRAPHQL_ENDPOINT,
   aws_appsync_region: process.env.NEXT_PUBLIC_AWS_REGION,
   aws_appsync_authenticationType: process.env.NEXT_PUBLIC_API_AUTH_TYPE,
   aws_appsync_apiKey: process.env.NEXT_PUBLIC_API_KEY,
   // Auth Settings
   aws_cognito_region: process.env.NEXT_PUBLIC_AWS_REGION,
   aws_user_pools_id: process.env.NEXT_PUBLIC_USER_POOL_ID,
   aws_user_pools_web_client_id: process.env.NEXT_PUBLIC_USER_POOL_WEB_CLIENT_ID,
   aws_cognito_identity_pool_id: process.env.NEXT_PUBLIC_IDENTITY_POOL_ID,
   aws_user_files_s3_bucket_region: process.env.NEXT_PUBLIC_AWS_REGION,
   aws_user_files_s3_bucket: process.env.NEXT_PUBLIC_S3_BUCKET,
   ssr: true,
   Analytics: {
     disabled: true,
   },
 };

@felixs8696
Copy link
Author

Okay, because I couldn't figure out how to get this to work, I've just used the graphQL API explicitly in my code instead of going through the NextJS API route, which works, but doesn't solve this problem of why it doesn't work through the API route.

I'm assuming this has something to do with the Cloudfront configuration and some header not being passed through or something to the api/* routes?

@kato-takaomi-ams
Copy link

@felixs8696 Are you calling Amplify.configure(config); in pages/api/users/[username]/index.js?

@felixs8696
Copy link
Author

No I'm calling Amplify.configure(config); in pages/_app.js.

@kato-takaomi-ams
Copy link

It seems that pages/api/* and pages/_app.js are packaged in different lambdas, so maybe you need to call Amplify.configure(config); in pages/api/users/[username]/index.js?

@KrustyC
Copy link

KrustyC commented May 23, 2021

I am experiencing the exact same issue.
My servrless.yml looks as follow

dcrestiniMe:
  component: "@sls-next/[email protected]"
  inputs:
    runtime:
      defaultLambda: "nodejs14.x"
      apiLambda: "nodejs14.x"

When I build and serve locally everything works fine, but when I deploy (using the serverless command) and I access my website, everything it's fine for static routes, but API routes and SSR routes all fail with a 503 and when I look into Cloudwatch, this is what I get

{
    "errorType": "TypeError",
    "errorMessage": "Cannot read property '0' of undefined",
    "stack": [
        "TypeError: Cannot read property '0' of undefined",
        "    at Runtime.handler (/var/task/index.js:3652:34)",
        "    at Runtime.handleOnce (/var/runtime/Runtime.js:66:25)"
    ]
}

my next.config.js is as follow

module.exports = {
  future: {
    webpack5: true,
  },
  target: "serverless",
};

@dphang
Copy link
Collaborator

dphang commented May 25, 2021

@KrustyC Sorry that I missed this issue, perhaps you can post the contents of the line it failed at in index.js, it's hard to understand just from the stack trace. It would be good if you can look into your JS files check that.

If it's similar to in #819, wondering if those libraries are manipulating event and removing some data that this component needs to parse.

@KrustyC
Copy link

KrustyC commented May 25, 2021

@dphang thanks for coming back to me. After some more debugging, I had to remove webpack5, and that sorted out the issue. I may come back to test it again with webpack 5 and update you here in case I have more issues

@dphang
Copy link
Collaborator

dphang commented Aug 1, 2021

Closing old issue, feel free to comment in case this is still an issue and I'll reopen, but most likely would be better to reopen a new issue against the latest versions.

@dphang dphang closed this as completed Aug 1, 2021
@alacomski
Copy link

thanks for coming back to me. After some more debugging, I had to remove webpack5, and that sorted out the issue. I may come back to test it again with webpack 5 and update you here in case I have more issues

this solved my problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants