From f298fc6eb39553ed14080694b6f22c83ff49c057 Mon Sep 17 00:00:00 2001
From: syuilo <syuilotan@yahoo.co.jp>
Date: Tue, 27 Mar 2018 14:13:12 +0900
Subject: [PATCH] Bye bye subdomains

---
 src/config.ts                 | 12 ++++-----
 src/server.ts                 |  1 -
 src/web/app/boot.js           | 16 +++++------
 src/web/app/desktop/script.ts | 39 +++++++++++++++------------
 src/web/app/dev/script.ts     | 23 +++++++++-------
 src/web/app/init.ts           |  8 +++---
 src/web/app/mobile/script.ts  | 51 +++++++++++++++++++----------------
 src/web/server.ts             |  5 +---
 8 files changed, 81 insertions(+), 74 deletions(-)

diff --git a/src/config.ts b/src/config.ts
index 349b161de1..6d3e7740b1 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -109,7 +109,6 @@ type Mixin = {
 	ws_url: string;
 	auth_url: string;
 	docs_url: string;
-	ch_url: string;
 	stats_url: string;
 	status_url: string;
 	dev_url: string;
@@ -135,12 +134,11 @@ export default function load() {
 	mixin.ws_scheme = mixin.scheme.replace('http', 'ws');
 	mixin.ws_url = `${mixin.ws_scheme}://${mixin.host}`;
 	mixin.api_url = `${mixin.scheme}://${mixin.host}/api`;
-	mixin.auth_url = `${mixin.scheme}://auth.${mixin.host}`;
-	mixin.ch_url = `${mixin.scheme}://ch.${mixin.host}`;
-	mixin.dev_url = `${mixin.scheme}://dev.${mixin.host}`;
-	mixin.docs_url = `${mixin.scheme}://docs.${mixin.host}`;
-	mixin.stats_url = `${mixin.scheme}://stats.${mixin.host}`;
-	mixin.status_url = `${mixin.scheme}://status.${mixin.host}`;
+	mixin.auth_url = `${mixin.scheme}://${mixin.host}/auth`;
+	mixin.dev_url = `${mixin.scheme}://${mixin.host}/dev`;
+	mixin.docs_url = `${mixin.scheme}://${mixin.host}/docs`;
+	mixin.stats_url = `${mixin.scheme}://${mixin.host}/stats`;
+	mixin.status_url = `${mixin.scheme}://${mixin.host}/status`;
 	mixin.drive_url = `${mixin.scheme}://${mixin.host}/files`;
 
 	return Object.assign(config, mixin);
diff --git a/src/server.ts b/src/server.ts
index 00d09f1538..0e030002a8 100644
--- a/src/server.ts
+++ b/src/server.ts
@@ -9,7 +9,6 @@ import * as cluster from 'cluster';
 import * as express from 'express';
 import * as morgan from 'morgan';
 import Accesses from 'accesses';
-import vhost = require('vhost');
 
 import log from './log-request';
 import config from './conf';
diff --git a/src/web/app/boot.js b/src/web/app/boot.js
index 00ac9daad9..0846e4bd55 100644
--- a/src/web/app/boot.js
+++ b/src/web/app/boot.js
@@ -21,13 +21,13 @@
 	// Get the current url information
 	const url = new URL(location.href);
 
-	// Extarct the (sub) domain part of the current url
-	//
-	// e.g.
-	//   misskey.alice               => misskey
-	//   misskey.strawberry.pasta    => misskey
-	//   dev.misskey.arisu.tachibana => dev
-	let app = url.host === HOST ? 'misskey' : url.host.substr(0, -HOST.length);
+	//#region Detect app name
+	let app = null;
+
+	if (url.pathname == '/docs') app = 'docs';
+	if (url.pathname == '/dev') app = 'dev';
+	if (url.pathname == '/auth') app = 'auth';
+	//#endregion
 
 	// Detect the user language
 	// Note: The default language is English
@@ -57,7 +57,7 @@
 	}
 
 	// Switch desktop or mobile version
-	if (app == 'misskey') {
+	if (app == null) {
 		app = isMobile ? 'mobile' : 'desktop';
 	}
 
diff --git a/src/web/app/desktop/script.ts b/src/web/app/desktop/script.ts
index f2bcc6f8a6..145cc45db2 100644
--- a/src/web/app/desktop/script.ts
+++ b/src/web/app/desktop/script.ts
@@ -2,13 +2,15 @@
  * Desktop Client
  */
 
+import VueRouter from 'vue-router';
+
 // Style
 import './style.styl';
 import '../../element.scss';
 
 import init from '../init';
 import fuckAdBlock from '../common/scripts/fuck-ad-block';
-import HomeStreamManager from '../common/scripts/streaming/home-stream-manager';
+import { HomeStreamManager } from '../common/scripts/streaming/home';
 import composeNotification from '../common/scripts/compose-notification';
 
 import chooseDriveFolder from './api/choose-drive-folder';
@@ -41,8 +43,26 @@ init(async (launch) => {
 	require('./views/components');
 	require('./views/widgets');
 
+	// Init router
+	const router = new VueRouter({
+		mode: 'history',
+		routes: [
+			{ path: '/', name: 'index', component: MkIndex },
+			{ path: '/i/customize-home', component: MkHomeCustomize },
+			{ path: '/i/messaging/:username', component: MkMessagingRoom },
+			{ path: '/i/drive', component: MkDrive },
+			{ path: '/i/drive/folder/:folder', component: MkDrive },
+			{ path: '/selectdrive', component: MkSelectDrive },
+			{ path: '/search', component: MkSearch },
+			{ path: '/othello', component: MkOthello },
+			{ path: '/othello/:game', component: MkOthello },
+			{ path: '/@:user', component: MkUser },
+			{ path: '/@:user/:post', component: MkPost }
+		]
+	});
+
 	// Launch the app
-	const [app, os] = launch(os => ({
+	const [, os] = launch(router, os => ({
 		chooseDriveFolder,
 		chooseDriveFile,
 		dialog,
@@ -71,21 +91,6 @@ init(async (launch) => {
 			registerNotifications(os.stream);
 		}
 	}
-
-	// Routing
-	app.$router.addRoutes([
-		{ path: '/', name: 'index', component: MkIndex },
-		{ path: '/i/customize-home', component: MkHomeCustomize },
-		{ path: '/i/messaging/:username', component: MkMessagingRoom },
-		{ path: '/i/drive', component: MkDrive },
-		{ path: '/i/drive/folder/:folder', component: MkDrive },
-		{ path: '/selectdrive', component: MkSelectDrive },
-		{ path: '/search', component: MkSearch },
-		{ path: '/othello', component: MkOthello },
-		{ path: '/othello/:game', component: MkOthello },
-		{ path: '/@:user', component: MkUser },
-		{ path: '/@:user/:post', component: MkPost }
-	]);
 }, true);
 
 function registerNotifications(stream: HomeStreamManager) {
diff --git a/src/web/app/dev/script.ts b/src/web/app/dev/script.ts
index 2f4a16fab1..c043813b40 100644
--- a/src/web/app/dev/script.ts
+++ b/src/web/app/dev/script.ts
@@ -3,6 +3,7 @@
  */
 
 import Vue from 'vue';
+import VueRouter from 'vue-router';
 import BootstrapVue from 'bootstrap-vue';
 import 'bootstrap/dist/css/bootstrap.css';
 import 'bootstrap-vue/dist/bootstrap-vue.css';
@@ -26,14 +27,18 @@ Vue.component('mk-ui', ui);
  * init
  */
 init(launch => {
-	// Launch the app
-	const [app] = launch();
+	// Init router
+	const router = new VueRouter({
+		mode: 'history',
+		base: '/dev/',
+		routes: [
+			{ path: '/', component: Index },
+			{ path: '/apps', component: Apps },
+			{ path: '/app/new', component: AppNew },
+			{ path: '/app/:id', component: App },
+		]
+	});
 
-	// Routing
-	app.$router.addRoutes([
-		{ path: '/', component: Index },
-		{ path: '/apps', component: Apps },
-		{ path: '/app/new', component: AppNew },
-		{ path: '/app/:id', component: App },
-	]);
+	// Launch the app
+	launch(router);
 });
diff --git a/src/web/app/init.ts b/src/web/app/init.ts
index 6cc7ae6ce6..521dade866 100644
--- a/src/web/app/init.ts
+++ b/src/web/app/init.ts
@@ -91,14 +91,14 @@ if (localStorage.getItem('should-refresh') == 'true') {
 }
 
 // MiOSを初期化してコールバックする
-export default (callback: (launch: (api?: (os: MiOS) => API) => [Vue, MiOS]) => void, sw = false) => {
+export default (callback: (launch: (router: VueRouter, api?: (os: MiOS) => API) => [Vue, MiOS]) => void, sw = false) => {
 	const os = new MiOS(sw);
 
 	os.init(() => {
 		// アプリ基底要素マウント
 		document.body.innerHTML = '<div id="app"></div>';
 
-		const launch = (api?: (os: MiOS) => API) => {
+		const launch = (router: VueRouter, api?: (os: MiOS) => API) => {
 			os.apis = api ? api(os) : null;
 
 			Vue.mixin({
@@ -112,9 +112,7 @@ export default (callback: (launch: (api?: (os: MiOS) => API) => [Vue, MiOS]) =>
 			});
 
 			const app = new Vue({
-				router: new VueRouter({
-					mode: 'history'
-				}),
+				router,
 				created() {
 					this.$watch('os.i', i => {
 						// キャッシュ更新
diff --git a/src/web/app/mobile/script.ts b/src/web/app/mobile/script.ts
index 2fcb085aca..062a6d83d4 100644
--- a/src/web/app/mobile/script.ts
+++ b/src/web/app/mobile/script.ts
@@ -2,6 +2,8 @@
  * Mobile Client
  */
 
+import VueRouter from 'vue-router';
+
 // Style
 import './style.styl';
 import '../../element.scss';
@@ -45,8 +47,33 @@ init((launch) => {
 	// http://qiita.com/junya/items/3ff380878f26ca447f85
 	document.body.setAttribute('ontouchstart', '');
 
+	// Init router
+	const router = new VueRouter({
+		mode: 'history',
+		routes: [
+			{ path: '/', name: 'index', component: MkIndex },
+			{ path: '/signup', name: 'signup', component: MkSignup },
+			{ path: '/i/settings', component: MkSettings },
+			{ path: '/i/settings/profile', component: MkProfileSetting },
+			{ path: '/i/notifications', component: MkNotifications },
+			{ path: '/i/messaging', component: MkMessaging },
+			{ path: '/i/messaging/:username', component: MkMessagingRoom },
+			{ path: '/i/drive', component: MkDrive },
+			{ path: '/i/drive/folder/:folder', component: MkDrive },
+			{ path: '/i/drive/file/:file', component: MkDrive },
+			{ path: '/selectdrive', component: MkSelectDrive },
+			{ path: '/search', component: MkSearch },
+			{ path: '/othello', component: MkOthello },
+			{ path: '/othello/:game', component: MkOthello },
+			{ path: '/@:user', component: MkUser },
+			{ path: '/@:user/followers', component: MkFollowers },
+			{ path: '/@:user/following', component: MkFollowing },
+			{ path: '/@:user/:post', component: MkPost }
+		]
+	});
+
 	// Launch the app
-	const [app] = launch(os => ({
+	launch(router, os => ({
 		chooseDriveFolder,
 		chooseDriveFile,
 		dialog,
@@ -54,26 +81,4 @@ init((launch) => {
 		post: post(os),
 		notify
 	}));
-
-	// Routing
-	app.$router.addRoutes([
-		{ path: '/', name: 'index', component: MkIndex },
-		{ path: '/signup', name: 'signup', component: MkSignup },
-		{ path: '/i/settings', component: MkSettings },
-		{ path: '/i/settings/profile', component: MkProfileSetting },
-		{ path: '/i/notifications', component: MkNotifications },
-		{ path: '/i/messaging', component: MkMessaging },
-		{ path: '/i/messaging/:username', component: MkMessagingRoom },
-		{ path: '/i/drive', component: MkDrive },
-		{ path: '/i/drive/folder/:folder', component: MkDrive },
-		{ path: '/i/drive/file/:file', component: MkDrive },
-		{ path: '/selectdrive', component: MkSelectDrive },
-		{ path: '/search', component: MkSearch },
-		{ path: '/othello', component: MkOthello },
-		{ path: '/othello/:game', component: MkOthello },
-		{ path: '/@:user', component: MkUser },
-		{ path: '/@:user/followers', component: MkFollowers },
-		{ path: '/@:user/following', component: MkFollowing },
-		{ path: '/@:user/:post', component: MkPost }
-	]);
 }, true);
diff --git a/src/web/server.ts b/src/web/server.ts
index 062d1f197a..b117f6ae81 100644
--- a/src/web/server.ts
+++ b/src/web/server.ts
@@ -10,9 +10,6 @@ import * as express from 'express';
 import * as bodyParser from 'body-parser';
 import * as favicon from 'serve-favicon';
 import * as compression from 'compression';
-import vhost = require('vhost');
-
-import config from '../conf';
 
 /**
  * Init app
@@ -20,7 +17,7 @@ import config from '../conf';
 const app = express();
 app.disable('x-powered-by');
 
-app.use(vhost(`docs.${config.host}`, require('./docs/server')));
+app.use('/docs', require('./docs/server'));
 
 app.use(bodyParser.urlencoded({ extended: true }));
 app.use(bodyParser.json({