@@ -230,7 +230,7 @@ impl HeaderContext {
230230
231231 async fn csv ( mut self , options : & JsonValue ) -> anyhow:: Result < PageContext > {
232232 self . response
233- . insert_header ( ( header:: CONTENT_TYPE , "text/csv" ) ) ;
233+ . insert_header ( ( header:: CONTENT_TYPE , "text/csv; charset=utf-8 " ) ) ;
234234 if let Some ( filename) = get_object_str ( options, "filename" ) {
235235 self . response . insert_header ( (
236236 header:: CONTENT_DISPOSITION ,
@@ -461,7 +461,7 @@ impl<W: std::io::Write> JsonBodyRenderer<W> {
461461
462462pub struct CsvBodyRenderer {
463463 writer : csv_async:: AsyncWriter < AsyncResponseWriter > ,
464- is_first : bool ,
464+ columns : Vec < String > ,
465465}
466466
467467impl CsvBodyRenderer {
@@ -501,29 +501,55 @@ impl CsvBodyRenderer {
501501 let writer = builder. create_writer ( async_writer) ;
502502 Ok ( CsvBodyRenderer {
503503 writer,
504- is_first : true ,
504+ columns : vec ! [ ] ,
505505 } )
506506 }
507507
508508 pub async fn handle_row ( & mut self , data : & JsonValue ) -> anyhow:: Result < ( ) > {
509- if self . is_first {
510- self . is_first = false ;
509+ if self . columns . is_empty ( ) {
511510 if let Some ( obj) = data. as_object ( ) {
512- let headers: Vec < _ > = obj. keys ( ) . collect ( ) ;
513- self . writer . write_record ( & headers) . await ?;
511+ let headers: Vec < String > = obj. keys ( ) . map ( String :: to_owned) . collect ( ) ;
512+ self . columns = headers;
513+ self . writer . write_record ( & self . columns ) . await ?;
514514 }
515515 }
516516
517517 if let Some ( obj) = data. as_object ( ) {
518- let values: Vec < _ > = obj. values ( ) . map ( std:: string:: ToString :: to_string) . collect ( ) ;
519- self . writer . write_record ( & values) . await ?;
518+ self . writer
519+ . write_record (
520+ self . columns
521+ . iter ( )
522+ . map ( |s| {
523+ let val = obj. get ( s) ;
524+ if let Some ( val) = val {
525+ if let Some ( s) = val. as_str ( ) {
526+ Cow :: Borrowed ( s. as_bytes ( ) )
527+ } else {
528+ Cow :: Owned ( val. to_string ( ) . into_bytes ( ) )
529+ }
530+ } else {
531+ Cow :: Borrowed ( & b"" [ ..] )
532+ }
533+ } )
534+ . collect :: < Vec < _ > > ( ) ,
535+ )
536+ . await ?;
520537 }
521538
522539 Ok ( ( ) )
523540 }
524541
525542 pub async fn handle_error ( & mut self , error : & anyhow:: Error ) -> anyhow:: Result < ( ) > {
526- self . writer . write_record ( & [ error. to_string ( ) ] ) . await ?;
543+ let err_str = error. to_string ( ) ;
544+ self . writer
545+ . write_record (
546+ self . columns
547+ . iter ( )
548+ . enumerate ( )
549+ . map ( |( i, _) | if i == 0 { & err_str } else { "" } )
550+ . collect :: < Vec < _ > > ( ) ,
551+ )
552+ . await ?;
527553 Ok ( ( ) )
528554 }
529555
0 commit comments