GET query missing: Implementing GraphQL Using Apollo On an Express Server - node.js

I'm following the tutorial here: Implementing GraphQL Using Apollo On an Express Server and I'm getting the error GET query missing in the browser at http://localhost:7700/graphql.
First I typed all the code myself. When I encountered the error, I downloaded the code from GitHub: kimobrian/GraphQL-Express: An Express Server implemented using GraphQL to eliminate the possibility that I had made a mistake. However, I'm still getting the same error.
I presume it is better to provide the link to the repo rather than paste the code here because I'm using the same code from the repo. Also, I am not sure which file might contain the problem.
$ npm start
> tutorial-server#1.0.0 start kimobrian/GraphQL-Express.git
> nodemon ./server.js --exec babel-node -e js
[nodemon] 1.18.9
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `babel-node ./server.js`
GraphQL Server is now running on http://localhost:7700
The error is GET query missing in the browser at http://localhost:7700/graphql. It's the same in Firefox and Chromium.
Update: The only question I find with relevant information is here: nodejs with Graphql. The suggested solution is
server.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
}));
However, that's exactly the code I have already (from the tutorial). Here is my entire server.js:
import express from 'express';
import cors from 'cors';
import {
graphqlExpress,
graphiqlExpress,
} from 'graphql-server-express';
import bodyParser from 'body-parser';
import { schema } from './src/schema';
const PORT = 7700;
const server = express();
server.use('*', cors({ origin: 'http://localhost:7800' }));
server.use('/graphql', bodyParser.json(), graphqlExpress({
schema
}));
server.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql'
}));
server.listen(PORT, () =>
console.log(`GraphQL Server is now running on http://localhost:${PORT}`)
);

Both the API and the package name itself have changed since that tutorial was written (the package is now apollo-server-express). You no longer need to import cors or body-parser. The simplest way to get started is to actually just use apollo-server:
const server = new ApolloServer({ typeDefs, resolvers });
const port = 7700;
server.listen({ port });
If you still want to apply other middleware yourself, you can use apollo-server-express:
const server = new ApolloServer({ typeDefs, resolvers });
const app = express();
server.applyMiddleware({ app });
const port = 7700;
app.listen({ port });
Please check the official docs for more details.

I fixed it by addding two fields into Apollo Server constructor: playground: true and introspection: true:
const apolloServer = new ApolloServer({
schema,
context: (ctx: Context) => ctx,
playground: true,
introspection: true,
});
Note: Beware that cors should be set up properly for your graphql server to be able to answer requests.
Found here.

Related

Getting an error: "querySrv ECONNREFUSED _mongodb._tcp.cluster0.vxgqt.mongodb.net" when connecting to mongodb atlas

I am getting the below error in the terminal:
Error: querySrv ECONNREFUSED _mongodb._tcp.cluster0.vxgqt.mongodb.net did not connect
on running the index.js file
It was working fine till yesterday and today on running it is giving this error.
This is the code snippet:
import express from 'express';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import cors from 'cors';
import postRoutes from './routes/posts.js';
const app = express();
app.use(bodyParser.json({ limit: '30mb', extended: true }))
app.use(bodyParser.urlencoded({ limit: '30mb', extended: true }))
app.use(cors());
app.use('/posts', postRoutes);
const CONNECTION_URL = 'mongodb+srv://<username>:<password>#cluster0.vxgqt.mongodb.net/myFirstDatabase?retryWrites=true&w=majority';
const PORT = process.env.PORT|| 5000;
mongoose.connect(CONNECTION_URL, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => app.listen(PORT, () => console.log(`Server Running on Port: http://localhost:${PORT}`)))
.catch((error) => console.log(`${error} did not connect`));
mongoose.set('useFindAndModify', false);
NOTE: I have provided the correct username and password in the connection url
I found a temporary fix and that is working: Under connect your application in MongoDB Atlas I selected node version 2.2.12 or later instead of 3.6 or later(which I used earlier). By selecting this, the application is now working fine as before
First of all check your internet connection and then go to mongodb Atlas and check whether your ip address is available in whitelist or not.
for testing purpose allow all ip's to access and then connect again.
querySrv ECONNREFUSED means that the attempt to resolve the SRV record failed to connect to a name server.
This is a DNS problem. Your application will need to be able to resolve the SRV record for _mongodb._tcp.cluster0.vxgqt.mongodb.net in order to use the mongodb+srv connection string.
you need to write your username and password inside URI of mongoDB, that mean u need to take value of CONNECTION_URL constant variable and change to current username of your account on mongoDB and change to current password of your account on mongoDB

Deploying VueJS app - Back end (ExpressJS) Not Responding

