Skip to content

Commit 34eaab0

Browse files
committed
feat: add gitlab support
1 parent 195aa57 commit 34eaab0

File tree

3 files changed

+60
-3
lines changed

3 files changed

+60
-3
lines changed

crates/origin/src/gitlab.rs

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use super::{Error, WebhookOrigin};
2+
use axum::http::HeaderMap;
3+
4+
pub struct GitLabValidator;
5+
6+
impl WebhookOrigin for GitLabValidator {
7+
fn validate_headers(&self, headers: &HeaderMap) -> Result<(), Error> {
8+
const REQUIRED_HEADERS: [&str; 3] =
9+
["X-Gitlab-Event", "X-Gitlab-Webhook-UUID", "X-Gitlab-UUID"];
10+
11+
for header in REQUIRED_HEADERS {
12+
if !headers.contains_key(header) {
13+
return Err(Error::MissingHeader(header));
14+
}
15+
}
16+
17+
let user_agent = headers
18+
.get("User-Agent")
19+
.and_then(|v| v.to_str().ok())
20+
.ok_or(Error::MissingHeader("User-Agent"))?;
21+
22+
if !user_agent.starts_with("Gitlab/") {
23+
return Err(Error::InvalidUserAgent);
24+
}
25+
26+
Ok(())
27+
}
28+
29+
fn extract_event_type(&self, headers: &HeaderMap) -> Result<String, Error> {
30+
headers
31+
.get("X-Gitlab-Event")
32+
.and_then(|v| v.to_str().ok())
33+
.map(|s| s.to_string())
34+
.ok_or(Error::MissingHeader("X-Gitlab-Event"))
35+
}
36+
37+
fn validate_signature(
38+
&self,
39+
headers: &HeaderMap,
40+
_secret: &str,
41+
_body: &[u8],
42+
) -> Result<(), Error> {
43+
_ = headers
44+
.get("X-Gitlab-Instance")
45+
.and_then(|v| v.to_str().ok())
46+
.ok_or(Error::MissingHeader("X-Gitlab-Event-UUID"))?;
47+
48+
Ok(())
49+
}
50+
}

crates/origin/src/lib.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
mod errors;
2-
mod github;
3-
41
use axum::http::HeaderMap;
52
use serde::Deserialize;
63

74
pub use crate::errors::Error;
85

6+
mod errors;
7+
mod github;
8+
mod gitlab;
9+
910
#[derive(Clone, Copy, Debug, Default, Deserialize)]
1011
#[serde(rename_all = "lowercase")]
1112
pub enum Origin {
1213
#[default]
1314
GitHub,
15+
GitLab,
1416
}
1517

1618
pub trait WebhookOrigin {
@@ -28,12 +30,14 @@ impl WebhookOrigin for Origin {
2830
fn validate_headers(&self, headers: &HeaderMap) -> Result<(), Error> {
2931
match self {
3032
Origin::GitHub => github::GitHubValidator.validate_headers(headers),
33+
Origin::GitLab => gitlab::GitLabValidator.validate_headers(headers),
3134
}
3235
}
3336

3437
fn extract_event_type(&self, headers: &HeaderMap) -> Result<String, Error> {
3538
match self {
3639
Origin::GitHub => github::GitHubValidator.extract_event_type(headers),
40+
Origin::GitLab => gitlab::GitLabValidator.extract_event_type(headers),
3741
}
3842
}
3943

@@ -45,6 +49,7 @@ impl WebhookOrigin for Origin {
4549
) -> Result<(), Error> {
4650
match self {
4751
Origin::GitHub => github::GitHubValidator.validate_signature(headers, secret, body),
52+
Origin::GitLab => gitlab::GitLabValidator.validate_signature(headers, secret, body),
4853
}
4954
}
5055
}

src/validator.rs

+2
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ pub async fn validate_signature_middleware(
5656
fn determine_origin(headers: &HeaderMap) -> Result<Origin, OriginError> {
5757
if headers.contains_key("X-GitHub-Event") {
5858
Ok(Origin::GitHub)
59+
} else if headers.contains_key("X-Gitlab-Event") {
60+
Ok(Origin::GitLab)
5961
} else {
6062
Err(OriginError::MissingHeader("X-*-Event"))
6163
}

0 commit comments

Comments
 (0)