From 47e5afe96387ea440082ed197a6e506c9782caa5 Mon Sep 17 00:00:00 2001
From: Kuingsmile <ma_shiqing@163.com>
Date: Sat, 30 Mar 2024 22:46:51 +0800
Subject: [PATCH] :hammer: Refactor(custom): refactor server

---
 src/main/server/index.ts         | 30 +++++++++++++++++++-----------
 src/main/server/router.ts        | 30 +++++++++++++++++++++++-------
 src/main/server/routerManager.ts | 15 ++++++++++++++-
 3 files changed, 56 insertions(+), 19 deletions(-)

diff --git a/src/main/server/index.ts b/src/main/server/index.ts
index 6de1839..be140a5 100644
--- a/src/main/server/index.ts
+++ b/src/main/server/index.ts
@@ -11,8 +11,6 @@ import multer from 'multer'
 import { app } from 'electron'
 import path from 'path'
 import fs from 'fs-extra'
-import { marked } from 'marked'
-import { markdownContent } from './apiDoc'
 
 const DEFAULT_PORT = 36677
 const DEFAULT_HOST = '0.0.0.0'
@@ -83,9 +81,9 @@ class Server {
   }
 
   private handlePostRequest = (request: http.IncomingMessage, response: http.ServerResponse) => {
-    const [url, query] = request.url!.split('?')
-    if (!routers.getHandler(url!)) {
-      logger.warn(`[PicList Server] don't support [${url}] url`)
+    const [url, query] = (request.url || '').split('?')
+    if (!routers.getHandler(url, 'POST')) {
+      logger.warn(`[PicList Server] don't support [${url}] endpoint`)
       handleResponse({
         response,
         statusCode: 404,
@@ -110,7 +108,7 @@ class Server {
           // @ts-ignore
           const list = request.files.map(file => file.path)
           logger.info('[PicList Server] get a formData request')
-          const handler = routers.getHandler(url)?.handler
+          const handler = routers.getHandler(url!, 'POST')?.handler
           if (handler) {
             handler({
               list,
@@ -139,7 +137,7 @@ class Server {
             })
           }
           logger.info('[PicList Server] get the request', body)
-          const handler = routers.getHandler(url!)?.handler
+          const handler = routers.getHandler(url!, 'POST')?.handler
           handler!({
             ...postObj,
             response,
@@ -151,10 +149,20 @@ class Server {
   }
 
   private handleGetRequest = (_request: http.IncomingMessage, response: http.ServerResponse) => {
-    response.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })
-    const htmlContent = marked(markdownContent)
-    response.write(htmlContent)
-    response.end()
+    const [url, query] = (_request.url || '').split('?')
+    if (!routers.getHandler(url, 'GET')) {
+      console.log(`[PicList Server] don't support [${url}] endpoint`)
+      response.statusCode = 404
+      response.end()
+    } else {
+      const handler = routers.getHandler(url, 'GET')?.handler
+      if (handler) {
+        handler({
+          response,
+          urlparams: query ? new URLSearchParams(query) : undefined
+        })
+      }
+    }
   }
 
   // port as string is a bug
diff --git a/src/main/server/router.ts b/src/main/server/router.ts
index 1f5dc3e..c128386 100644
--- a/src/main/server/router.ts
+++ b/src/main/server/router.ts
@@ -1,20 +1,36 @@
+type HttpMethod = 'GET' | 'POST'
+
 class Router {
-  private router = new Map<string, {handler: routeHandler, urlparams?: URLSearchParams}>()
+  private router = new Map<string, Map<HttpMethod, {handler: routeHandler, urlparams?: URLSearchParams}>>()
+
+  private addRoute (method: HttpMethod, url: string, callback: routeHandler, urlparams?: URLSearchParams): void {
+    if (!this.router.has(url)) {
+      this.router.set(url, new Map())
+    }
+    this.router.get(url)!.set(method, { handler: callback, urlparams })
+  }
 
   get (url: string, callback: routeHandler, urlparams?: URLSearchParams): void {
-    this.router.set(url, { handler: callback, urlparams })
+    this.addRoute('GET', url, callback, urlparams)
   }
 
   post (url: string, callback: routeHandler, urlparams?: URLSearchParams): void {
-    this.router.set(url, { handler: callback, urlparams })
+    this.addRoute('POST', url, callback, urlparams)
   }
 
-  getHandler (url: string) {
+  any (url: string, callback: routeHandler, urlparams?: URLSearchParams): void {
+    this.addRoute('GET', url, callback, urlparams)
+    this.addRoute('POST', url, callback, urlparams)
+  }
+
+  getHandler (url: string, method: HttpMethod) {
     if (this.router.has(url)) {
-      return this.router.get(url)
-    } else {
-      return null
+      const methods = this.router.get(url)!
+      if (methods.has(method)) {
+        return methods.get(method)
+      }
     }
+    return null
   }
 }
 
diff --git a/src/main/server/routerManager.ts b/src/main/server/routerManager.ts
index a843ae3..17d3fa4 100644
--- a/src/main/server/routerManager.ts
+++ b/src/main/server/routerManager.ts
@@ -12,6 +12,9 @@ import { changeCurrentUploader } from '../utils/handleUploaderConfig'
 import { app } from 'electron'
 import fs from 'fs-extra'
 import { AESHelper } from '../utils/aesHelper'
+import { marked } from 'marked'
+import { markdownContent } from './apiDoc'
+import http from 'http'
 
 const appPath = app.getPath('userData')
 const serverTempDir = path.join(appPath, 'serverTemp')
@@ -22,6 +25,16 @@ const LOG_PATH = path.join(STORE_PATH, 'piclist.log')
 const errorMessage = `upload error. see ${LOG_PATH} for more detail.`
 const deleteErrorMessage = `delete error. see ${LOG_PATH} for more detail.`
 
+async function responseForGet ({ response } : {response: http.ServerResponse}) {
+  response.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' })
+  const htmlContent = marked(markdownContent)
+  response.write(htmlContent)
+  response.end()
+}
+
+router.get('/', responseForGet)
+router.get('/upload', responseForGet)
+
 router.post('/upload', async ({
   response,
   list = [],
@@ -203,7 +216,7 @@ router.post('/delete', async ({
   }
 })
 
-router.post('/heartbeat', async ({
+router.any('/heartbeat', async ({
   response
 } : {
   response: IHttpResponse,