This is my first time deploying a VueJS app. It is full stack, back end is Express/MySQL. All running fine in developer mode. My dev platform is Windows 10, VS Code.
I am currently trying to preview the app on my dev PC using local webserver.
To that end, I built Vue app to server/public. The static site then runs fine, but I can't seem to get the Express back end to respond, either from the app or from browser accessing the api directly. I followed a model from Brad Traversy tutorial, here is what vue.config.js looks like:
const path = require('path');
module.exports = {
outputDir: path.resolve(__dirname, './server/public'),
devServer: {
disableHostCheck: true,
proxy: {
'/api': {
target: 'http://localhost:5000'
}
}
},
transpileDependencies: ['vuetify'],
pluginOptions: {
i18n: {
locale: 'en',
fallbackLocale: 'en',
localeDir: 'locales',
enableInSFC: false,
},
},
};
Here is the index.js for Express/back end. I commented out the NODE_ENV test because I haven't yet figured out how to set it properly. This should just hardwire the code to run in production mode. __dirname points to the server directory, which contains the Express code and other server stuff.
// Create express app
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
//Create Express App
const app = express();
// Add Middleware
app.use(bodyParser.json());
app.use(cors());
//
const water = require('./routes/api/water');
const waterlog = require('./routes/api/waterlog');
// Direct /api
app.use('/api/water', water);
app.use('/api/waterlog', waterlog);
// Handle production
// if (process.env.NODE_ENV === 'production') {
// Static folder
app.use(express.static(__dirname + '/public/'));
// Handle SPA
app.get(/.*/, (req, res) => res.sendFile(__dirname + '/public/index.html'));
// }
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`CORS-EnabledServer started on port ${port}`));
I use (from npm serve) this to start the Vue app:
serve -s server/public
What am I missing? Feels very close but no cigar yet...
serve is just a simple, static HTTP server. It won't run your backend.
Your production build puts your front-end assets into your Express app's statically served directory so all you should need to do after building the front-end is start your server
# Build your front-end
npm run build
# Start your Express server, assuming this is configured in package.json
NODE_ENV=production npm start
Now open http://localhost:5000/ in your browser
See also https://expressjs.com/en/advanced/best-practice-performance.html#set-node_env-to-production

CORS giving issues once I went from localhost --> heroku

