Apollo Server 2 + Express: req.body missing on post handler - graphql

Had this working in version 1, but the whole server config has changed. This is what I have, after adding bodyparser() to the express app as was suggested by Daniel in the comments:
const server = new ApolloServer({
typeDefs,
resolvers,
playground: {
settings: {
'editor.theme': 'light',
}
},
})
// Initialize the app
const app = express();
app.use(cors())
app.use(bodyParser.json())
server.applyMiddleware({
app
})
app.post('/calc', function(req, res){
const {body} = req;
console.log("HOWDYHOWDYHOWDY", body) // <== body is {}
res.setHeader('content-type', 'application/json')
calculate(body)
.then(result => res.send(result))
.catch(e => res.status(400).send({error: e.toString()}))
})
The request body is never making it to the app.post handler, though the handler is called. I see it going out from the browser, though. Any ideas?
Update: Daniel had the correct answer, but I had another problem in the request headers I was using. Once I fixed that, then the post handler received the body.

Apollo's middleware applies the bodyparser middleware specifically to the GraphQL endpoint -- it won't affect any other routes your server exposes. In order to correctly populate req.body, you need to add the bodyparser middleware yourself, for example:
app.use(bodyParser.json())
app.post('/calc', routeHandler)
// or...
app.post('/calc', bodyParser.json(), routeHandler)

I just ran into this as well. Fixed it by passing the following into the headers:
Content-Type: application/json

Related

Performing a PATCH request in Vodapay Mini-Programs

I am working on a Vodapay mini-program and would like to know if it is possible to perform a PATCH request using my.request?
You cant perform PATCH requests using my.request.It only supports GET/POST. You can read a about it on the docs here.
You could try overriding the method using X-Method-Override header. This basically tells the server Hey, I know its a POST. But could you use Patch Instead?.
This may need some additional config on your backend. I had to use the method-override package for express.js.
Mini App:
my.request({
url: 'http://localhost:3000',
headers: {
'x-method-override': 'PATCH',
'content-type': 'application/json'
},
method: 'POST',
complete: (res) => {
console.log(res);
}
});
express.js backend :
const express = require('express')
const methodOverride = require('method-override')
const PORT = process.env.PORT || 3000;
const app = express();
app.use(express.json())
app.use(methodOverride('x-method-override'))
app.get('/', (req, res)=>{
res.send('in get')
})
app.post('/', (req, res)=>{
res.send('in post')
})
app.patch('/', (req, res)=>{
res.send('in patch')
})
app.listen(PORT);

getInitialProps in never called in NextJS

I have problem with getInitialProps method in NextJS. It is never called. This is project where I have Apollo GraphQL client for some pages and getInitialProps for other. I am not sure how to configure them correctly to work.
Apollo is working fine and fetching data as it should. Problem is that getInitialProps isn't called.
Here is my custom _app.js file
const App = ({ Component, pageProps, apollo }) => {
return (
<ApolloProvider client={apollo}>
<Component {...pageProps} />
</ApolloProvider>
)
}
const API_URL =
process.env.NODE_ENV === "development"
? "http://localhost/wordpress/index.php?graphql"
: "https://page/index.php?graphql"
export default withApollo(({ initialState }) => {
return new ApolloClient({
link: new createHttpLink({
uri: API_URL,
fetch: fetch
}),
cache: new InMemoryCache()
})
})(App, { getDataFromTree })
And here is how I call getInitialProps on page
Coupons.getInitialProps = async function() {
const res = await fetch('http://localhost:8000/data/');
const data = await res.json();
console.log(`Data fetched. Count: ${data.length}`);
return {
shows: data.map(entry => entry.show)
};
};
Also. Pages where I have Apollo fetching data doesn't need to call this REST API. Apollo pages and REST pages are totally different
This problem was fixed by following documentation on https://github.com/zeit/next.js/tree/canary/examples/with-apollo
Thing is that I wrapped whole _app in Apollo provider and right way is to wrap only pages that need Apollo in it.
Other that need getInitialProps should remain as is and call REST API in them.

Apollo GraphQL: How to Set Up Secure Websockets?

