mirror of
https://github.com/wassname/talk.git
synced 2026-07-27 11:28:12 +08:00
working websockets
This commit is contained in:
@@ -4,13 +4,11 @@ const morgan = require('morgan');
|
||||
const path = require('path');
|
||||
const helmet = require('helmet');
|
||||
const passport = require('./services/passport');
|
||||
const session = require('express-session');
|
||||
const enabled = require('debug').enabled;
|
||||
const RedisStore = require('connect-redis')(session);
|
||||
const redis = require('./services/redis');
|
||||
const csrf = require('csurf');
|
||||
const errors = require('./errors');
|
||||
const graph = require('./graph');
|
||||
const session = require('./services/session');
|
||||
const {createGraphOptions} = require('./graph');
|
||||
const apollo = require('graphql-server-express');
|
||||
|
||||
const app = express();
|
||||
@@ -42,34 +40,7 @@ app.set('view engine', 'ejs');
|
||||
// SESSION MIDDLEWARE
|
||||
//==============================================================================
|
||||
|
||||
const session_opts = {
|
||||
secret: process.env.TALK_SESSION_SECRET,
|
||||
httpOnly: true,
|
||||
rolling: true,
|
||||
saveUninitialized: true,
|
||||
resave: true,
|
||||
unset: 'destroy',
|
||||
name: 'talk.sid',
|
||||
cookie: {
|
||||
secure: false,
|
||||
maxAge: 8.64e+7, // 24 hours for session token expiry
|
||||
},
|
||||
store: new RedisStore({
|
||||
client: redis.createClient(),
|
||||
})
|
||||
};
|
||||
|
||||
if (app.get('env') === 'production') {
|
||||
|
||||
// Enable the secure cookie when we are in production mode.
|
||||
session_opts.cookie.secure = true;
|
||||
} else if (app.get('env') === 'test') {
|
||||
|
||||
// Add in the secret during tests.
|
||||
session_opts.secret = 'keyboard cat';
|
||||
}
|
||||
|
||||
app.use(session(session_opts));
|
||||
app.use(session);
|
||||
|
||||
//==============================================================================
|
||||
// PASSPORT MIDDLEWARE
|
||||
@@ -83,10 +54,8 @@ app.use(passport.session());
|
||||
// GraphQL Router
|
||||
//==============================================================================
|
||||
|
||||
graph.createSubscriptionManager(app, '/api/v1/live');
|
||||
|
||||
// GraphQL endpoint.
|
||||
app.use('/api/v1/graph/ql', apollo.graphqlExpress(graph.createGraphOptions));
|
||||
app.use('/api/v1/graph/ql', apollo.graphqlExpress(createGraphOptions));
|
||||
|
||||
// Only include the graphiql tool if we aren't in production mode.
|
||||
if (app.get('env') !== 'production') {
|
||||
|
||||
+5
-3
@@ -1,14 +1,14 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const app = require('../app');
|
||||
const program = require('./commander');
|
||||
const app = require('../app');
|
||||
const {createServer} = require('http');
|
||||
const scraper = require('../services/scraper');
|
||||
const mailer = require('../services/mailer');
|
||||
const kue = require('../services/kue');
|
||||
const mongoose = require('../services/mongoose');
|
||||
const util = require('./util');
|
||||
const {createSubscriptionManager} = require('../graph');
|
||||
const subscriptions = require('../services/subscriptions');
|
||||
|
||||
/**
|
||||
* Get port from environment and store in Express.
|
||||
@@ -91,7 +91,9 @@ function startApp() {
|
||||
* Listen on provided port, on all network interfaces.
|
||||
*/
|
||||
server.listen(port, () => {
|
||||
createSubscriptionManager(server, '/api/v1/live');
|
||||
|
||||
// Mount the subscriptions server on the application server.
|
||||
subscriptions.mount(server);
|
||||
});
|
||||
|
||||
server.on('error', onError);
|
||||
|
||||
@@ -3,6 +3,8 @@ import React from 'react';
|
||||
import {graphql} from 'react-apollo';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import PubDate from 'coral-plugin-pubdate/PubDate';
|
||||
|
||||
class Embed extends React.Component {
|
||||
|
||||
static propTypes = {
|
||||
@@ -20,18 +22,24 @@ class Embed extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
console.log(this.props);
|
||||
const {asset, loading} = this.props.data;
|
||||
return (
|
||||
<div>
|
||||
<h1>Live Stream</h1>
|
||||
<ul>
|
||||
<h1>Wyatt's Awesome Live Stream</h1>
|
||||
<div>
|
||||
{!loading && asset && asset.comments && asset.comments.map((comment) => (
|
||||
<li key={comment.id}>
|
||||
<span>{comment.id} {comment.body}</span>
|
||||
</li>
|
||||
<div key={comment.id} style={{position: 'relative'}}>
|
||||
<span>
|
||||
<b>{comment.user.username}</b> - {comment.body}
|
||||
</span>
|
||||
<span
|
||||
style={{float: 'right'}}
|
||||
>
|
||||
<PubDate created_at={comment.created_at} />
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -40,12 +48,13 @@ class Embed extends React.Component {
|
||||
const COMMENT_QUERY = gql`
|
||||
query Comment($assetID: ID!) {
|
||||
asset(id: $assetID) {
|
||||
comments {
|
||||
comments(limit: 50) {
|
||||
id
|
||||
body
|
||||
user {
|
||||
username
|
||||
}
|
||||
created_at
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,6 +68,7 @@ const COMMENTS_SUBSCRIPTION = gql`
|
||||
user {
|
||||
username
|
||||
}
|
||||
created_at
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -95,8 +105,6 @@ const withData = graphql(COMMENT_QUERY, {
|
||||
}
|
||||
};
|
||||
|
||||
console.log('updateQuery', before, after);
|
||||
|
||||
return after;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -10,7 +10,7 @@ import Embed from './Embed';
|
||||
|
||||
render(
|
||||
<ApolloProvider client={client}>
|
||||
<Embed assetID='8377903e-2601-47d9-af8a-1baab5651da9' />
|
||||
<Embed assetID='7babeab7-4546-4b2d-a0cd-841bd4e32c05' />
|
||||
</ApolloProvider>
|
||||
, document.querySelector('#coralStream')
|
||||
);
|
||||
|
||||
@@ -2,7 +2,7 @@ import ApolloClient, {addTypename} from 'apollo-client';
|
||||
import getNetworkInterface from './transport';
|
||||
|
||||
import {SubscriptionClient, addGraphQLSubscriptions} from 'subscriptions-transport-ws';
|
||||
const wsClient = new SubscriptionClient('ws://localhost:3001/api/v1/live', {
|
||||
const wsClient = new SubscriptionClient('ws://localhost:3000/api/v1/live', {
|
||||
reconnect: true
|
||||
});
|
||||
const networkInterface = getNetworkInterface();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
const loaders = require('./loaders');
|
||||
const mutators = require('./mutators');
|
||||
const uuid = require('uuid');
|
||||
|
||||
const plugins = require('../plugins');
|
||||
const debug = require('debug')('talk:graph:context');
|
||||
@@ -33,6 +34,9 @@ const decorateContextPlugins = (context, contextPlugins) => contextPlugins.reduc
|
||||
class Context {
|
||||
constructor({user = null}, pubsub) {
|
||||
|
||||
// Generate a new context id for the request.
|
||||
this.id = uuid.v4();
|
||||
|
||||
// Load the current logged in user to `user`, otherwise this'll be null.
|
||||
if (user) {
|
||||
this.user = user;
|
||||
|
||||
+14
-4
@@ -19,7 +19,7 @@ module.exports = {
|
||||
// the lifespan of this request.
|
||||
context: new Context(req, pubsub)
|
||||
}),
|
||||
createSubscriptionManager: (server, path) => new SubscriptionServer({
|
||||
createSubscriptionManager: (server, path, sessionFactory) => new SubscriptionServer({
|
||||
subscriptionManager: new SubscriptionManager({
|
||||
schema,
|
||||
pubsub,
|
||||
@@ -31,9 +31,19 @@ module.exports = {
|
||||
}),
|
||||
}
|
||||
}),
|
||||
// onConnect: (connectionParams, webSocket) => {
|
||||
// console.log(webSocket.upgradeReq.headers);
|
||||
// }
|
||||
onSubscribe: (parsedMessage, baseParams, connection) => {
|
||||
|
||||
// Attach the context per request.
|
||||
baseParams.context = () => sessionFactory(connection.upgradeReq)
|
||||
.then((req) => new Context(req, pubsub))
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
|
||||
return new Context({}, pubsub);
|
||||
});
|
||||
|
||||
return baseParams;
|
||||
}
|
||||
}, {
|
||||
server,
|
||||
path
|
||||
|
||||
@@ -5,6 +5,10 @@ module.exports = new GraphQLScalarType({
|
||||
name: 'Date',
|
||||
description: 'Date represented as an ISO8601 string',
|
||||
serialize(value) {
|
||||
if (typeof value === 'string') {
|
||||
return value;
|
||||
}
|
||||
|
||||
return value.toISOString();
|
||||
},
|
||||
parseValue(value) {
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
const session = require('express-session');
|
||||
const RedisStore = require('connect-redis')(session);
|
||||
const redis = require('./services/redis');
|
||||
|
||||
//==============================================================================
|
||||
// SESSION MIDDLEWARE
|
||||
//==============================================================================
|
||||
|
||||
const session_opts = {
|
||||
secret: process.env.TALK_SESSION_SECRET,
|
||||
httpOnly: true,
|
||||
rolling: true,
|
||||
saveUninitialized: true,
|
||||
resave: true,
|
||||
unset: 'destroy',
|
||||
name: 'talk.sid',
|
||||
cookie: {
|
||||
secure: false,
|
||||
maxAge: 8.64e+7, // 24 hours for session token expiry
|
||||
},
|
||||
store: new RedisStore({
|
||||
client: redis.createClient(),
|
||||
})
|
||||
};
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
|
||||
// Enable the secure cookie when we are in production mode.
|
||||
session_opts.cookie.secure = true;
|
||||
} else if (process.env.NODE_ENV === 'test') {
|
||||
|
||||
// Add in the secret during tests.
|
||||
session_opts.secret = 'keyboard cat';
|
||||
}
|
||||
|
||||
module.exports = session(session_opts);
|
||||
@@ -0,0 +1,35 @@
|
||||
const {createSubscriptionManager} = require('../graph');
|
||||
const session = require('./session');
|
||||
const passport = require('./passport');
|
||||
|
||||
module.exports = class Subscriptions {
|
||||
|
||||
static deserializeUser(req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
session(req, {}, () => {
|
||||
|
||||
if ('session' in req && 'passport' in req.session && 'user' in req.session.passport) {
|
||||
passport.deserializeUser(req.session.passport.user, (err, user) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
||||
req.user = user;
|
||||
|
||||
return resolve(req);
|
||||
});
|
||||
} else {
|
||||
resolve(req);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static mount(server) {
|
||||
|
||||
// Create the SubscriptionManager and mount it on the specified route with
|
||||
// this deserializer.
|
||||
createSubscriptionManager(server, '/api/v1/live', Subscriptions.deserializeUser);
|
||||
}
|
||||
};
|
||||
@@ -4251,10 +4251,6 @@ jsbn@~0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd"
|
||||
|
||||
jsdom-global@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/jsdom-global/-/jsdom-global-2.1.1.tgz#47d46fe77f6167baf5d34431d3bb59fc41b0915a"
|
||||
|
||||
jsdom@^7.0.2:
|
||||
version "7.2.2"
|
||||
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-7.2.2.tgz#40b402770c2bda23469096bee91ab675e3b1fc6e"
|
||||
@@ -4275,7 +4271,7 @@ jsdom@^7.0.2:
|
||||
whatwg-url-compat "~0.6.5"
|
||||
xml-name-validator ">= 2.0.1 < 3.0.0"
|
||||
|
||||
jsdom@^9.12.0:
|
||||
jsdom@^9.8.3:
|
||||
version "9.12.0"
|
||||
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-9.12.0.tgz#e8c546fffcb06c00d4833ca84410fed7f8a097d4"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user