Graphql Server cannot be reached in nextjs production - graphql

i tested it in locally it work perfectly to fetch data from graphql. But, it up to production version the playground show message Server cannot be reached. What's the different in my locally and production server?
i setup server manually in digitalOcean. It is in nginx and pm2 to start the web.
i had install the mongdb in my server.
this project created from nextjs framework
Below that is my ApolloServer Code:
import { ApolloServer } from "apollo-server-micro";
import { MongoClient } from "mongodb";
import { schema } from "#/apollo/schema";
let db;
const apolloServer = new ApolloServer({
schema,
playground: true,
context: async ({ res, req }) => {
if (!db) {
try {
const dbClient = new MongoClient(process.env.MONGO_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
});
if (!dbClient.isConnected()) await dbClient.connect();
db = dbClient.db("databaseName");
} catch (error) {
console.log(`error while connecting with graphql context (db):`;
}
}
return { db, res, req };
},
});
export const config = {
api: {
bodyParser: false,
},
};
export default apolloServer.createHandler({ path: "/api/graphql" });
Updated: Solved
Is the uri wrong? that is my website url.
return new ApolloClient({
ssrMode,
link: new HttpLink({
uri: `http://dayfruit.staging.domian.com/api/graphql`,
credentials: "include",
fetch,
}),
cache,
});

Related

Setting up graphql yoga with websockets in nextjs api

In graphql yoga documentation, I found this example for using graphql yoga with websockets but it's in nodejs environment. How can I setup a server in nextjs api using this example? All advice is appreciated, thanks.
import { createServer } from '#graphql-yoga/node'
import { WebSocketServer } from 'ws'
import { useServer } from 'graphql-ws/lib/use/ws'
async function main() {
const yogaApp = createServer({
graphiql: {
// Use WebSockets in GraphiQL
subscriptionsProtocol: 'WS'
}
})
// Get NodeJS Server from Yoga
const httpServer = await yogaApp.start()
// Create WebSocket server instance from our Node server
const wsServer = new WebSocketServer({
server: httpServer,
path: yogaApp.getAddressInfo().endpoint
})
// Integrate Yoga's Envelop instance and NodeJS server with graphql-ws
useServer(
{
execute: (args: any) => args.rootValue.execute(args),
subscribe: (args: any) => args.rootValue.subscribe(args),
onSubscribe: async (ctx, msg) => {
const { schema, execute, subscribe, contextFactory, parse, validate } =
yogaApp.getEnveloped(ctx)
const args = {
schema,
operationName: msg.payload.operationName,
document: parse(msg.payload.query),
variableValues: msg.payload.variables,
contextValue: await contextFactory(),
rootValue: {
execute,
subscribe
}
}
const errors = validate(args.schema, args.document)
if (errors.length) return errors
return args
}
},
wsServer
)
}
main().catch((e) => {
console.error(e)
process.exit(1)
})

Next JS server side graphql subscriptions

I am currently building chat app in Next JS. I use graphql with Apollo Client in frontend and Apollo Server on backend. Now I want real time updates, but I found out there is no support for Subscription in apollo-server-micro. As they write here 😢 :
https://www.apollographql.com/docs/apollo-server/data/subscriptions#enabling-subscriptions
Beginning in Apollo Server 3, subscriptions are not supported by the
"batteries-included" apollo-server package. To enable subscriptions,
you must first swap to the apollo-server-express package (or any other
Apollo Server integration package that supports subscriptions).
But I can not use apollo-server-express because I use NextAuth for authentication and then I pass it to context:
export async function createContext({
req,
res,
}: {
req: NextApiRequest;
res: NextApiResponse;
}): Promise<Context> {
const session = await getSession({ req });
const user = { ...session?.user, _id: session?.userId } as User;
const db = await dbConnect();
return {
user,
db,
};
}
Thanks for help 👍.
I found a solution, for everyone who wants to use graphql subscriptions on server: Use graphql-yoga instead :
https://www.graphql-yoga.com/docs/features/subscriptions
My code for pages/api/graphql.ts :
import { createServer, createPubSub, PubSub } from "#graphql-yoga/node";
import { NextApiRequest, NextApiResponse } from "next";
import { Session } from "next-auth";
import { getSession } from "next-auth/react";
const pubSub = createPubSub<{
"user:newMessage": [userId: string, message: Message];
"user:newChat": [userId: string, chat: Chat];
}>();
export type pubSub = typeof pubSub;
const server = createServer<
{
req: NextApiRequest;
res: NextApiResponse;
},
{
user: User;
pubSub: any;
}
>({
context: async ({ req }) => {
const session = await getSession({ req });
await dbConnect();
return {
user: { ...session?.user, _id: session?.userId } as User,
pubSub,
};
},
schema: {
typeDefs,
resolvers: {
Query,
Mutation,
Subscription,
},
},
});
export default server;

Apollo studio CORS error unable to reach server