I'm setting up my dev system to use https, and Chrome is complaining about my websocket not begin secure:
VM4965:161 Mixed Content: The page at 'https://mywebsite.io/' was
loaded over HTTPS, but attempted to connect to the insecure WebSocket
endpoint 'ws://mywebsite.io:4000/subscriptions'. This request has
been blocked; this endpoint must be available over WSS.
Here's my current server-side setup for WS, based on the Apollo docs:
const localHostString = 'mywebsite.io';
const pubsub = new PubSub();
// additional context you use for your resolvers, if any
const context = {connectors: connectors};
//SET UP APOLLO QUERY / MUTATIONS / PUBSUB
//start a graphql server with Express handling a possible Meteor current user
createApolloServer({
schema,
context
});
const METEOR_PORT = 3000;
const GRAPHQL_PORT = 4000;
const server = express();
server.use('*', cors({ origin: `https://${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',
});
});
How can I update this so as to use WSS rather than WS websockets?
Thanks in advance to all for any info.
It looks like you're doing
subscriptionsEndpoint: `ws://${localHostString}:${GRAPHQL_PORT}/subscriptions
Maybe instead, change ws to wss. ie:
subscriptionsEndpoint: `wss://${localHostString}:${GRAPHQL_PORT}/subscriptions

node.js express: How can I know if a request is an AJAX request?

Let's say I have a small piece of code:
var express = require('express');
var app = express();
app.get('/', function(req, res){
//I want to acccess 'req' and get info whether it's an AJAX call
});
app.listen(3000);
When I go inside the app.get(..) function, I want to know if the get request sent is an AJAX call. What is the field in the object 'req' that can tell me this?
The header X-Requested-With: XMLHttpRequest HTTP header is not automatically added to an AJAX request, either with fetch or with the old-fashioned use of the XMLHttpRequest object. It is often added by client libraries such as jQuery.
If the header is present, it is represented in Express by request.xhr.
If you want to add it to the request (the simplest solution to this problem) you can add it as a custom header with fetch:
fetch(url, {
headers: {
"X-Requested-With": "XMLHttpRequest"
}
});
This will now be reflected in req.xhr.
A better solution is to set the Accept header to a sensible value. If you want JSON to be returned, set Accept to application/json:
fetch(url, {
headers: {
"Accept": "application/json"
}
});
You can then test for this with req.accepts:
switch (req.accepts(['html', 'json'])) { //possible response types, in order of preference
case 'html':
// respond with HTML
break;
case 'json':
// respond with JSON
break;
default:
// if the application requested something we can't support
res.status(400).send('Bad Request');
return;
}
This is much more powerful than the req.xhr approach.
app.get('/', function(req, res){
//I want to acccess 'req' and get info whether it's an AJAX call
if(req.xhr){
//the request is ajax call
}
})
var express = require('express');
var app = express();
app.get('/', function(req, res){
var isAjax = req.xhr;
});
app.listen(3000);

Make AJAX request using mootools and node.js with expressjs

I'm trying establish an AJAX connection on node 0.10.3 using mootools. My code is:
Client
var ajax = new Request({
url: '/register',
method: 'post',
onSuccess: function(responseText){
console.log(responseText);
}
})
var json = {data:'data'};
ajax.send(JSON.stringify(json));
//ajax.send(json);
Server
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.listen(1344);
app.post('/register', function(req,res){
//Auth.register()
console.log(req.body);
res.contentType('json');
res.send({ some: JSON.stringify({response:'json'}) })
})
The connection is working Ok. On the client I get the response. So the console.log(responseText) inside the OnSucces method is printing the correct value.
But on the server side, the console.log(req.body) is undefined.
I have a few doubts here. Does mootools converts the javascript object to a json string? Is it necessary to convert de object at all? What is the correct way of sending information trough AJAX to node? Is this ajax.send(JSON.stringify(json)); OK? Or is it like this ajax.send(json);?
Do I need to specify the headers to be json?
Apart for solving the particular problem, it would be nice some article, o some feedback to definitely clarify this concepts around node.js.
EDIT
I'm going to post the correct code, for those who are facing a similar problem. Noah was right about the parser, but there is another detail, the parser is expecting for the key data. Luckily I was using data as example!
Client
var ajax = new Request({
url: '/register',
method: 'post',
onSuccess: function(responseText){
console.log(responseText); //Logs "some": "{\"response\":\"json\"}"
}
})
ajax.send({data:{ok:'OK'}});
Server
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.use(express.bodyParser());
app.listen(1344);
app.post('/register', function(req,res){
console.log(req.body); //logs {ok:'OK'}
res.contentType('json');
res.send({ some: JSON.stringify({response:'json'}) })
})
In the code you posted you are missing the bodyParser middleware app.use(express.bodyParser().
After you add the bodyParser middleware you will be able to access req.body
var express = require('express');
var app = express();
app.use(express.bodyParser()
app.use(express.static(__dirname + '/public'));
app.use(app.router)

Resources