I've been trying to send set and call-requests with Falcor model from react-client on port 3000 to node.js server which is serving the router on port 3001. The get-request is working without a problem but with set and call requests I'm just getting Internal Server Error.
I tried adding the body-parser to the server and crossDomain:true to the client request as for some it fixed the problem but it seems that those weren't the cause.
Then I tried separating the set-request to it's own route but the result was still the same.
To be honest I'm not even sure at this point is the problem with falcor, client or backend. It's even more confusing that the get-request works just fine.
I noticed something about set and call requests. When sending that type of requests to the server the request's query-object is empty. When sending a working get-request to the same route the object is like this
{ paths: '[["user","marisanity",["_id","games_length"]]]',
method: 'get' }
I don't know if that helps.
This is the server side:
server.js
const express = require('express');
const config = require('config');
const app = express();
const FalcorServer = require('falcor-express');
const bodyParser = require('body-parser');
const userRouter = require('./src/routes/users');
if (!config.get('jwtPrivateKey')) {
console.error('jwtPrivateKey is not defined, shutting down');
process.exit(1);
}
app.use(bodyParser.urlencoded({extended: false}));
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", `http://localhost:3000`);
res.header("Access-Control-Allow-Headers", "Authorization, X-Auth-Token, Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Credentials", "true");
next();
});
app.use('/api/users/model.json', FalcorServer.dataSourceRoute((req) => userRouter(req)));
const port = process.env.PORT || 3001;
app.listen(port, () => {console.log(`Listening on port ${port}`)});
users.js
const userRepository = require('./../db/repositories/userRepository');
const Router = require('falcor-router');
let UserRouterBase = Router.createClass([
{
route: "user[{keys:username}][{keys:fields}]",
get: async function (pathSet) {
const results = [];
return await userRepository.findByUsername(pathSet.username).then(user => {
if (user === null || user.games.length === 0) {
return ({
path: ['users'],
value: "No results"
});
} else {
pathSet.fields.forEach(field => {
if (field === 'games_length') {
results.push({
path: ['user', pathSet.username[0], "games_length"],
value: user.games.length
});
} else {
results.push({
path: ['user', pathSet.username[0], field],
value: String(user[field])
});
}
});
return results;
}
})
},
async set(jsonGraphArg) {
console.log(jsonGraphArg);
return {
path: ['user', 'marisanity', 'games_length'],
value: 'test'
};
}
}
]);
let UserRouter = function (res) {
UserRouterBase.call(this);
//used later to pass token for this component
this.res = res;
};
UserRouter.prototype = Object.create(UserRouterBase.prototype);
module.exports = function (res) {
return new UserRouter(res);
};
This is the client side:
import React, {Component} from 'react';
import Falcor from 'falcor';
import HttpDataSource from 'falcor-http-datasource';
export default class Test extends Component {
constructor(props) {
super(props);
this.userModel = this.constructUserModel();
}
componentDidMount() {
//works just fine
this.fetchUserInfo();
//this produces error
this.editUSerInfo();
}
constructUserModel = () => {
return new Falcor.Model({
source: new HttpDataSource('http://localhost:3001/api/users/model.json', {
crossDomain: true,
headers: {
'x-auth-token': "secret"
}
})
});
};
editUSerInfo = () => {
this.userModel.setValue(["user", "marisanity","games_length"], 3).then(function(done){
console.log(done);
});
};
fetchUserInfo = () => {
this.userModel.get(["user", ['marisanity'], ['_id', 'games_length']])
.then(function (response) {
console.log(response);
});
};
}
And finally this is the error that is shown in the browser:
OPTIONS http://localhost:3001/api/users/model.json 500 (Internal Server Error)
requestObserver @ request.js:135
o.subscribe @ request.js:30
sendSetRequest @ sendSetRequest.js:41
set @ RequestQueueV2.js:40
setRequestCycle @ setRequestCycle.js:63
_subscribe @ SetResponse.js:89
subscribe @ ModelResponse.js:90
(anonymous) @ setValue.js:25
subscribe @ ModelResponse.js:90
(anonymous) @ ModelResponse.js:137
then @ ModelResponse.js:134
Test._this.editUSerInfo @ Wow.js:55
componentDidMount @ Wow.js:18
commitLifeCycles @ react-dom.development.js:18071
commitAllLifeCycles @ react-dom.development.js:19630
callCallback @ react-dom.development.js:147
invokeGuardedCallbackDev @ react-dom.development.js:196
invokeGuardedCallback @ react-dom.development.js:250
commitRoot @ react-dom.development.js:19854
(anonymous) @ react-dom.development.js:21402
unstable_runWithPriority @ scheduler.development.js:255
completeRoot @ react-dom.development.js:21401
performWorkOnRoot @ react-dom.development.js:21324
performWork @ react-dom.development.js:21229
performSyncWork @ react-dom.development.js:21203
requestWork @ react-dom.development.js:21058
scheduleWork @ react-dom.development.js:20871
scheduleRootUpdate @ react-dom.development.js:21566
updateContainerAtExpirationTime @ react-dom.development.js:21592
updateContainer @ react-dom.development.js:21660
push../node_modules/react-dom/cjs/react-dom.development.js.ReactRoot.render @ react-dom.development.js:21973
(anonymous) @ react-dom.development.js:22125
unbatchedUpdates @ react-dom.development.js:21448
legacyRenderSubtreeIntoContainer @ react-dom.development.js:22121
render @ react-dom.development.js:22196
./src/index.js @ index.js:7
__webpack_require__ @ bootstrap:781
fn @ bootstrap:149
0 @ Yay.js:4
__webpack_require__ @ bootstrap:781
checkDeferredModules @ bootstrap:45
webpackJsonpCallback @ bootstrap:32
(anonymous)
This issue was caused by invalid CORS-configurations. It was solved by replacing the old configurations with Express' official CORS middleware: