///|
pub struct RouteRule {
name : String
provider : String
event_type : String
path : String
http_method : HttpMethod
handler : String
enabled : Bool
} derive(Eq, Debug)
///|
pub fn RouteRule::new(
name : String,
provider : String,
event_type : String,
path : String,
http_method : HttpMethod,
handler : String,
enabled? : Bool = true,
) -> RouteRule {
{ name, provider, event_type, path, http_method, handler, enabled }
}
///|
pub fn RouteRule::matches(
self : RouteRule,
request : WebhookRequest,
profile : ProviderProfile,
) -> Bool {
self.enabled &&
self.provider == profile.name &&
self.event_type == provider_event_type(request, profile) &&
self.path == request.path &&
self.http_method == request.http_method
}
///|
pub struct RouteDecision {
matched : Bool
rule_name : String
handler : String
reason : String
} derive(Eq, Debug)
///|
pub fn RouteDecision::matched(rule : RouteRule) -> RouteDecision {
{
matched: true,
rule_name: rule.name,
handler: rule.handler,
reason: "matched",
}
}
///|
pub fn RouteDecision::miss(reason : String) -> RouteDecision {
{ matched: false, rule_name: "", handler: "", reason }
}
///|
pub struct EventRouter {
rules : Array[RouteRule]
} derive(Eq, Debug)
///|
pub fn EventRouter::empty() -> EventRouter {
{ rules: [] }
}
///|
pub fn EventRouter::add(self : EventRouter, rule : RouteRule) -> EventRouter {
let old = self.rules
let rules = Array::makei(old.length() + 1, i => {
if i < old.length() {
old[i]
} else {
rule
}
})
{ rules, }
}
///|
pub fn EventRouter::route(
self : EventRouter,
request : WebhookRequest,
profile : ProviderProfile,
) -> RouteDecision {
for i in 0.. Int {
let mut count = 0
for i in 0.. Array[String] {
let mut count = 0
for i in 0.. {
while offset < self.rules.length() {
let handler = self.rules[offset].handler
let mut seen = false
for j in 0.. EventRouter {
EventRouter::empty()
.add(
RouteRule::new(
"github_issues",
"github",
"issues",
"/webhook/github",
Post,
"handle_github_issues",
),
)
.add(
RouteRule::new(
"github_push",
"github",
"push",
"/webhook/github",
Post,
"handle_github_push",
),
)
.add(
RouteRule::new(
"feishu_message",
"feishu",
"im.message.receive_v1",
"/webhook/feishu",
Post,
"handle_feishu_message",
),
)
.add(
RouteRule::new(
"stripe_invoice",
"stripe",
"invoice.paid",
"/webhook/stripe",
Post,
"handle_stripe_invoice",
),
)
}
///|
pub struct DispatchOutcome {
verification : VerificationResult
route : RouteDecision
} derive(Eq, Debug)
///|
pub fn dispatch_request(
request : WebhookRequest,
policy : VerificationPolicy,
router : EventRouter,
) -> DispatchOutcome {
let verification = verify_request(request, policy)
let route = if verification.is_ok() {
router.route(request, policy.provider)
} else {
RouteDecision::miss("verification failed")
}
{ verification, route }
}
///|
pub fn dispatch_text(outcome : DispatchOutcome) -> String {
let builder = StringBuilder::new()
builder.write_string(outcome.verification.to_text())
builder.write_string("\nroute=")
if outcome.route.matched {
builder.write_string(outcome.route.rule_name)
builder.write_string(" handler=")
builder.write_string(outcome.route.handler)
} else {
builder.write_string("miss reason=")
builder.write_string(outcome.route.reason)
}
builder.to_string()
}
///|
pub fn route_demo_events() -> String {
let outcome = dispatch_request(
example_github_request(),
VerificationPolicy::default(),
default_router(),
)
dispatch_text(outcome)
}