path-to-regexp#MatchFunction TypeScript Examples

The following examples show how to use path-to-regexp#MatchFunction. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: mock.ts    From mockiavelli with MIT License 5 votes vote down vote up
private matcher: {
        method: string;
        hostname: string | undefined;
        path: string;
        query: QueryObject;
        pathMatch: MatchFunction<PathParameters>;
        body: any;
    };
Example #2
Source File: router.ts    From farrow with MIT License 4 votes vote down vote up
createRouterPipeline = (): RouterPipeline => {
  const pipeline = createAsyncPipeline<RequestInfo, Response>()

  const capture: RouterPipeline['capture'] = (type, f) => {
    pipeline.use(matchBodyType(type, f))
  }

  const route: RouterPipeline['route'] = (name) => {
    const routePipeline = createRoute(name)
    pipeline.use(routePipeline)
    return routePipeline
  }

  const serve: RouterPipeline['serve'] = (name, dirname) => {
    dirname = path.normalize(dirname)

    const getIndexHtmlPath = (filename: string): string => {
      if (filename.endsWith('/')) {
        return `${filename}index.html`
      }
      return `${filename}/index.html`
    }

    route(name).use((request, next) => {
      // prevent directory traversal attack
      const filename = path.normalize(request.pathname)
      const fullpath = path.join(dirname, filename)
      if (fullpath.indexOf(dirname) !== 0) {
        return next(request)
      }

      return getStats(fullpath).then((stats) => {
        /**
         * handle file
         */
        if (stats?.isFile()) {
          return Response.file(fullpath)
        }

        /**
         * handle {dirname}/index.html
         */
        if (stats?.isDirectory()) {
          const indexHtmlPath = getIndexHtmlPath(fullpath)
          return getStats(indexHtmlPath).then((indexHtmlStats) => {
            if (indexHtmlStats?.isFile()) {
              return Response.file(getIndexHtmlPath(fullpath))
            }
            return next(request)
          })
        }

        return next(request)
      })
    })
  }

  const createMatchedPipeline = <T>({
    matchedPipeline,
    method,
    options,
    validator,
    matcher,
  }: {
    matchedPipeline: Pipeline<T, MaybeAsyncResponse>
    method: RouterSharedSchema['method']
    options?: MatchOptions
    validator: Validator<T>
    matcher: MatchFunction<object>
  }) => {
    const config = {
      block: false,
      ...options,
    }

    const methods = getMethods(method)

    pipeline.use((input, next) => {
      const container = useContainer()

      if (input.method && !methods.includes(input.method.toLowerCase())) {
        return next()
      }

      const matches = matcher(input.pathname)

      if (!matches) {
        return next()
      }

      const { params } = matches

      const result = validator({
        ...input,
        params,
      })

      if (result.isErr) {
        if (config.onSchemaError) {
          const response = config.onSchemaError(result.value)
          if (response) return response
        }

        let { message } = result.value

        if (result.value.path) {
          message = `path: ${JSON.stringify(result.value.path)}\n${message}`
        }

        throw new HttpError(message, 400)
      }

      return matchedPipeline.run(result.value, {
        container,
        onLast: () => {
          if (config.block) {
            throw new Error(`Unhandled request: ${input.pathname}`)
          } else {
            return next()
          }
        },
      })
    })

    return matchedPipeline
  }

  const match: RouterPipeline['match'] = (schema: any, options: MatchOptions) => {
    if (isRouterRequestSchema(schema)) {
      const matchedPipeline = createPipeline<any, MaybeAsyncResponse>()
      const { validator, matcher } = createRequestSchemaValidatorAndMatcher(schema)
      return createMatchedPipeline({
        matchedPipeline,
        validator,
        matcher,
        method: schema.method,
        options,
      })
    }

    if (isRouterUrlSchema(schema)) {
      const matchedPipeline = createPipeline<any, MaybeAsyncResponse>()
      const { validator, matcher } = createUrlSchemaValidatorAndMatcher(schema)
      return createMatchedPipeline({
        matchedPipeline,
        validator,
        matcher,
        method: schema.method,
        options,
      })
    }

    throw new Error(`Unsupported schema: {${Object.keys(schema)}}`)
  }

  const createRoutingMethod = (method: string) => {
    return (<U extends string, T extends Omit<RouterSharedSchema, 'method'>>(
      path: U,
      schema?: T,
      options?: MatchOptions,
    ) => {
      return match(
        {
          ...schema,
          method,
          url: path,
        },
        options,
      )
    }) as unknown as RoutingMethod
  }

  const methods: RoutingMethods = {
    get: createRoutingMethod('GET'),
    post: createRoutingMethod('POST'),
    put: createRoutingMethod('PUT'),
    head: createRoutingMethod('HEAD'),
    delete: createRoutingMethod('DELETE'),
    patch: createRoutingMethod('PATCH'),
    options: createRoutingMethod('OPTIONS'),
  }

  return {
    ...pipeline,
    ...methods,
    capture,
    route,
    serve,
    match,
  }
}