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
use super::Turbine;
use crate::error_views::ServerErrorData;
use crate::{errors::*, i18n::TranslationsManager, plugins::PluginAction, stores::MutableStore};
use std::fs;
use std::sync::Arc;

impl<M: MutableStore, T: TranslationsManager> Turbine<M, T> {
    /// Exports the error page of the given exit code to the given path.
    pub async fn export_error_page(&self, code: u16, output: &str) -> Result<(), Arc<Error>> {
        self.plugins
            .functional_actions
            .export_error_page_actions
            .before_export_error_page
            .run((code, output.to_string()), self.plugins.get_plugin_data())
            .map_err(|err| Arc::new(err.into()))?;

        // Build that error page as the server does (assuming the app has been
        // built so that the HTML shell is ready)
        let err_page_str = self.build_error_page(
            ServerErrorData {
                status: code,
                // Hopefully, this error will appear in a context that makes sense (e.g. a 404).
                // Exporting a 500 page doesn't make a great deal of sense on most
                // static serving infrastructure (they'll have their own).
                msg: "app was exported, no further details available".to_string(),
            },
            // Localizing exported error pages is not currently supported. However, if a locale is
            // available in the browser, it will be used to override whatever was
            // rendered from this.
            None,
        );

        // Write that to the given output location (this will be relative to wherever
        // the user executed from)
        match fs::write(output, err_page_str) {
            Ok(_) => (),
            Err(err) => {
                let err = EngineError::WriteErrorPageError {
                    source: err,
                    dest: output.to_string(),
                };
                let err: Arc<Error> = Arc::new(err.into());
                self.plugins
                    .functional_actions
                    .export_error_page_actions
                    .after_failed_write
                    .run(err.clone(), self.plugins.get_plugin_data())
                    .map_err(|err| Arc::new(err.into()))?;
                return Err(err);
            }
        };

        self.plugins
            .functional_actions
            .export_error_page_actions
            .after_successful_export_error_page
            .run((), self.plugins.get_plugin_data())
            .map_err(|err| Arc::new(err.into()))?;

        Ok(())
    }
}