1
1
use crate :: web:: page:: TemplateData ;
2
2
use lol_html:: errors:: RewritingError ;
3
+ use std:: path:: Path ;
3
4
use tera:: Context ;
4
5
5
6
/// Rewrite a rustdoc page to have the docs.rs header
@@ -13,6 +14,7 @@ pub(crate) fn rewrite_lol(
13
14
max_allowed_memory_usage : usize ,
14
15
ctx : Context ,
15
16
templates : & TemplateData ,
17
+ file_path : & Path ,
16
18
) -> Result < Vec < u8 > , RewritingError > {
17
19
use lol_html:: html_content:: { ContentType , Element } ;
18
20
use lol_html:: { ElementContentHandlers , HtmlRewriter , MemorySettings , Settings } ;
@@ -23,6 +25,7 @@ pub(crate) fn rewrite_lol(
23
25
24
26
let head_handler = |head : & mut Element | {
25
27
head. append ( & tera_head, ContentType :: Html ) ;
28
+
26
29
Ok ( ( ) )
27
30
} ;
28
31
@@ -77,11 +80,33 @@ pub(crate) fn rewrite_lol(
77
80
78
81
// The input and output are always strings, we just use `&[u8]` so we only have to validate once.
79
82
let mut buffer = Vec :: new ( ) ;
83
+ // TODO: Make the rewriter persistent?
80
84
let mut writer = HtmlRewriter :: try_new ( settings, |bytes : & [ u8 ] | {
81
85
buffer. extend_from_slice ( bytes) ;
82
86
} )
83
87
. expect ( "utf8 is a valid encoding" ) ;
84
- writer. write ( html) ?;
85
- writer. end ( ) ?;
88
+
89
+ log_memory_errors ( writer. write ( html) , file_path) ?;
90
+ log_memory_errors ( writer. end ( ) , file_path) ?;
91
+
86
92
Ok ( buffer)
87
93
}
94
+
95
+ /// Logs OOM errors encountered while rewriting a html file
96
+ fn log_memory_errors < T > (
97
+ result : Result < T , RewritingError > ,
98
+ file_path : & Path ,
99
+ ) -> Result < T , RewritingError > {
100
+ match result {
101
+ err @ Err ( RewritingError :: MemoryLimitExceeded ( ..) ) => {
102
+ crate :: web:: metrics:: HTML_REWRITE_OOMS . inc ( ) ;
103
+ log:: error!(
104
+ "Failed to serve the rustdoc file '{}' because rewriting it hit a memory limit" ,
105
+ file_path. display( ) ,
106
+ ) ;
107
+
108
+ err
109
+ }
110
+ result => result,
111
+ }
112
+ }
0 commit comments