-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #130 from sima-land/38-proxy-feature
Шаг 79 #38 Возможность проксирования http-запросов
- Loading branch information
Showing
11 changed files
with
266 additions
and
110 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,47 @@ | ||
/* eslint-disable require-jsdoc, jsdoc/require-jsdoc */ | ||
import { Resolve } from '../../../di'; | ||
import { KnownToken } from '../../../tokens'; | ||
import { Handler } from '../../../http'; | ||
import { route, router } from '@krutoo/fetch-tools'; | ||
import { Handler, proxy } from '../../../http'; | ||
import { router, applyMiddleware } from '@krutoo/fetch-tools'; | ||
import { applyServerMiddleware } from '../../server/utils/apply-server-middleware'; | ||
|
||
export function provideServe(resolve: Resolve): Handler { | ||
const middleware = resolve(KnownToken.Http.Serve.middleware); | ||
const routes = resolve(KnownToken.Http.Serve.routes); | ||
const config = resolve(KnownToken.Config.base); | ||
const pageRoutes = resolve(KnownToken.Http.Serve.pageRoutes); | ||
const serviceRoutes = resolve(KnownToken.Http.Serve.serviceRoutes); | ||
const middleware = resolve(KnownToken.Http.Serve.middleware); | ||
const proxyConfig = resolve(KnownToken.Http.Serve.Proxy.config); | ||
|
||
const enhance = | ||
config.env === 'development' && proxyConfig | ||
? applyMiddleware( | ||
...(Array.isArray(proxyConfig) ? proxyConfig.map(proxy) : [proxy(proxyConfig)]), | ||
) | ||
: identity; | ||
|
||
const enhance = applyServerMiddleware(...middleware); | ||
const builder = router.builder(); | ||
|
||
return router( | ||
// маршруты с промежуточными слоями | ||
...routes.map(([pattern, handler]) => { | ||
const enhancedHandler = enhance(handler); | ||
// маршруты с промежуточными слоями | ||
for (const [pattern, handler] of pageRoutes) { | ||
const path = typeof pattern === 'string' ? pattern : pattern.path; | ||
const method = typeof pattern === 'string' ? 'get' : pattern.method; | ||
const pageHandler = applyServerMiddleware(...middleware)(handler); | ||
|
||
return route.get(pattern, request => enhancedHandler(request, { events: new EventTarget() })); | ||
}), | ||
builder[method](path, request => pageHandler(request, { events: new EventTarget() })); | ||
} | ||
|
||
// @todo вместо routes обрабатывать pageRoutes с помощью route.get() из новой версии fetch-tools (для явности) | ||
// @todo также добавить apiRoutes и обрабатывать их с помощью с помощью route()? | ||
// служебные маршруты (к ним не применяются промежуточные слои) | ||
for (const [pattern, handler] of serviceRoutes) { | ||
const path = typeof pattern === 'string' ? pattern : pattern.path; | ||
const method = typeof pattern === 'string' ? 'get' : pattern.method; | ||
|
||
builder[method](path, request => handler(request, { events: new EventTarget() })); | ||
} | ||
|
||
// @todo также добавить apiRoutes? | ||
return enhance(builder.build()); | ||
} | ||
|
||
// служебные маршруты (без промежуточных слоев) | ||
...serviceRoutes.map(([pattern, handler]) => | ||
route(pattern, request => handler(request, { events: new EventTarget() })), | ||
), | ||
); | ||
function identity<T>(value: T): T { | ||
return value; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,62 @@ | ||
import express from 'express'; | ||
import type { Resolve } from '../../../di'; | ||
import { KnownToken } from '../../../tokens'; | ||
import express from 'express'; | ||
import { createProxyMiddleware } from 'http-proxy-middleware'; | ||
|
||
/** | ||
* Провайдер основного express-приложения. | ||
* @param resolve Функция для получения зависимости по токену. | ||
* @return Основное express-приложение. | ||
*/ | ||
export function provideMainExpressApp(resolve: Resolve): express.Application { | ||
const config = resolve(KnownToken.Config.base); | ||
const pageRoutes = resolve(KnownToken.Express.pageRoutes); | ||
const serviceRoutes = resolve(KnownToken.Express.serviceRoutes); | ||
const middleware = resolve(KnownToken.Express.middleware); | ||
const endMiddleware = resolve(KnownToken.Express.endMiddleware); | ||
const proxyConfig = resolve(KnownToken.Http.Serve.Proxy.config); | ||
|
||
const app = express(); | ||
|
||
if (config.env === 'development' && proxyConfig) { | ||
const proxyConfigs = Array.isArray(proxyConfig) ? proxyConfig : [proxyConfig]; | ||
|
||
for (const { target, filter } of proxyConfigs) { | ||
// ВАЖНО: так как не можем предоставить web-интерфейс Request бросаем ошибку | ||
if (typeof filter === 'function') { | ||
throw new Error('Currently function is not supported for proxy "filter"'); | ||
} | ||
|
||
const proxyPaths = Array.isArray(filter) ? filter : [filter]; | ||
|
||
app.use( | ||
createProxyMiddleware({ | ||
target, | ||
changeOrigin: true, | ||
pathFilter: inputPath => proxyPaths.some(proxyPath => inputPath.startsWith(proxyPath)), | ||
}), | ||
); | ||
} | ||
} | ||
|
||
// маршруты страниц | ||
for (const [routePath, routeHandler] of pageRoutes) { | ||
app.use(routePath, middleware); | ||
app.get(routePath, routeHandler); | ||
app.use(routePath, endMiddleware); | ||
const path = typeof routePath === 'string' ? routePath : routePath.path; | ||
const method = typeof routePath === 'string' ? 'get' : routePath.method; | ||
|
||
app.use(path, middleware); | ||
app[method](path, routeHandler); | ||
app.use(path, endMiddleware); | ||
} | ||
|
||
// служебные маршруты (к ним не применяются промежуточные слои) | ||
for (const [routePath, routeHandler] of serviceRoutes) { | ||
app.get(routePath, routeHandler); | ||
const path = typeof routePath === 'string' ? routePath : routePath.path; | ||
const method = typeof routePath === 'string' ? 'get' : routePath.method; | ||
|
||
app[method](path, routeHandler); | ||
} | ||
|
||
// @todo также добавить apiRoutes? | ||
return app; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,13 @@ | ||
import type { Request, Response, NextFunction } from 'express'; | ||
import type express from 'express'; | ||
import type { RouteInfo } from '../server/types'; | ||
|
||
/** | ||
* Контекст обработчика express. | ||
*/ | ||
export interface ExpressHandlerContext { | ||
readonly req: Request; | ||
readonly res: Response; | ||
readonly next: NextFunction; | ||
readonly req: express.Request; | ||
readonly res: express.Response; | ||
readonly next: express.NextFunction; | ||
} | ||
|
||
export type ExpressRouteList = Array<[string | RouteInfo, express.Handler]>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters