本地JavaScript路线 /路由器建议
#javascript #node #deno

新的标准类,例如urlpattern,响应,请求和URL,使我思考了本机路由/路由器类的外观。我已经尝试了各种服务器框架,例如Express,Oak和Fresh,并且一直在考虑从Wintercg或Mozilla的角度来看服务器的外观。这是仅在方法和URL上匹配的简单路线和路由类。

type Handler = (req: Request) => Promise<Response> | Response

export class Route {
  urlPattern: URLPattern
  constructor (
    public method: string,
    public pathname: string,
    public handler: Handler
  ) {
    this.urlPattern = new URLPattern({ pathname })
  }
  static get (pathname: string, handler: Handler) {
    return new Route("GET", pathname, handler)
  }
}

export class Routes {
  routes: Route[]
  constructor (...routes: Route[]) {
    this.routes = routes
  }
  async match (req: Request): Promise<Response> {
    const matches = this.routes.filter(route => {
      return route.urlPattern.test(req.url) && route.method === req.method
    })
    if (matches.length > 1) { 
      return new Response('internal error, more then one route with the same pathname')
    } else if (matches.length === 0) {
      return new Response('internal error, not found')
    } else {
      const response = await matches[0].handler(req)

      return response
    }
  }
}

这将使您可以做类似的事情:

import { serve } from "https://deno.land/std@0.173.0/http/server.ts";

const routes = new Routes(
  Route.get('/elephant', () => Response.json('elephant')),
  Route.get('/monkey', () => Response.json('monkey')),
  Route.get('/racoon', () => Response.json('racoon')),
  Route.get('/bunny', () => Response.json('bunny')),
)

// To listen on port 4242.
serve((request) => {
  return routes.match(request)
}, { port: 4242 });

这有一个问题:如果您想在请求的其他部分匹配该怎么办?这可能会很快变得复杂。除了标准URL和方法外,还有标题,查询,主体,应该在提取的,解析的身体上匹配匹配项吗?如果是这样,应该在请求对象中验证身体吗?要获得身体,这是一个承诺的背后。要匹配身体,您需要了解车身的类型(例如形式,XML,JSON),然后使用像ZOD这样的工具来验证它。它没有在这里概述,但是我创建了WrapedRequest的想法,该想法会在WrapedRequest实例中缓存身体,以便将诺言解决一次并传递给每个Router以进行匹配。

一个更复杂的Route类可以将所有匹配条件列为一系列选项和要求。

new RouteMatcher(
  method.get,
  oneOf(urlPattern('/elephant'), urlPattern('/elephant/:name')),
  oneOf([queryParam('name'), urlPattern('/elephant/:name'), header('x-name')]),
)

我喜欢一个可以符合各种标准的简单路线/路由器的概念,我想知道其他人是否也在考虑这个想法。它无疑简化了仅与方法和URL路径匹配的事物。

我一直在思考可以与各种标准匹配的本地路线/路由器类的潜力。我一直在尝试不同的服务器框架,并从各个角度考虑服务器的设计。我建议可以在方法上匹配的简单路线和路由类是一个不错的起点,但是在其他条件下也有扩展的余地。我很想知道其他人是否分享了这一观点,并想对此主题进行讨论。