1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
// Copyright Materialize, Inc. and contributors. All rights reserved.
//
// Use of this software is governed by the Business Source License
// included in the LICENSE file.
//
// As of the Change Date specified in that file, in accordance with
// the Business Source License, use of this software will be governed
// by the Apache License, Version 2.0.

use anyhow::bail;

use crate::action::{ControlFlow, State};
use crate::parser::BuiltinCommand;

pub async fn run_append(
    mut cmd: BuiltinCommand,
    state: &State,
) -> Result<ControlFlow, anyhow::Error> {
    let database = cmd
        .args
        .opt_string("database")
        .unwrap_or_else(|| "materialize".to_string());
    let schema = cmd
        .args
        .opt_string("schema")
        .unwrap_or_else(|| "public".to_string());
    let name = cmd.args.string("name")?;

    let status_code = cmd.args.opt_parse::<u16>("status")?;
    // Interpret the remaining arguments as headers.
    let headers: Vec<(String, String)> = cmd.args.into_iter().collect();

    let body = cmd.input.join("\n");

    println!("$ webhook-append {database}.{schema}.{name}\n{body}\n{headers:?}");

    let client = if state.materialize.use_https {
        reqwest::Client::builder()
            .danger_accept_invalid_certs(true)
            .build()
            .unwrap()
    } else {
        reqwest::Client::new()
    };
    let url = format!(
        "{}://{}/api/webhook/{database}/{schema}/{name}",
        if state.materialize.use_https {
            "https"
        } else {
            "http"
        },
        state.materialize.http_addr
    );
    let mut builder = client.post(url).body(body);

    // Append all of our headers.
    for (name, value) in headers {
        builder = builder.header(name, value);
    }

    let response = builder.send().await?;
    let status = response.status();

    println!("{}\n{}", status, response.text().await?);

    let expected_status = status_code.unwrap_or(200);
    if status.as_u16() == expected_status {
        Ok(ControlFlow::Continue)
    } else {
        bail!("webhook append returned unexpected status: {}", status);
    }
}