From b5ee9a89809f726b5bddb6388eafeadb341dede2 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Mon, 7 Nov 2016 01:18:53 -0500 Subject: [PATCH] Limit number of words or characters in the request Config options for both. --- config.toml | 4 ++ src/config.rs | 10 +++++ src/handlers/audio_synth_handler.rs | 63 ++++++++++++++++------------- 3 files changed, 48 insertions(+), 29 deletions(-) diff --git a/config.toml b/config.toml index e09dc2a900..91a4ee1ac3 100644 --- a/config.toml +++ b/config.toml @@ -9,6 +9,10 @@ square_dictionary_file = "./dictionary/square-dict" abbreviation_file = "./dictionary/abbreviations.dict" + # Input control. Respond with 400 when over limit. + max_num_characters = 255 + max_num_words = 100 + # Logging verbosity log_handler = false log_parsing = false diff --git a/src/config.rs b/src/config.rs index 9fe60921f2..92349de484 100644 --- a/src/config.rs +++ b/src/config.rs @@ -25,6 +25,10 @@ pub struct Config { /// Where the abbreviation file is found. pub abbreviation_file: Option, + /// Input control. Respond with 400 when over limit. + pub max_num_characters: Option, + pub max_num_words: Option, + /// What events to log. pub log_handler: Option, pub log_parsing: Option, @@ -111,6 +115,12 @@ impl Config { abbreviation_file: self.abbreviation_file .clone() .or(other.abbreviation_file.clone()), + max_num_characters: self.max_num_characters + .clone() + .or(other.max_num_characters.clone()), + max_num_words: self.max_num_words + .clone() + .or(other.max_num_words.clone()), log_handler: self.log_handler .clone() .or(other.log_handler.clone()), diff --git a/src/handlers/audio_synth_handler.rs b/src/handlers/audio_synth_handler.rs index bd40857c3e..d6061635d5 100644 --- a/src/handlers/audio_synth_handler.rs +++ b/src/handlers/audio_synth_handler.rs @@ -13,6 +13,7 @@ use iron::mime::Mime; use iron::prelude::IronResult; use iron::prelude::Request; use iron::prelude::Response; +use iron::status::BadRequest; use iron::status; use lang::parser::Parser; use speaker::Speaker; @@ -215,7 +216,7 @@ impl SpeakRequest { impl Handler for AudioSynthHandler { /// Process request. fn handle(&self, req: &mut Request) -> IronResult { - let sentence_error = build_error(status::BadRequest, + let sentence_error = build_error(BadRequest, &format!("Missing `{}` parameter.", SENTENCE_PARAM)); let request = match SpeakRequest::parse(req) { @@ -249,8 +250,39 @@ impl Handler for AudioSynthHandler { } } + let max_characters = self.config.max_num_characters.unwrap_or(5_000); + if request.sentence.len() > max_characters { + return build_error(BadRequest, "Too many characters in request."); + } + + // GENERATE AUDIO + let start = PreciseTime::now(); - let result = try!(self.create_audio(request)); + + let synth = try!(self.synthesizer.read().map_err(|_| SynthesisError::LockError)); + + let params = SynthesisParams { + use_words: request.use_words, + use_bare_monophones: request.use_bare_monophones, + use_n_phones: request.use_n_phones, + use_syllables: request.use_syllables, + use_ends: request.use_ends, + volume: request.volume, + speed: request.speed, + padding_between_phones: request.padding_between_phones, + polyphone_padding_start: request.polyphone_padding_start, + polyphone_padding_end: request.polyphone_padding_end, + word_padding_start: request.word_padding_start, + word_padding_end: request.word_padding_end, + }; + + let tokens = self.parser.parse(&request.sentence); + + if tokens.len() > self.config.max_num_words.unwrap_or(1_000) { + return build_error(BadRequest, "Too many words in request."); + } + + let result = try!(synth.generate(tokens, &request.speaker, params)); info!(target: "timing", "Total parsing and synthesis took: {}", start.to(PreciseTime::now())); @@ -274,33 +306,6 @@ impl AudioSynthHandler { config: config, } } - - /// Create audio from the sentence. - fn create_audio(&self, request: SpeakRequest) - -> Result, SynthesisError> { - let synth = match self.synthesizer.read() { - Err(_) => { return Err(SynthesisError::LockError); }, - Ok(synth) => synth, - }; - - let params = SynthesisParams { - use_words: request.use_words, - use_bare_monophones: request.use_bare_monophones, - use_n_phones: request.use_n_phones, - use_syllables: request.use_syllables, - use_ends: request.use_ends, - volume: request.volume, - speed: request.speed, - padding_between_phones: request.padding_between_phones, - polyphone_padding_start: request.polyphone_padding_start, - polyphone_padding_end: request.polyphone_padding_end, - word_padding_start: request.word_padding_start, - word_padding_end: request.word_padding_end, - }; - - let tokens = self.parser.parse(&request.sentence); - synth.generate(tokens, &request.speaker, params) - } } fn get_str<'a>(params: &'a QueryParams, param_name: &str)