graphql playground behaving weirdly running on heroku - heroku

So i have an apollo-server running using apollo-server-express:
const PORT = process.env.PORT || 8000
const graphqlPath = process.env.GRAPHQL || 'graphql'
const app = express()
app.use(cors())
app.use(bodyParser.text({ type: 'application/graphql' }))
const gqlServer = new ApolloServer({
typeDefs: schema,
resolvers,
context: {
me: users[1]
},
debug: true,
tracing: true
})
gqlServer.applyMiddleware({ app, path: `/${graphqlPath}` })
app.listen(PORT, () => console.log(`graphql listening on port ${PORT}`))
module.exports = app
it runs perfectly on localhost, but deploying it to heroku, it becomes weird when i run the playground:
it says Server cannot be reached
I can't get the schema
the queries run (sometimes) and immediately after i see the result, it changes to that json error object
when i copy the curl request, and run it on my terminal, i always get the result without any problems
Here's a sample of the console errors:
POST <graphql_server_url> 400 (Bad Request)
Error: Response not successful: Received status code 400

Try adding introspection and playground to your ApolloServer config and set to true. They get turned off automatically when the Node environment is set to production, but this way you can enable it in prod. Reference: https://www.apollographql.com/docs/apollo-server/v2/testing/graphql-playground/#enabling-graphql-playground-in-production
const gqlServer = new ApolloServer({
typeDefs: schema,
resolvers,
context: {
me: users[1]
},
debug: true,
tracing: true,
introspection: true,
playground: true
})

adding introspection: true to new ApollowServer object will solve the porblem

Related

Not able to connect to my local graphql server with apollo studio sandbox

I am running a graphql server using serverless offline and trying to connect to the server with Aollo Studio. The weirdest bug is that it was connecting properly a week back and now the exact same server is not connecting. The same thing I have deployed on the AWS and Aollo Studio is able to connect to the deployed server. Any idea what could be the reason for it?
Environment
I am on Macbook m1 pro.
Node Version 15.6
As you can in the config file I have started a playground as well on this path http://localhost:3000/dev/playground which I am able to access but this playground is also not connecting the server.
One thing which I have observed is my local network IP URL like http://192.168.1.3:3000/dev/playground is also not working when I am trying to visit so maybe some kind of network issue might be there.
But when I run something like a React App I am able to access it on this http://192.168.1.3:3000
My serverless.yml looks like below
service: serverless-graphql-rds
frameworkVersion: "3.8.0"
provider:
name: aws
runtime: nodejs14.x
stage: ${env:PROVIDER_STAGE}
region: ${env:REGION}
environment:
JWT_SECRET: ${env:JWT_SECRET}
DATABASE_URL: ${env:DATABASE_URL}
REDIRECT_TO_DASHBOARD: ${env:REDIRECT_TO_DASHBOARD}
HUB_SPOT_CLIENT_ID: ${env:HUB_SPOT_CLIENT_ID}
HUB_SPOT_CLIENT_SECRET: ${env:HUB_SPOT_CLIENT_SECRET}
HUB_SPOT_REDIRECT_URI: ${env:HUB_SPOT_REDIRECT_URI}
plugins:
- serverless-plugin-typescript
- serverless-offline
package:
patterns:
- "migrations/**"
- "**.js"
- "config"
custom:
serverless-offline:
httpPort: ${env:httpPort, 3000}
lambdaPort: ${env:lambdaPort, 3002}
serverless-plugin-typescript:
tsConfigFileLocation: "./tsconfig.json"
functions:
graphql:
handler: server.handler
events:
- http:
path: graphql
method: post
cors: true
playground:
handler: server.playgroundHandler
events:
- http:
path: playground
method: get
cors: true
oauth-callback:
handler: ./rest-apis-handlers/oauth-callback.handler
events:
- http:
path: oauth-callback
method: get
cors: true
And the file server.ts looks like below which contains the handler function
import { ApolloError, ApolloServer } from "apollo-server-lambda";
import lambdaPlayground from "graphql-playground-middleware-lambda";
import { verifyToken } from "./common/jwt";
import { useContext } from "./core/context";
import resolvers from "./graphql/resolvers";
import typeDefs from "./graphql/schema";
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ event, context, express }) => {
const auth = express.req.headers["authorization"] as string;
if (auth) {
const [_, token] = auth.split("Bearer ");
try {
const user = verifyToken(token);
if (user) {
return useContext({
type: "user",
properties: {
...user,
},
});
} else {
throw new ApolloError("Not authenticated", "UNAUTHENTICATED");
}
} catch (ex) {}
}
return useContext({
type: "public",
});
},
});
export const handler = server.createHandler({});
// for local endpointURL is /graphql and for prod it is /stage/graphql
export const playgroundHandler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
return lambdaPlayground({
endpoint: process.env.REACT_APP_GRAPHQL_ENDPOINT,
})(event, context, callback);
};
After struggling for 3 days today I finally figured it out.
As I am using the serverless-offline package to run the local graphql server and due to the node version it requires less than 15. Here is the details discussion on it.
So just downgrade the node version to anything < 15 and it will work.