I'm trying to setup apollo server in my NextJS project, I'm using apollo-server-micro and I ran into these issues:
the apollo studio sandbox is unable to reach the server due to CORS.
This is in pages/api/graphql
import { ApolloServer } from "apollo-server-micro";
import { typeDefs } from "./schemas";
import { resolvers } from "./resolvers/index";
import { createContext } from "./db/context";
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
context: ({ res, req }) => createContext(res, req),
uploads: false,
introspection: true,
formatError: (error) => {
console.log(error);
return error;
},
});
export const config = {
api: {
bodyParser: false,
externalResolver: true,
},
};
module.exports = apolloServer
.start()
.then(() => apolloServer.createHandler({ path: "/api/graphql" }));
then I tried to enable cors but without success because I get this error:
API resolved without sending a response for /api/graphql, this may result in stalled requests.
import { ApolloServer } from "apollo-server-micro";
import { typeDefs } from "./schemas";
import { resolvers } from "./resolvers/index";
import { createContext } from "./db/context";
import { send } from "micro";
import cors from "micro-cors";
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
context: ({ res, req }) => createContext(res, req),
uploads: false,
introspection: true,
formatError: (error) => {
console.log(error);
return error;
},
});
export const config = {
api: {
bodyParser: false,
externalResolver: true,
},
};
module.exports = apolloServer.start().then(() => {
const handler = apolloServer.createHandler({ path: "/api/graphql" });
return cors((req, res) => {
console.log(res);
return req.method === "OPTIONS" ? send(res, 200, 'ok') : handler(req, res);
});
});

API Routes on Next.JS with Apollo-Server : why does using a basePath cause error?

I'm using API Routes on a Next.JS app with Apollo-Server, to create a GraphQL API wrapper around a REST endpoint. But I'm running into an issue if the project has a bathPath.
I've been following this example, and a video tutorial on youtube.
I've replicated my issue by using the repo from that tutorial. Upon running that code $ yarn dev, and navigating to http://localhost:3000/api/graphql the GraphQl playground shows up, and works as expected.
However if I add a basepath to the project then the graphQl playground still shows up fine at http://localhost:300/basepath/api/graphql but it gives me the error of "Server cannot be reached" and shows a 404 error in the network tab on the dev tools.
To add the base path I created a next.config.js and added
module.exports = {
basePath: '/basepath'
}
In pages/api/graphql.ts I updated the path from /api/graphql to /basepath/api/graphql
import { ApolloServer } from "apollo-server-micro";
import { schema } from "src/schema";
const server = new ApolloServer({ schema });
const handler = server.createHandler({ path: "/somewhere/api/graphql" });
export const config = {
api: {
bodyParser: false,
},
};
export default handler;
In src/apollo.ts I updated the HttpLink uri from /api/graphql to /basepath/api/graphql
import {
ApolloClient,
InMemoryCache,
NormalizedCacheObject,
} from "#apollo/client";
import { useMemo } from "react";
let apolloClient: ApolloClient<NormalizedCacheObject>;
function createIsomorphicLink() {
if (typeof window === "undefined") {
// server
const { SchemaLink } = require("#apollo/client/link/schema");
const { schema } = require("./schema");
return new SchemaLink({ schema });
} else {
// client
const { HttpLink } = require("#apollo/client/link/http");
return new HttpLink({ uri: "/bathpath/api/graphql" });
}
}
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === "undefined",
link: createIsomorphicLink(),
cache: new InMemoryCache(),
});
}
export function initializeApollo(initialState = null) {
const _apolloClient = apolloClient ?? createApolloClient();
if (initialState) {
_apolloClient.cache.restore(initialState);
}
if (typeof window === "undefined") return _apolloClient;
apolloClient = apolloClient ?? _apolloClient;
return apolloClient;
}
export function useApollo(initialState) {
const store = useMemo(() => initializeApollo(initialState), [initialState]);
return store;
}
Any ideas why adding a basepath would break this setup? and what I'd need to do to fix it?
This is my first time posting on stack overflow, so I hope my description is good enough, please do ask if I've missed anything and thanks for your help in advance!

Can't access req from context

I'm using Koa.js with Apollo Server's apollo-server-koa.
I've debug the { req } and the value is undefined.
I've followed the documentation, but still got no clue.
Even if I access the req.headers.authorization and put this on HTTP Header of graphql gui:
{
"authorization": "bla"
}
the value is still undefined.
app.ts:
import cors from "#koa/cors";
import Koa from "koa";
import config from "./config/environtment";
import server from "./server";
const PORT: number = config.port;
async function bootstrap() {
try {
const app: Koa = new Koa();
server.applyMiddleware({ app });
app
.use(cors())
.listen(PORT, () =>
console.log(
`Server running on http://localhost:${PORT}${server.graphqlPath}`,
),
);
} catch (error) {
console.error(error);
}
}
bootstrap();
server.ts:
import { ApolloServer } from "apollo-server-koa";
import typeDefs from "./graphql/schema";
import resolvers from "./graphql/resolvers";
import context from "./graphql/context";
export default new ApolloServer({
typeDefs,
resolvers,
context,
});
context.ts
export default ({ req }) => {
console.log(req) // return undefined.
return {
test: "test",
};
};
The docs are specific to apollo-server, which uses apollo-server-express under the hood. I believe for apollo-server-koa, the options are passed in an object with a ctx field that holds the Koa Context. So the following should work:
export default ({ ctx }) => {
console.log(ctx.request)
console.log(ctx.response)
return {};
};

Resources