1

I have a website in production (https://socialvc.netlify.app/) but the queries on the page will only appear if the app is also running locally on localhost:3000.

I tried to configure ApolloClient 3 ways

  1. locally only
  2. with a conditional to see if the app is in production or local environment
  3. exclusively the production ur - only the first code block works on prod and it only works if I am running locally as well

All 3 are demonstrated below:

const client = new ApolloClient({
  uri: "http://localhost:3000/api/graphql",
  cache: new InMemoryCache(),
});

so if im running my localhost:3000 I can see the queries in production

I tried

let uri = "http://localhost:3000/api/graphql";
if (process.env.NODE_ENV === "production") {
  uri = "https://socialvc.netlify.app/api/graphql";
}

const client = new ApolloClient({
  uri: uri,
  cache: new InMemoryCache(),
});

and

const client = new ApolloClient({
  uri: "https://socialvc.netlify.app/api/graphql",
  cache: new InMemoryCache(),
});

Some more info: I am using Next.JS with graphql/ApolloClient/Prisma and Postgre

Edit: So I have cors enabled but am still getting that error. Below I show where I have set my headers and allowed for Cors. Could I be missing something there?

const apolloServer = new ApolloServer({
  typeDefs,
  resolvers,
});
const startServer = apolloServer.start();

export default async function handler(req: any, res: any) {
  res.setHeader("Access-Control-Allow-Credentials", "true");
  res.setHeader("Access-Control-Allow-Origin", "*");
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept, Access-Control-Allow-Methods, Access-Control-Allow-Origin, Access-Control-Allow-Credentials, Access-Control-Allow-Headers"
  );
  res.setHeader(
    "Access-Control-Allow-Methods",
    "POST, GET, PUT, PATCH, DELETE, OPTIONS, HEAD"
  );
  if (req.method === "OPTIONS") {
    res.end();
    return false;
  }
  await startServer;
  await apolloServer.createHandler({
    path: "/api/graphql",
  })(req, res);
}
fwan
  • 43
  • 6
  • @SeanW I am not seeing any errors in the netlify functions tab. It shows these three functions there: ___netlify-handler, ___netlify-odb-handler, _ipx. So I assume server side since I am using gql queries and mutations to make the requests. When I am not running my server locally on the prod site in the console I get this errror: POST http://localhost:3000/api/graphql net::ERR_CONNECTION_REFUSED I learned even when I'm running my local server, only I am able to see the queries come through on the production site. No one else is able to see those. I guess it is looking for my ip+localhost – fwan Jan 22 '23 at 01:39
  • @SeanW So I only see POST localhost:3000/api/graphql net::ERR_CONNECTION_REFUSED in the console. I don't see any error that says its related to CORS specifically. In the network tab there are failed graphql requests but there are no error messages in the response. It makes those requests to http://localhost:3000/api/graphql but it does have this referrer policy in the headers section of the network tab for this request.Referrer Policy: strict-origin-when-cross-origin. Could that be a cors thing? – fwan Jan 22 '23 at 19:41
  • @SeanW Appreciate your help so much. Actually I already have CORS enabled, and I have edited my post to show how I did that. Is it something I am doing wrong there or am I not enabling it properly? – fwan Jan 26 '23 at 18:01

1 Answers1

0

Enable CORS for Apollo Server 4 and Next.js

src/allow-next-api-cors.ts

import { NextApiResponse, NextApiRequest, NextApiHandler } from "next";

const allowedHeaders = [
  "access-control-allow-credentials",
  "access-control-allow-origin",
  "apollographql-client-name", // this might be key for you
  "authorization",
  "content-type",
];

export const allowNextApiCors = (handler: NextApiHandler) =>
  async (req: NextApiRequest, res: NextApiResponse) => {
    res.setHeader("Access-Control-Allow-Credentials", "true");
    res.setHeader("Access-Control-Allow-Origin","*");// research having this set to *
    res.setHeader("Access-Control-Allow-Methods", ["GET", "OPTIONS", "POST"]);
    res.setHeader("Access-Control-Allow-Headers", allowedHeaders.join(","));
    if (req.method === "OPTIONS") {
      res.status(200).end();
      return;
    }
    await handler(req, res);
  };

api/graphql.ts

import { startServerAndCreateNextHandler } from "@as-integrations/next";
import { NextApiRequest, NextApiResponse } from "next";
import { ApolloServer } from "@apollo/server";
// set correct import paths
import { typeDefs, resolvers } from "your-types-and-resolvers";
import { allowNextApiCors } from "src/apollo-next-allow-cors";

type User = { email: string; id: string; name: string; role: string };
type Context = { currentUser: User; accessToken: string };
type CreateContext = (req: NextApiRequest, res: NextApiResponse) => Promise<Context>;

const getUser = (): Context => ({
  currentUser: {
    email: "test@example.com",
    id: "1",
    name: "Test User",
    role: "USER",
  },
  accessToken: "super-secret-token",
});

const context: CreateContext = async () => {
  const { currentUser, accessToken } = getUser();
  return { currentUser, accessToken };
};

const context: CreateContext = async () => {
  const { currentUser, accessToken } = getUser();
  return { currentUser, accessToken };
};

const apolloServer = new ApolloServer({ typeDefs, resolvers });

const handler = startServerAndCreateNextHandler(apolloServer, { context });

export default allowNextApiCors(handler);
Sean W
  • 5,663
  • 18
  • 31