I have found the best way to do this in React is to add the csrf
token to a store, or pass it to the component context.
You can see how its done by slightly altering the Yahoo Fluxible react-router example.
context.executeAction(setTokenAction, req.csrfToken(), function(){});
This executes a flux action with the csrf
token as a parameter. The Yahoo flux architecture serializes the values of the store to the client via:
var exposed = 'window.App=' + serialize(app.dehydrate(context)) + ';';
This gets written out to the page in a script tag, which can then be accessed on in the client-side javascript. It will look something like this:
<script>
window.App = {
context: {
dispatcher: {
stores: {
ApplicationStore: {
csrf: "1234abcd",
}
}
}
}
};
</script>
Here is the Html.jsx component in the Flux example.
If you are not creating an isomorphic application (the React components are run on the sever as well as the client) then I would suggest just to write out a script tag that contains the csrf
token.
For Fluxible that value is then rehydrated on the client.
var dehydratedState = window.App; // Sent from the server
var app = require('./app');
app.rehydrate(dehydratedState, function (err, context) {
...
});
Leaving you with a populated store on the client without an additional http request. You can then access the csrf
token from anywhere by accessing the store.
You can pass it via the context by doing something like this:
var componentContext = context.getComponentContext();
componentContext.csrf = req.csrfToken();
...
var markup = React.renderToString(Component({context: componentContext}))
You can then access it via the component's props.
this.props.context.csrf
If you are using Fluxible and want to pass it via the context I would maybe do it in a plugin, but you get the idea.
Full sever code:
/**
* Copyright 2014, Yahoo! Inc.
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
*/
require('babel/register');
var express = require('express');
var favicon = require('serve-favicon');
var serialize = require('serialize-javascript');
var navigateAction = require('./actions/navigate');
var setCsrfTokenAction = require('./actions/setCsrfToken');
var debug = require('debug')('Example');
var React = require('react');
var app = require('./app');
var HtmlComponent = React.createFactory(require('./components/Html.jsx'));
var Router = require('react-router');
var server = express();
server.use(favicon(__dirname + '/../favicon.ico'));
server.use('/public', express.static(__dirname + '/build'));
server.use(function (req, res, next) {
var context = app.createContext();
debug('Executing navigate action');
Router.run(app.getComponent(), req.path, function (Handler, state) {
context.executeAction(setCsrfTokenAction, req.csrfToken(), function(){});
context.executeAction(navigateAction, state, function () {
debug('Exposing context state');
var exposed = 'window.App=' + serialize(app.dehydrate(context)) + ';';
debug('Rendering Application component into html');
var Component = React.createFactory(Handler);
var html = React.renderToStaticMarkup(HtmlComponent({
state: exposed,
markup: React.renderToString(Component({context:context.getComponentContext()}))
}));
debug('Sending markup');
res.send(html);
});
});
});
var port = process.env.PORT || 3000;
server.listen(port);
console.log('Listening on port ' + port);
$http
service handles this by looking for a session cookie, and including that on every outgoing XHR request. – Yand