Graphql subscription in playground during local development throwing "Could not connect to websocket endpoint" in basic nestjs project

This is happening on a simple project during local development, so cloud infrastructure isn't an issue.
This is also happening in the application playground.
My module registration:
GraphQLModule.forRootAsync<ApolloDriverConfig>({
driver: ApolloDriver,
imports: [YeoConfigModule],
useFactory: (configService: YeoConfigService<AppConfig>) => {
const config: ApolloDriverConfig = {
debug: true,
subscriptions: {
'graphql-ws': true,
},
playground: true,
autoSchemaFile: './apps/event-service/schema.gql',
sortSchema: true,
context: ({ req, res }) => ({ req, res }),
};
const origins = configService.get('CORS_ORIGINS')();
config.cors = { origin: origins, credentials: true };
// config.path = '/apis/event-service/graphql';
return config;
},
inject: [YeoConfigService],
My app startup:
async function bootstrap(): Promise<void> {
const app = await getApp();
await app.listen(process.env.PORT ?? 3600);
}
bootstrap();
My versions:
"graphql-ws": "5.11.2",
"graphql-redis-subscriptions": "2.5.0"
"#apollo/gateway": "2.1.3",
"#nestjs/graphql": "10.1.3",
"graphql": "16.5.0",
Result:
{
"error": "Could not connect to websocket endpoint ws://localhost:3600/graphql. Please check if the endpoint url is correct."
}
Any ideas why this isn't working as expected? I've been reading the nestjs docs up at https://docs.nestjs.com/graphql/subscriptions but there's nothing that I can find about extra setup required other than adding
subscriptions: {
'graphql-ws': true,
},
when registering the graphql module.
For anyone else stumbling upon this, I have started using altair which allows me to specify the ws endpoint as well as the type of connection, among which there is a graphql-ws option.
So I went with it.
If anyone knows how to achieve this using the playground referred in the original answer, happy to mark that one as the right answer over my own.

GraphQL with ApolloServer says "GET query missing." even though I have playground set to true the way another post advised

I am trying to use Postman to hit a graphQL endpoint to teach myself how it works. I have a database with user data prepopulated and two Postman routes that should work but don't work.
The requests I am trying to send via Postman:
(1) Using GraphQL mode under the Body tab
{
User {
first_name
last_name
}
}
(2) using the raw mode under the Body tab
{
user {
first_name
last_name
}
}
In both cases I have correctly set the headers Content-Type to application/graphql. So it's not that.
I found two posts about this while Googling. Both are on StackOverflow.
(1) apollo-server returning GET query missing when playground is disabled
This one says basically, "do this":
const server = new ApolloServer({
introspection: true, // i inserted this line & the next one as specified
playground: true,
typeDefs,
resolvers,
})
(2) GET query missing: Implementing GraphQL Using Apollo On an Express Server
This one references the prior link. It's also for graph-server-express, and I'm using apollo-server-fastify
I also found Apollo Graphql with Fastify who also has "GET query missing." issue but no solution. It says to downgrade to fastify v2 but that's an old answer from 2020. This is 2022, we can do better.
Again the issue is that Postman says "GET query missing." to all my requests.
My server:
async function startApolloServer(typeDefs, resolvers) {
const apolloServer = new ApolloServer({
// introspection: true,
// playground: true, // to resolve "GET query missing." in Postman
typeDefs,
resolvers,
plugins: [
fastifyAppClosePlugin(fastify),
ApolloServerPluginDrainHttpServer({ httpServer: fastify.server }),
ApolloServerPluginLandingPageGraphQLPlayground(),
],
context: ({ request, reply }) => {
//Invaluable for debugging
if (env === "development") {
console.log("GOT A REQUEST: ", request.body);
}
return { knex, reply };
},
});
await apolloServer.start();
fastify
.register(helmet)
.register(require("fastify-sensible"))
.register(require("fastify-healthcheck"))
.register(require("fastify-formbody"))
.register(apolloServer.createHandler());
await fastify.listen(serviceListeningPort);
console.log(
`🚀 Server ready at http://localhost:${serviceListeningPort}${apolloServer.graphqlPath}`
);
}
startApolloServer(typeDefs, resolvers);
Also, the updated version of Apollo Server seems to replace playground: true with ApolloServerPluginLandingPageGraphQLPlayground(), which for me enables a page that says "Loading GraphQL Playground" at the server root but never finishes loading.

Unsupported content type with GraphIql apollo engine

I'm running apollo-server-express, and all works fine. I have 2 endpoints - 1 for graphiql (/graphql) and one for non-interactive (/client) queries (I know - they were called that before I started with apollo).
app.use('/client', bodyParser.json() ,
(req, res,next) => {
const context = { pool , apiKey:req.query.key , bidules };
if (server.isAuthorized(context.apiKey)) {
return graphqlExpress({
schema: schema,
context: context,
tracing: true,
cacheControl: {
defaultMaxAge: 30,
}
}) (req,res,next);
}
else {
res.setHeader('Content-Type', 'application/json');
res.status(403)
.send (JSON.stringify({
errors:[ {message: "api key is unauthorized"} ]
}));
}
}
);
// endpoint for browser graphIQL
app.use('/graphql', graphiqlExpress({
endpointURL: '/client'
}));
app.use("/schema", (req, res) => {
res.set("Content-Type", "text/plain");
res.send(printSchema(schema));
});
But, when I introduce apollo engine
engine.listen({
port: port,
expressApp: fidserver.app,
graphqlPaths: ['/graphql', '/client']
});
everything still works fine - except when I refresh graphiql on the browser with the query as parameters on the browser url.
Then I get this error
{"errors":[{"message":"Unsupported Content-Type from origin: text/html"}]}
Doing the same thing without apollo engine running does not cause an error. If run the query again, or refresh the browser without the query and variable parameters everything works just fine with or without Apollo Engine enabled.
When the error happens I can see from my server log that it's trying to return a react web page containing some javascript for decoding parameters from somewhere but I can't track down from where - it doesn't get as far as hitting any of my code.
This was solved by the guys at Apollo. Here's the answer - I shouldn't have had my graphIQL end point mentioned in the engine.listen options.
Engine should only be placed between the client and the GraphQL server endpoint. Try a config like this:
engine.listen({
port: port,
expressApp: fidserver.app,
graphqlPaths: ['/client'] // removed "graphql"
});

Apollo GraphQL: Setting Port for HTTPBatchedNetworkInterface?

I'm trying to connect to a local dev environment via an IP address. I'm getting an error because HTTPBatchedNetworkInterface shows:
_uri: "http://10.0.1.10/graphql"
...when it needs to be:
"http://10.0.1.10:3000/graphql"
Here's my server-side setup code:
const localHostString = '10.0.1.10';
const METEOR_PORT = 3000;
const GRAPHQL_PORT = 4000;
const server = express();
server.use('*', cors({ origin: `http://${localHostString}:${METEOR_PORT}` }));
server.use('/graphql', bodyParser.json(), graphqlExpress({
schema,
context
}));
server.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
subscriptionsEndpoint: `ws://${localHostString}:${GRAPHQL_PORT}/subscriptions`
}));
// Wrap the Express server
const ws = createServer(server);
ws.listen(GRAPHQL_PORT, () => {
console.log(`GraphQL Server is now running on http://${localHostString}:${GRAPHQL_PORT}`);
console.log(`GraphiQL available at http://${localHostString}:${GRAPHQL_PORT}/graphiql`);
// Set up the WebSocket for handling GraphQL subscriptions
new SubscriptionServer({
execute,
subscribe,
schema
}, {
server: ws,
path: '/subscriptions',
});
});
What is the correct way to get the port number into HTTPBatchedNetworkInterface._uri?
Thanks in advance to all for any info.
Fixed. My framework is Meteor and I had to set ROOT_URL = 10.0.1.10:3000/.

Resources