Skip to content
Snippets Groups Projects
Commit bb158458 authored by Bojan Marjanovic's avatar Bojan Marjanovic :five:
Browse files

Merge branch 'rule-action' into 'main'

Introduce abstract class Action to handle classify or proxy

See merge request !218
parents 1a14377c f63adbce
No related branches found
No related tags found
1 merge request!218Introduce abstract class Action to handle classify or proxy
Pipeline #1440624182 passed
import { ROUTER_RULE_ACTION_HEADER, ROUTER_RULE_TYPE_HEADER } from './rules/constants';
import { Rule, ClassifyRule, ProxyRule } from './rules/types.d';
import { classifyFetch } from './topology_service/classify';
import { proxifyFetch } from './utils';
export abstract class Action<T extends Rule> {
constructor(protected rule: T) {}
async apply(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
this.setHeaders(request);
return this.fetch(request, env, ctx);
}
protected setHeaders(request: Request): void {
request.headers.set(ROUTER_RULE_ACTION_HEADER, this.rule.action);
}
protected abstract fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response>;
}
export class ClassifyAction extends Action<ClassifyRule> {
override setHeaders(request: Request): void {
super.setHeaders(request);
request.headers.set(ROUTER_RULE_TYPE_HEADER, this.rule.classify.type);
}
override async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
if (!env.GITLAB_TOPOLOGY_SERVICE_URL) {
throw new Error('Topology Service is not configured to perform classify action');
}
const { type, value } = this.rule.classify;
return classifyFetch(env, ctx, type, value).then((response) => {
switch (response.action) {
case 'PROXY':
return proxifyFetch(request, response.proxy.address);
default:
throw new Error(`Topology Service action is not supported: ${response.action}`);
}
});
}
}
export class ProxyAction extends Action<ProxyRule> {
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- ctx is not used but it's part of the method signature
override async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const proxyAddress = this.rule.proxy?.address || env.GITLAB_PROXY_HOST;
if (!proxyAddress) {
throw new Error('Proxy address is not specified in rule or environment.');
}
return proxifyFetch(request, proxyAddress);
}
}
import { ActionType, Rule, Rules } from './rules/types.d';
import { ClassifyAction, ProxyAction } from './action';
import { allRules } from './rules/index';
import { ClassifyRequest } from './topology_service/types';
import { executeClassifyAction } from './topology_service/classify';
import { proxifyFetch } from './utils';
import { setRouterHeaders } from './header';
class RouterEngine {
private readonly rules: Rules;
......@@ -26,24 +23,11 @@ class RouterEngine {
private async applyRule(request: Request, ctx: ExecutionContext, rule: Rule): Promise<Response> {
switch (rule.action) {
case ActionType.Classify: {
const classifyRequest: ClassifyRequest = {
type: rule.classify.type,
value: rule.classify.value,
};
setRouterHeaders(request, rule);
return executeClassifyAction(classifyRequest, request, this.env, ctx);
return new ClassifyAction(rule).apply(request, this.env, ctx);
}
case ActionType.Proxy: {
const proxy_address = rule.proxy?.address || this.env.GITLAB_PROXY_HOST;
if (!proxy_address) {
throw new Error('Proxy address is not specified in rule or environment.');
}
setRouterHeaders(request, rule);
return proxifyFetch(request, proxy_address);
return new ProxyAction(rule).apply(request, this.env, ctx);
}
default:
......
import { ActionType, Rule } from './rules/types.d';
export const ROUTER_RULE_ACTION_HEADER = 'X-GitLab-HTTP-Router-Rule-Action';
export const ROUTER_RULE_TYPE_HEADER = 'X-GitLab-HTTP-Router-Rule-Type';
export function setRouterHeaders(request: Request, rule: Rule): void {
request.headers.set(ROUTER_RULE_ACTION_HEADER, rule.action);
if (rule.action === ActionType.Classify) {
request.headers.set(ROUTER_RULE_TYPE_HEADER, rule.classify.type);
}
}
[
{
"id": "0_proxy",
"action": "proxy"
}
{
"id": "0_proxy",
"action": "proxy"
}
]
......@@ -12,7 +12,7 @@ interface BaseRule {
id: string;
}
interface ClassifyAction extends BaseRule {
interface ClassifyRule extends BaseRule {
action: ActionType.Classify;
classify: {
type: ClassifyType;
......@@ -20,14 +20,14 @@ interface ClassifyAction extends BaseRule {
};
}
interface ProxyAction extends BaseRule {
interface ProxyRule extends BaseRule {
action: ActionType.Proxy;
proxy?: {
address: string;
};
}
export type Rule = ClassifyAction | ProxyAction;
export type Rule = ClassifyRule | ProxyRule;
// Define the Rules type as an array of Rule
export type Rules = Rule[];
import { GITLAB_TOPOLOGY_SERVICE_CLASSIFY_PATH } from './constants';
import { ClassifyRequest, ClassifyResponse } from './types';
import { proxifyFetch, secureCachedApiFetch } from '../utils';
import { ClassifyResponse } from './types';
import { secureCachedApiFetch } from '../utils';
export async function classifyFetch(env: Env, ctx: ExecutionContext, type: string, value?: string): Promise<ClassifyResponse> {
const topologyServiceUrl = new URL(`${env.GITLAB_TOPOLOGY_SERVICE_URL}${GITLAB_TOPOLOGY_SERVICE_CLASSIFY_PATH}`);
......@@ -23,23 +23,3 @@ export async function classifyFetch(env: Env, ctx: ExecutionContext, type: strin
return response.json() as Promise<ClassifyResponse>;
});
}
export async function executeClassifyAction(
classify: ClassifyRequest,
request: Request,
env: Env,
ctx: ExecutionContext,
): Promise<Response> {
if (!env.GITLAB_TOPOLOGY_SERVICE_URL) {
throw new Error('Topology Service is not configured to perform classify action');
}
return classifyFetch(env, ctx, classify.type, classify.value).then((response) => {
switch (response.action) {
case 'PROXY':
return proxifyFetch(request, response.proxy.address);
default:
throw new Error(`Topology Service action is not supported: ${response.action}`);
}
});
}
import { env, createExecutionContext, waitOnExecutionContext, fetchMock } from 'cloudflare:test';
import { beforeAll, beforeEach, afterEach, describe, it, expect, vi } from 'vitest';
import { ROUTER_RULE_ACTION_HEADER, ROUTER_RULE_TYPE_HEADER } from '../src/header';
import { GITLAB_TOPOLOGY_SERVICE_CLASSIFY_PATH } from '../src/topology_service/constants';
import { ROUTER_RULE_ACTION_HEADER, ROUTER_RULE_TYPE_HEADER } from '../src/rules/constants';
import { ActionType, ClassifyType } from '../src/rules/types.d';
import worker from '../src';
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment