Arbitrary header fields in commands

Adopt the parser to be able to parse header fields.
This commit is contained in:
finga 2021-03-30 01:16:15 +02:00
parent 2c00441b34
commit 8099bf773f
2 changed files with 39 additions and 21 deletions

View file

@ -55,16 +55,26 @@ Configuration syntax is YAML and has to be done in following order:
Right now there is only the configuration parameter for hooks, here Right now there is only the configuration parameter for hooks, here
each hook has to be configured, It contains following fields: each hook has to be configured, It contains following fields:
- command: String for a command to be executed when all filters - command: A command to be executed if a filter matches
match. Pointers ([RFC 6901](https://tools.ietf.org/html/rfc6901)) to
JSON fields may be used to be replaced with data from the JSON data
with `{{ /field/pointed/to }}`. Further `{{ event }}` and `{{
signature }}` are valid variables as they contain the values from
the regarding header fields of the http request.
- signature: Name of the HTTP header field containing the signature. - signature: Name of the HTTP header field containing the signature.
- secrets: List of secrets. - secrets: List of secrets.
- filters: List of filters. - filters: List of filters.
### Command
To pass data to a command following two different methods can be used.
#### JSON Pointers
Use JSON pointers ([RFC 6901](https://tools.ietf.org/html/rfc6901))
point to values of a JSON field from the JSON data.
Example: `{{ /field/pointed/to }}`.
#### Header
Use values from header fields sent with the HTTP request.
Example: `{{ header X-Gitea-Event }}`.
### Filter
Each filter must have following fields: Each filter must have following fields:
- pointer: pointer to the JSON field according to [RFC - pointer: pointer to the JSON field according to [RFC
6901](https://tools.ietf.org/html/rfc6901) 6901](https://tools.ietf.org/html/rfc6901)

View file

@ -67,21 +67,29 @@ fn replace_parameter(input: &str, headers: &HeaderMap, data: &serde_json::Value)
let parse: IResult<&str, Vec<&str>> = many0(alt(( let parse: IResult<&str, Vec<&str>> = many0(alt((
map_res( map_res(
delimited(tag("{{"), take_until("}}"), tag("}}")), delimited(tag("{{"), take_until("}}"), tag("}}")),
|param: &str| match param.trim() { |param: &str| {
"event" => { let expr = param.trim().split(' ').collect::<Vec<&str>>();
if let Some(event) = headers.get_one("X-Gitea-Event") {
Ok(event) match expr.get(0) {
} else { Some(&"header") => {
bail!("Could not extract event parameter from header"); if let Some(field) = expr.get(1) {
match headers.get_one(field) {
Some(value) => Ok(value),
_ => bail!("Could not extract event parameter from header"),
}
} else {
bail!("Missing parameter for `header` expression");
}
} }
} Some(pointer) => match data.pointer(pointer) {
pointer => match data.pointer(pointer) { Some(value) => match value.as_str() {
Some(value) => match value.as_str() { Some(value) => Ok(value),
Some(value) => Ok(value), _ => bail!("Could not convert value `{}` to string", value),
_ => bail!("Could not convert value `{}` to string", value), },
_ => bail!("Could not convert field `{}` to string", param.trim()),
}, },
_ => bail!("Could not convert field `{}` to string", param.trim()), None => bail!("Missing expression in `{}`", input),
}, }
}, },
), ),
take_until("{{"), take_until("{{"),
@ -297,7 +305,7 @@ fn get_config() -> Result<File> {
return Ok(config); return Ok(config);
} }
bail!("No configuration files found."); bail!("No configuration file found.");
} }
fn main() -> Result<()> { fn main() -> Result<()> {
@ -471,7 +479,7 @@ mod tests {
assert_eq!( assert_eq!(
replace_parameter( replace_parameter(
" {{ event }} command", " {{ header X-Gitea-Event }} command",
&map, &map,
&json!({ "field1": { "foo": "bar" } }) &json!({ "field1": { "foo": "bar" } })
) )