I have a chat application where my client side is written in Reactjs and my backend is written in Nodejs/Express. I have required cors and everything on my backend and the entire application worked perfectly when I was using localhost:3000 for the client and localhost:5000 for the server. I then deployed the server to heroku and the client to netlify, and now I am getting this CORS error every time I try to log in using a POST request (using axios as well):
Under the network tab on chrome, I get two things, a "signin" that has 204 and it works, and then a "signin" that just says error.
This is what my backend looks like in Nodejs/express:
require('dotenv').config()
const http = require('http');
const cors = require('cors');
const hostname = '127.0.0.1';
const port = process.env.PORT || 5000;
const express = require('express');
const jwt = require('jsonwebtoken')
const cookieParser = require('cookie-parser');
const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
const {AddUser, FindUser, RemoveUser, FindId} = require('./users.js')
var corsOptions = {
origin: ['http://localhost:3000', 'https://easytalkchat.netlify.app'],
credentials: true,
methods: ['GET', 'POST', 'OPTIONS', 'PUT', 'DELETE'] };
app.use(cors(corsOptions));
app.use(express.json())
app.use(cookieParser());
//Tells the server what port to listen to and can add a function to talk to command line
server.listen(port, () => {
console.log("Server is up!");
});
What I THINK might be the problem is maybe I'm not setting up the server using https, because I'm doing it with http. Maybe this is causing the problem but I don't know how to fix it. Other people have also mentioned it might not be a problem with CORS but rather Heroku, since Heroku only installs devDependencies or something like that, but I don't know how to fix that either.
I've tried adding headers, credentials, everything, I have no clue.
My front end looks like this:
const signIn = (e) => {
e.preventDefault();
axios.post('https://easytalkchatapp.herokuapp.com/signin', {
username: username,
password: password
}).then(res => {
...
and I have axios.defaults.withCredentials = true written at the top.
And just to re-state above, if I literally go to terminal and just run my server on localhost:5000 instead of heroku and make all my POST/GET requests through the localhost:500 server it works completely fine. If, however, I run my client on localhost:3000 and have the server be heroku, it breaks, so the problem is most certaintly with heroku and how I'm using it.
Since, you are using withCredentials, so I thinks its better to provide specific values for origin instead of true or '*' because it will not work with credentials true.
Try using this options:
var corsOptions = {
origin: ['http://localhost:3000', 'https://easytalkchat.netlify.app'],
credentials: true,
};
I hope it helps.
if you use withCredentials= true and when you run frontend and backend both form localhost, it runs perfectly because they are in the same origin
but if you run frontend and backend from different origin(host) in that time it gives you cors issue. for resolve this issue you have to whitelist the frontend origin in the backend
var corsOptions = {
origin: ['http://localhost:3000', 'https://easytalkchat.netlify.app'],
credentials: true,
};
by this way backend now trust the frontend origin
It turns out it was completely my own fault with my backend code. I was using process.env.(variable) and I had never specified it in the heroku config vars so it kept breaking when trying to access it. UGH. Thanks everyone.

Adding GraphQL subscriptions to the existing express app using single server

GraphQL playground subscription fails with 400 error code.
WebSocket connection to 'ws://localhost:3000/graphql' failed: Error during WebSocket handshake: Unexpected response code: 400
I have an existing code based on express. I've integrated Apollo v2 this way:
const { ApolloServer, PubSub, gql } = require('apollo-server-express');
...
const app = express();
const server = new ApolloServer({
typeDefs,
resolvers
});
server.applyMiddleware({ app });
...
app.listen(port, () =>
console.log(chalk.blue(`App listening on port ${port}!`)),
);
and then i start my existing app on port 3000 and can access the GraphQL playground on http://localhost:3000/graphql. All queries and mutations work as expected
Now I want to add subscriptions. Turns out I need to use an http server:
const httpServer = http.createServer(app);
server.installSubscriptionHandlers(httpServer);
and then listen to it on another port:
httpServer.listen(3005, () => {
console.log(`Server ready at http://localhost:3005${server.graphqlPath}`);
console.log(`Subscriptions ready at ws://localhost:3005${server.subscriptionsPath}`);
});
So I have two servers running. My own on port 3000 and the subscriptions server on 3005. Is that the right way? Is it the only way?
There's no need to call both app.listen and httpServer.listen -- calling httpServer.listen will expose both your Express app and the subscription server.
Additional reading: Express.js - app.listen vs server.listen

nodejs + express: Cors is not a function

Been working fine up until this morning and now, suddenly i am getting a type error stating that Cors is not a function
My code
import * as Cors from "cors";
...
const corsOptions: Cors.CorsOptions = {
allowedHeaders: ["Origin", "X-Requested-With", "Content-Type", "Accept", "X-Access-Token", "Authorization"],
credentials: true,
methods: "GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE",
origin: "*",
preflightContinue: true
};
createConnection(ormConfig).then(async connection => {
// run pending migrations
await connection.runMigrations();
// create express server
const app = express();
app.use(bodyParser.json({limit: "50mb"}));
app.use(bodyParser.urlencoded({limit: "50mb", extended: true}));
// register cors
app.use(Cors(corsOptions)); //<---error occurs here
// register all controllers
useExpressServer(app, {
routePrefix: "/api",
controllers: [
__dirname + "/controllers/**/*{.js,.ts}"
],
authorizationChecker: async (action: any, roles: string[]) => {
return JwtAuthorizationMiddleware.checkIsAuthorized(action, roles);
},
currentUserChecker: async (actions: any) => {
return JwtAuthorizationMiddleware.extractUserFromJwtToken(actions);
}
});
// start the express server
const port: number = +(process.env.PORT || 44320);
app.listen(port, (err: Error) => {
console.log(`App listening on port ${port}`);
console.log("Press Ctrl+C to quit.");
});
}).catch(error => console.error("TypeORM connection error: ", error));
Current versions of cors and Node
cors: "^2.8.4"
Node: v8.4.0
The only change that recently done was on Friday when I included the following packages
multer: "^1.3.0"
#google-cloud/datastore: "^1.1.0"
#google-cloud/storage: "^1.4.0"
and everything was working till this morning, same version is deployed on gcloud and this works so I am a little bemused as to why I Am suddenly getting this error and what could be the cause.
Any help is greatly appreciated
You have to have something such as
const cors = require('cors');
in the top of your file, and then refer to the module as cors, not Cors.
You can read Express's cors documentation to learn more.
To apply cors to all routes in your project you can write:
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
Ok, so I found the problem which turned out to be PEBKAC.
While implementing file uploads and storage in gcloud, I had to enable CORS on gcloud and had saved the settings file in the root of my project, this file was called cors.json.
In the code posted in my question above the import statement was reading my cors.json file and not (as I thought) the cors NPM package.
Lesson learnt from this one should anyone else make the same rookie mistake I just made is be careful what you name your files and where you put them!!!

Resources