summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-04-13 00:51:55 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-04-13 00:51:55 +0900
commita3bd4ba42693b1dc99ef586ef35f61dc53cdf9e9 (patch)
tree1d9ef7220ca46696ee4ada43f41fcd59d386abc8 /src
parentMerge branch 'master' of https://github.com/syuilo/misskey (diff)
downloadsharkey-a3bd4ba42693b1dc99ef586ef35f61dc53cdf9e9.tar.gz
sharkey-a3bd4ba42693b1dc99ef586ef35f61dc53cdf9e9.tar.bz2
sharkey-a3bd4ba42693b1dc99ef586ef35f61dc53cdf9e9.zip
wip
Diffstat (limited to 'src')
-rw-r--r--src/server/activitypub.ts142
-rw-r--r--src/server/activitypub/inbox.ts32
-rw-r--r--src/server/activitypub/index.ts18
-rw-r--r--src/server/activitypub/note.ts28
-rw-r--r--src/server/activitypub/outbox.ts28
-rw-r--r--src/server/activitypub/publickey.ts23
-rw-r--r--src/server/activitypub/user.ts19
-rw-r--r--src/server/index.ts69
-rw-r--r--src/server/log-request.ts21
-rw-r--r--src/server/webfinger.ts32
10 files changed, 183 insertions, 229 deletions
diff --git a/src/server/activitypub.ts b/src/server/activitypub.ts
new file mode 100644
index 0000000000..ed0311af9d
--- /dev/null
+++ b/src/server/activitypub.ts
@@ -0,0 +1,142 @@
+import * as Router from 'koa-router';
+import { parseRequest } from 'http-signature';
+
+import { createHttp } from '../queue';
+import context from '../remote/activitypub/renderer/context';
+import render from '../remote/activitypub/renderer/note';
+import Note from '../models/note';
+import User, { isLocalUser } from '../models/user';
+import renderNote from '../remote/activitypub/renderer/note';
+import renderKey from '../remote/activitypub/renderer/key';
+import renderPerson from '../remote/activitypub/renderer/person';
+import renderOrderedCollection from '../remote/activitypub/renderer/ordered-collection';
+//import parseAcct from '../acct/parse';
+import config from '../config';
+
+// Init router
+const router = new Router();
+
+//#region Routing
+
+// inbox
+router.post('/users/:user/inbox', ctx => {
+ let signature;
+
+ ctx.req.headers.authorization = 'Signature ' + ctx.req.headers.signature;
+
+ try {
+ signature = parseRequest(ctx.req);
+ } catch (e) {
+ ctx.status = 401;
+ return;
+ }
+
+ createHttp({
+ type: 'processInbox',
+ activity: ctx.request.body,
+ signature
+ }).save();
+
+ ctx.status = 202;
+});
+
+// note
+router.get('/notes/:note', async (ctx, next) => {
+ const accepted = ctx.accepts('html', 'application/activity+json', 'application/ld+json');
+ if (!['application/activity+json', 'application/ld+json'].includes(accepted as string)) {
+ next();
+ return;
+ }
+
+ const note = await Note.findOne({
+ _id: ctx.params.note
+ });
+
+ if (note === null) {
+ ctx.status = 404;
+ return;
+ }
+
+ const rendered = await render(note);
+ rendered['@context'] = context;
+
+ ctx.body = rendered;
+});
+
+// outbot
+router.get('/users/:user/outbox', async ctx => {
+ const userId = ctx.params.user;
+
+ const user = await User.findOne({ _id: userId });
+
+ if (user === null) {
+ ctx.status = 404;
+ return;
+ }
+
+ const notes = await Note.find({ userId: user._id }, {
+ limit: 10,
+ sort: { _id: -1 }
+ });
+
+ const renderedNotes = await Promise.all(notes.map(note => renderNote(note)));
+ const rendered = renderOrderedCollection(`${config.url}/users/${userId}/inbox`, user.notesCount, renderedNotes);
+ rendered['@context'] = context;
+
+ ctx.body = rendered;
+});
+
+// publickey
+router.get('/users/:user/publickey', async ctx => {
+ const userId = ctx.params.user;
+
+ const user = await User.findOne({ _id: userId });
+
+ if (user === null) {
+ ctx.status = 404;
+ return;
+ }
+
+ if (isLocalUser(user)) {
+ const rendered = renderKey(user);
+ rendered['@context'] = context;
+
+ ctx.body = rendered;
+ } else {
+ ctx.status = 400;
+ }
+});
+
+// user
+router.get('/users/:user', async ctx => {
+ const userId = ctx.params.user;
+
+ const user = await User.findOne({ _id: userId });
+
+ if (user === null) {
+ ctx.status = 404;
+ return;
+ }
+
+ const rendered = renderPerson(user);
+ rendered['@context'] = context;
+
+ ctx.body = rendered;
+});
+
+// follow form
+router.get('/authorize-follow', async ctx => {
+ /* TODO
+ const { username, host } = parseAcct(ctx.query.acct);
+ if (host === null) {
+ res.sendStatus(422);
+ return;
+ }
+
+ const finger = await request(`https://${host}`)
+ */
+});
+
+//#endregion
+
+export default router;
diff --git a/src/server/activitypub/inbox.ts b/src/server/activitypub/inbox.ts
deleted file mode 100644
index 643d2945bd..0000000000
--- a/src/server/activitypub/inbox.ts
+++ /dev/null
@@ -1,32 +0,0 @@
-import * as bodyParser from 'body-parser';
-import * as express from 'express';
-import { parseRequest } from 'http-signature';
-import { createHttp } from '../../queue';
-
-const app = express.Router();
-
-app.post('/users/:user/inbox', bodyParser.json({
- type() {
- return true;
- }
-}), async (req, res) => {
- let signature;
-
- req.headers.authorization = 'Signature ' + req.headers.signature;
-
- try {
- signature = parseRequest(req);
- } catch (exception) {
- return res.sendStatus(401);
- }
-
- createHttp({
- type: 'processInbox',
- activity: req.body,
- signature,
- }).save();
-
- return res.status(202).end();
-});
-
-export default app;
diff --git a/src/server/activitypub/index.ts b/src/server/activitypub/index.ts
deleted file mode 100644
index 042579db9d..0000000000
--- a/src/server/activitypub/index.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import * as express from 'express';
-
-import user from './user';
-import inbox from './inbox';
-import outbox from './outbox';
-import publicKey from './publickey';
-import note from './note';
-
-const app = express();
-app.disable('x-powered-by');
-
-app.use(user);
-app.use(inbox);
-app.use(outbox);
-app.use(publicKey);
-app.use(note);
-
-export default app;
diff --git a/src/server/activitypub/note.ts b/src/server/activitypub/note.ts
deleted file mode 100644
index 1c2e695b80..0000000000
--- a/src/server/activitypub/note.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import * as express from 'express';
-import context from '../../remote/activitypub/renderer/context';
-import render from '../../remote/activitypub/renderer/note';
-import Note from '../../models/note';
-
-const app = express.Router();
-
-app.get('/notes/:note', async (req, res, next) => {
- const accepted = req.accepts(['html', 'application/activity+json', 'application/ld+json']);
- if (!(['application/activity+json', 'application/ld+json'] as any[]).includes(accepted)) {
- return next();
- }
-
- const note = await Note.findOne({
- _id: req.params.note
- });
-
- if (note === null) {
- return res.sendStatus(404);
- }
-
- const rendered = await render(note);
- rendered['@context'] = context;
-
- res.json(rendered);
-});
-
-export default app;
diff --git a/src/server/activitypub/outbox.ts b/src/server/activitypub/outbox.ts
deleted file mode 100644
index 1c97c17a2e..0000000000
--- a/src/server/activitypub/outbox.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import * as express from 'express';
-import context from '../../remote/activitypub/renderer/context';
-import renderNote from '../../remote/activitypub/renderer/note';
-import renderOrderedCollection from '../../remote/activitypub/renderer/ordered-collection';
-import config from '../../config';
-import Note from '../../models/note';
-import User from '../../models/user';
-
-const app = express.Router();
-
-app.get('/users/:user/outbox', async (req, res) => {
- const userId = req.params.user;
-
- const user = await User.findOne({ _id: userId });
-
- const notes = await Note.find({ userId: user._id }, {
- limit: 20,
- sort: { _id: -1 }
- });
-
- const renderedNotes = await Promise.all(notes.map(note => renderNote(note)));
- const rendered = renderOrderedCollection(`${config.url}/users/${userId}/inbox`, user.notesCount, renderedNotes);
- rendered['@context'] = context;
-
- res.json(rendered);
-});
-
-export default app;
diff --git a/src/server/activitypub/publickey.ts b/src/server/activitypub/publickey.ts
deleted file mode 100644
index e874b82729..0000000000
--- a/src/server/activitypub/publickey.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import * as express from 'express';
-import context from '../../remote/activitypub/renderer/context';
-import render from '../../remote/activitypub/renderer/key';
-import User, { isLocalUser } from '../../models/user';
-
-const app = express.Router();
-
-app.get('/users/:user/publickey', async (req, res) => {
- const userId = req.params.user;
-
- const user = await User.findOne({ _id: userId });
-
- if (isLocalUser(user)) {
- const rendered = render(user);
- rendered['@context'] = context;
-
- res.json(rendered);
- } else {
- res.sendStatus(400);
- }
-});
-
-export default app;
diff --git a/src/server/activitypub/user.ts b/src/server/activitypub/user.ts
deleted file mode 100644
index 9e98e92b6a..0000000000
--- a/src/server/activitypub/user.ts
+++ /dev/null
@@ -1,19 +0,0 @@
-import * as express from 'express';
-import context from '../../remote/activitypub/renderer/context';
-import render from '../../remote/activitypub/renderer/person';
-import User from '../../models/user';
-
-const app = express.Router();
-
-app.get('/users/:user', async (req, res) => {
- const userId = req.params.user;
-
- const user = await User.findOne({ _id: userId });
-
- const rendered = render(user);
- rendered['@context'] = context;
-
- res.json(rendered);
-});
-
-export default app;
diff --git a/src/server/index.ts b/src/server/index.ts
index 962d3b5f4f..e9bfa9e10b 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -5,67 +5,40 @@
import * as fs from 'fs';
import * as http from 'http';
import * as https from 'https';
-import * as express from 'express';
-import * as morgan from 'morgan';
+import * as Koa from 'koa';
+import * as Router from 'koa-router';
+import * as bodyParser from 'koa-bodyparser';
import activityPub from './activitypub';
import webFinger from './webfinger';
-import log from './log-request';
import config from '../config';
-/**
- * Init app
- */
-const app = express();
-app.disable('x-powered-by');
-app.set('trust proxy', 'loopback');
-
-app.use(morgan(process.env.NODE_ENV == 'production' ? 'combined' : 'dev', {
- // create a write stream (in append mode)
- stream: config.accesslog ? fs.createWriteStream(config.accesslog) : null
-}));
-
-app.use((req, res, next) => {
- log(req);
- next();
-});
+// Init server
+const app = new Koa();
+app.proxy = true;
+app.use(bodyParser);
-/**
- * HSTS
- * 6month(15552000sec)
- */
+// HSTS
+// 6months (15552000sec)
if (config.url.startsWith('https')) {
- app.use((req, res, next) => {
- res.header('strict-transport-security', 'max-age=15552000; preload');
+ app.use((ctx, next) => {
+ ctx.set('strict-transport-security', 'max-age=15552000; preload');
next();
});
}
-// Drop request when without 'Host' header
-app.use((req, res, next) => {
- if (!req.headers['host']) {
- res.sendStatus(400);
- } else {
- next();
- }
-});
+// Init router
+const router = new Router();
-// 互換性のため
-app.post('/meta', (req, res) => {
- res.header('Access-Control-Allow-Origin', '*');
- res.json({
- version: 'nighthike'
- });
-});
+// Routing
+router.use('/api', require('./api'));
+router.use('/files', require('./file'));
+router.use(activityPub.routes());
+router.use(webFinger.routes());
+router.use(require('./web'));
-/**
- * Register modules
- */
-app.use('/api', require('./api'));
-app.use('/files', require('./file'));
-app.use(activityPub);
-app.use(webFinger);
-app.use(require('./web'));
+// Register router
+app.use(router.routes());
function createServer() {
if (config.https) {
diff --git a/src/server/log-request.ts b/src/server/log-request.ts
deleted file mode 100644
index e431aa271d..0000000000
--- a/src/server/log-request.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import * as crypto from 'crypto';
-import * as express from 'express';
-import * as proxyAddr from 'proxy-addr';
-import Xev from 'xev';
-
-const ev = new Xev();
-
-export default function(req: express.Request) {
- const ip = proxyAddr(req, () => true);
-
- const md5 = crypto.createHash('md5');
- md5.update(ip);
- const hashedIp = md5.digest('hex').substr(0, 3);
-
- ev.emit('request', {
- ip: hashedIp,
- method: req.method,
- hostname: req.hostname,
- path: req.originalUrl
- });
-}
diff --git a/src/server/webfinger.ts b/src/server/webfinger.ts
index dbf0999f3e..e72592351b 100644
--- a/src/server/webfinger.ts
+++ b/src/server/webfinger.ts
@@ -1,17 +1,19 @@
-import * as express from 'express';
+import * as Router from 'koa-router';
import config from '../config';
import parseAcct from '../acct/parse';
import User from '../models/user';
-const app = express.Router();
+// Init router
+const router = new Router();
-app.get('/.well-known/webfinger', async (req, res) => {
- if (typeof req.query.resource !== 'string') {
- return res.sendStatus(400);
+router.get('/.well-known/webfinger', async ctx => {
+ if (typeof ctx.query.resource !== 'string') {
+ ctx.status = 400;
+ return;
}
- const resourceLower = req.query.resource.toLowerCase();
+ const resourceLower = ctx.query.resource.toLowerCase();
const webPrefix = config.url.toLowerCase() + '/@';
let acctLower;
@@ -25,15 +27,21 @@ app.get('/.well-known/webfinger', async (req, res) => {
const parsedAcctLower = parseAcct(acctLower);
if (![null, config.host.toLowerCase()].includes(parsedAcctLower.host)) {
- return res.sendStatus(422);
+ ctx.status = 422;
+ return;
}
- const user = await User.findOne({ usernameLower: parsedAcctLower.username, host: null });
+ const user = await User.findOne({
+ usernameLower: parsedAcctLower.username,
+ host: null
+ });
+
if (user === null) {
- return res.sendStatus(404);
+ ctx.status = 404;
+ return;
}
- return res.json({
+ ctx.body = {
subject: `acct:${user.username}@${config.host}`,
links: [{
rel: 'self',
@@ -47,7 +55,7 @@ app.get('/.well-known/webfinger', async (req, res) => {
rel: 'http://ostatus.org/schema/1.0/subscribe',
template: `${config.url}/authorize-follow?acct={uri}`
}]
- });
+ };
});
-export default app;
+export default router;