From 12268919c24ccdf24e8ad95949125f72d53f318e Mon Sep 17 00:00:00 2001 From: ksg Date: Sun, 22 Sep 2024 03:32:50 +0900 Subject: [PATCH 1/9] refactor: refactor config initializer to handle missing keys and add new default option --- src/config_initializer.cr | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/config_initializer.cr b/src/config_initializer.cr index 1d575585..4be2bc37 100644 --- a/src/config_initializer.cr +++ b/src/config_initializer.cr @@ -47,8 +47,10 @@ class ConfigInitializer symbolized_hash = parsed_yaml.transform_keys(&.to_s) # Transform specific keys from "yes"/"no" to true/false for old version noir config - ["color", "debug", "include_path", "nolog", "send_req", "all_taggers"].each do |key| - if symbolized_hash[key] == "yes" + ["color", "debug", "show_status", "include_path", "nolog", "send_req", "all_taggers"].each do |key| + if !symbolized_hash.has_key?(key) + symbolized_hash[key] = default_options[key] + elsif symbolized_hash[key] == "yes" symbolized_hash[key] = YAML::Any.new(true) elsif symbolized_hash[key] == "no" symbolized_hash[key] = YAML::Any.new(false) @@ -61,7 +63,9 @@ class ConfigInitializer "set_pvalue", "set_pvalue_header", "set_pvalue_cookie", "set_pvalue_query", "set_pvalue_form", "set_pvalue_json", "set_pvalue_path", ].each do |key| - if symbolized_hash[key].to_s == "" + if !symbolized_hash.has_key?(key) + symbolized_hash[key] = default_options[key] + elsif symbolized_hash[key].to_s == "" # If the value is an empty string, initialize it as an empty array of YAML::Any symbolized_hash[key] = YAML::Any.new([] of YAML::Any) else @@ -94,6 +98,7 @@ class ConfigInitializer "debug" => YAML::Any.new(false), "exclude_techs" => YAML::Any.new(""), "format" => YAML::Any.new("plain"), + "show_status" => YAML::Any.new(false), "include_path" => YAML::Any.new(false), "nolog" => YAML::Any.new(false), "output" => YAML::Any.new(""), From c4da29770351aaea904ff20772dbfcdc67992bb0 Mon Sep 17 00:00:00 2001 From: ksg Date: Sun, 22 Sep 2024 03:35:29 +0900 Subject: [PATCH 2/9] feat: add a new `--show-status` boolean option --- docs/_advanced/configuration.md | 3 ++ src/models/endpoint.cr | 10 +++++- src/models/noir.cr | 58 ++++++++++++++++++++++++++++++++- src/noir.cr | 8 +++++ src/options.cr | 5 +++ src/output_builder/common.cr | 5 +++ 6 files changed, 87 insertions(+), 2 deletions(-) diff --git a/docs/_advanced/configuration.md b/docs/_advanced/configuration.md index 60bb7f0a..fd949ba7 100644 --- a/docs/_advanced/configuration.md +++ b/docs/_advanced/configuration.md @@ -51,6 +51,9 @@ exclude_techs: "" # The format to use for the output format: "plain" +# Whether to display HTTP status codes in the output +show_status: "false" + # Whether to include the path in the output include_path: "false" diff --git a/src/models/endpoint.cr b/src/models/endpoint.cr index 0d538db2..0006b008 100644 --- a/src/models/endpoint.cr +++ b/src/models/endpoint.cr @@ -30,7 +30,8 @@ struct Endpoint @tags = [] of Tag end - def details=(@details : Details) + def details=(details : Details) + @details = details end def protocol=(protocol : String) @@ -52,6 +53,7 @@ struct Endpoint params_hash["form"] = {} of String => String params_hash["header"] = {} of String => String params_hash["cookie"] = {} of String => String + params_hash["path"] = {} of String => String @params.each do |param| params_hash[param.param_type][param.name] = param.value @@ -107,6 +109,7 @@ struct Details include JSON::Serializable include YAML::Serializable property code_paths : Array(PathInfo) = [] of PathInfo + property status_code : Int32 | Nil # + New details types to be added in the future.. @@ -121,7 +124,12 @@ struct Details @code_paths << code_path end + def status_code=(status_code : Int32) + @status_code = status_code + end + def ==(other : Details) : Bool + return false if @status_code != other.status_code return false if @code_paths.size != other.code_paths.size return false unless @code_paths.all? { |path| other.code_paths.any? { |other_path| path == other_path } } true diff --git a/src/models/noir.cr b/src/models/noir.cr index 814708ea..672de252 100644 --- a/src/models/noir.cr +++ b/src/models/noir.cr @@ -85,6 +85,11 @@ class NoirRunner combine_url_and_endpoints add_path_parameters + # Set status code + if any_to_bool(@options["show_status"]) == true + update_status_codes + end + # Run tagger if any_to_bool(@options["all_taggers"]) == true @logger.success "Running all taggers." @@ -219,7 +224,7 @@ class NoirRunner end def add_path_parameters - @logger.info "Adding path parameters by URL" + @logger.info "Adding path parameters by URL." final = [] of Endpoint @endpoints.each do |endpoint| @@ -263,6 +268,57 @@ class NoirRunner @endpoints = final end + def update_status_codes + @logger.info "Updating status codes." + final = [] of Endpoint + + @endpoints.each do |endpoint| + begin + if endpoint.params.size > 0 + endpoint_hash = endpoint.params_to_hash + body = {} of String => String + is_json = false + if endpoint_hash["json"].size > 0 + is_json = true + body = endpoint_hash["json"] + else + body = endpoint_hash["form"] + end + + response = Crest::Request.execute( + method: get_symbol(endpoint.method), + url: endpoint.url, + tls: OpenSSL::SSL::Context::Client.insecure, + user_agent: "Noir/#{Noir::VERSION}", + params: endpoint_hash["query"], + form: body, + json: is_json, + handle_errors: false, + read_timeout: 5.second + ) + endpoint.details.status_code = response.status_code + final << endpoint + else + response = Crest::Request.execute( + method: get_symbol(endpoint.method), + url: endpoint.url, + tls: OpenSSL::SSL::Context::Client.insecure, + user_agent: "Noir/#{Noir::VERSION}", + handle_errors: false, + read_timeout: 5.second + ) + endpoint.details.status_code = response.status_code + final << endpoint + end + rescue e + @logger.error "Failed to get status code for #{endpoint.url} (#{e.message})." + final << endpoint + end + end + + @endpoints = final + end + def deliver if @send_proxy != "" @logger.info "Sending requests with proxy #{@send_proxy}." diff --git a/src/noir.cr b/src/noir.cr index 764e9509..698f50d9 100644 --- a/src/noir.cr +++ b/src/noir.cr @@ -23,6 +23,14 @@ if noir_options["base"] == "" exit(1) end +# Check URL +if noir_options["show_status"] && noir_options["url"] == "" + STDERR.puts "ERROR: --show-status requires -u or --url flag.".colorize(:yellow) + STDERR.puts "Please use -u or --url to set the URL." + STDERR.puts "If you need help, use -h or --help." + exit(1) +end + # Run Noir app = NoirRunner.new noir_options start_time = Time.monotonic diff --git a/src/options.cr b/src/options.cr index 7d1bf76d..b8c51913 100644 --- a/src/options.cr +++ b/src/options.cr @@ -54,9 +54,14 @@ def run_options_parser append_to_yaml_array(noir_options, set_pvalue_path, var) end + parser.on "--show-status", "Display HTTP status codes for discovered endpoints" do + noir_options["show_status"] = YAML::Any.new(true) + end + parser.on "--include-path", "Include file path in the plain result" do noir_options["include_path"] = YAML::Any.new(true) end + parser.on "--no-color", "Disable color output" do noir_options["color"] = YAML::Any.new(false) end diff --git a/src/output_builder/common.cr b/src/output_builder/common.cr index f3ffcac2..9bad5fda 100644 --- a/src/output_builder/common.cr +++ b/src/output_builder/common.cr @@ -76,6 +76,11 @@ class OutputBuilderCommon < OutputBuilder end end + if any_to_bool(@options["show_status"]) == true + r_status = endpoint.details.status_code.to_s.colorize(:light_yellow).toggle(@is_color) + r_buffer += "\n ○ status: #{r_status}" + end + ob_puts r_buffer end end From 418f3edd90115337fdb113d8efd1f4648879eb26 Mon Sep 17 00:00:00 2001 From: ksg Date: Sun, 22 Sep 2024 03:36:18 +0900 Subject: [PATCH 3/9] chore: update docs, completions --- docs/_includes/usage.md | 9 ++++++++- src/completions.cr | 14 ++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/_includes/usage.md b/docs/_includes/usage.md index 0d73054b..232fc43c 100644 --- a/docs/_includes/usage.md +++ b/docs/_includes/usage.md @@ -11,7 +11,14 @@ FLAGS: * curl httpie oas2 oas3 * only-url only-param only-header only-cookie only-tag -o PATH, --output out.txt Write result to file - --set-pvalue VALUE Specifies the value of the identified parameter + --set-pvalue VALUE Specifies the value of the identified parameter for all types + --set-pvalue-header VALUE Specifies the value of the identified parameter for headers + --set-pvalue-cookie VALUE Specifies the value of the identified parameter for cookies + --set-pvalue-query VALUE Specifies the value of the identified parameter for query parameters + --set-pvalue-form VALUE Specifies the value of the identified parameter for form data + --set-pvalue-json VALUE Specifies the value of the identified parameter for JSON data + --set-pvalue-path VALUE Specifies the value of the identified parameter for path parameters + --show-status Display HTTP status codes for discovered endpoints --include-path Include file path in the plain result --no-color Disable color output --no-log Displaying only the results diff --git a/src/completions.cr b/src/completions.cr index 84463346..521965f8 100644 --- a/src/completions.cr +++ b/src/completions.cr @@ -8,6 +8,13 @@ def generate_zsh_completion_script '-f[Set output format]:format:(plain yaml json jsonl markdown-table curl httpie oas2 oas3 only-url only-param only-header only-cookie)' \\ '-o[Write result to file]:path:_files' \\ '--set-pvalue[Specifies the value of the identified parameter]:value:' \\ + '--set-pvalue-header[Specifies the value of the identified parameter for headers]:value:' \\ + '--set-pvalue-cookie[Specifies the value of the identified parameter for cookies]:value:' \\ + '--set-pvalue-query[Specifies the value of the identified parameter for query parameters]:value:' \\ + '--set-pvalue-form[Specifies the value of the identified parameter for form data]:value:' \\ + '--set-pvalue-json[Specifies the value of the identified parameter for JSON data]:value:' \\ + '--set-pvalue-path[Specifies the value of the identified parameter for path parameters]:value:' \\ + '--show-status[Display HTTP status codes for discovered endpoints]' \\ '--include-path[Include file path in the plain result]' \\ '--no-color[Disable color output]' \\ '--no-log[Displaying only the results]' \\ @@ -46,6 +53,13 @@ def generate_bash_completion_script -f --format -o --output --set-pvalue + --set-pvalue-header + --set-pvalue-cookie + --set-pvalue-query + --set-pvalue-form + --set-pvalue-json + --set-pvalue-path + --show-status --include-path --no-color --no-log From 2c6df5c3aa1582edd61e3000de19edf1c7b01534 Mon Sep 17 00:00:00 2001 From: ksg Date: Sun, 22 Sep 2024 03:47:26 +0900 Subject: [PATCH 4/9] fix: correct path parameter handling --- src/models/noir.cr | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/models/noir.cr b/src/models/noir.cr index 672de252..414aaa58 100644 --- a/src/models/noir.cr +++ b/src/models/noir.cr @@ -232,10 +232,10 @@ class NoirRunner scans = endpoint.url.scan(/\/\{([^}]+)\}/).flatten scans.each do |match| - param = match[1].split(":")[-1] + param = match[1].split(":")[0] new_value = apply_pvalue("path", param, "") if new_value != "" - new_endpoint.url = new_endpoint.url.gsub("{#{param}}", new_value) + new_endpoint.url = new_endpoint.url.gsub("{#{match[1]}}", new_value) end new_endpoint.params << Param.new(param, "", "path") @@ -243,13 +243,12 @@ class NoirRunner scans = endpoint.url.scan(/\/:([^\/]+)/).flatten scans.each do |match| - param = match[1].split(":")[-1] - new_value = apply_pvalue("path", param, "") + new_value = apply_pvalue("path", match[1], "") if new_value != "" new_endpoint.url = new_endpoint.url.gsub(":#{match[1]}", new_value) end - new_endpoint.params << Param.new(param, "", "path") + new_endpoint.params << Param.new(match[1], "", "path") end scans = endpoint.url.scan(/\/<([^>]+)>/).flatten From 5141bd7a0924e6efe27254c6a6b65e0d70a2ed05 Mon Sep 17 00:00:00 2001 From: ksg Date: Sun, 22 Sep 2024 04:09:43 +0900 Subject: [PATCH 5/9] fix: fix conditional check for show_status and url in noir.cr --- src/noir.cr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/noir.cr b/src/noir.cr index 698f50d9..cc2a902d 100644 --- a/src/noir.cr +++ b/src/noir.cr @@ -24,7 +24,7 @@ if noir_options["base"] == "" end # Check URL -if noir_options["show_status"] && noir_options["url"] == "" +if noir_options["show_status"] == true && noir_options["url"] == "" STDERR.puts "ERROR: --show-status requires -u or --url flag.".colorize(:yellow) STDERR.puts "Please use -u or --url to set the URL." STDERR.puts "If you need help, use -h or --help." From 233b5fccda793a2ed113a0d144ee0ab7732496a6 Mon Sep 17 00:00:00 2001 From: ksg Date: Sun, 22 Sep 2024 04:42:17 +0900 Subject: [PATCH 6/9] feat: add a new `--exclude-status` string option --- docs/_advanced/configuration.md | 3 +++ docs/_includes/usage.md | 1 + src/completions.cr | 2 ++ src/config_initializer.cr | 3 ++- src/models/noir.cr | 23 ++++++++++++++++++++--- src/noir.cr | 8 ++++++++ src/options.cr | 3 +++ src/output_builder/common.cr | 2 +- 8 files changed, 40 insertions(+), 5 deletions(-) diff --git a/docs/_advanced/configuration.md b/docs/_advanced/configuration.md index fd949ba7..f19a0a54 100644 --- a/docs/_advanced/configuration.md +++ b/docs/_advanced/configuration.md @@ -54,6 +54,9 @@ format: "plain" # Whether to display HTTP status codes in the output show_status: "false" +# Whether to exclude HTTP status codes from the output +exclude_status: "" + # Whether to include the path in the output include_path: "false" diff --git a/docs/_includes/usage.md b/docs/_includes/usage.md index 232fc43c..55e5e903 100644 --- a/docs/_includes/usage.md +++ b/docs/_includes/usage.md @@ -19,6 +19,7 @@ FLAGS: --set-pvalue-json VALUE Specifies the value of the identified parameter for JSON data --set-pvalue-path VALUE Specifies the value of the identified parameter for path parameters --show-status Display HTTP status codes for discovered endpoints + --exclude-status Exclude specific HTTP status code --include-path Include file path in the plain result --no-color Disable color output --no-log Displaying only the results diff --git a/src/completions.cr b/src/completions.cr index 521965f8..fcc3a68c 100644 --- a/src/completions.cr +++ b/src/completions.cr @@ -15,6 +15,7 @@ def generate_zsh_completion_script '--set-pvalue-json[Specifies the value of the identified parameter for JSON data]:value:' \\ '--set-pvalue-path[Specifies the value of the identified parameter for path parameters]:value:' \\ '--show-status[Display HTTP status codes for discovered endpoints]' \\ + '--exclude-status[Exclude specific HTTP status codes from the results]:status:' \\ '--include-path[Include file path in the plain result]' \\ '--no-color[Disable color output]' \\ '--no-log[Displaying only the results]' \\ @@ -60,6 +61,7 @@ def generate_bash_completion_script --set-pvalue-json --set-pvalue-path --show-status + --exclude-status --include-path --no-color --no-log diff --git a/src/config_initializer.cr b/src/config_initializer.cr index 4be2bc37..9210045d 100644 --- a/src/config_initializer.cr +++ b/src/config_initializer.cr @@ -47,7 +47,7 @@ class ConfigInitializer symbolized_hash = parsed_yaml.transform_keys(&.to_s) # Transform specific keys from "yes"/"no" to true/false for old version noir config - ["color", "debug", "show_status", "include_path", "nolog", "send_req", "all_taggers"].each do |key| + ["color", "debug", "show_status", "exclude_status", "include_path", "nolog", "send_req", "all_taggers"].each do |key| if !symbolized_hash.has_key?(key) symbolized_hash[key] = default_options[key] elsif symbolized_hash[key] == "yes" @@ -99,6 +99,7 @@ class ConfigInitializer "exclude_techs" => YAML::Any.new(""), "format" => YAML::Any.new("plain"), "show_status" => YAML::Any.new(false), + "exclude_status" => YAML::Any.new(""), "include_path" => YAML::Any.new(false), "nolog" => YAML::Any.new(false), "output" => YAML::Any.new(""), diff --git a/src/models/noir.cr b/src/models/noir.cr index 414aaa58..edc63be8 100644 --- a/src/models/noir.cr +++ b/src/models/noir.cr @@ -86,7 +86,7 @@ class NoirRunner add_path_parameters # Set status code - if any_to_bool(@options["show_status"]) == true + if any_to_bool(@options["show_status"]) == true || any_to_bool(@options["exclude_status"]) != "" update_status_codes end @@ -271,6 +271,19 @@ class NoirRunner @logger.info "Updating status codes." final = [] of Endpoint + exclude_status = [] of Int32 + @options["exclude_status"].to_s.split(",").each do |code| + if code.size > 0 + begin + exclude_status << code.strip.to_i + rescue + @logger.error "Invalid --exclude-status option: '#{code}'" + @logger.error "Please use comma separated numbers." + exit(1) + end + end + end + @endpoints.each do |endpoint| begin if endpoint.params.size > 0 @@ -296,7 +309,9 @@ class NoirRunner read_timeout: 5.second ) endpoint.details.status_code = response.status_code - final << endpoint + unless exclude_status.includes?(response.status_code) + final << endpoint + end else response = Crest::Request.execute( method: get_symbol(endpoint.method), @@ -307,7 +322,9 @@ class NoirRunner read_timeout: 5.second ) endpoint.details.status_code = response.status_code - final << endpoint + unless exclude_status.includes?(response.status_code) + final << endpoint + end end rescue e @logger.error "Failed to get status code for #{endpoint.url} (#{e.message})." diff --git a/src/noir.cr b/src/noir.cr index cc2a902d..da139689 100644 --- a/src/noir.cr +++ b/src/noir.cr @@ -31,6 +31,14 @@ if noir_options["show_status"] == true && noir_options["url"] == "" exit(1) end +# Check URL +if noir_options["exclude_status"] != "" && noir_options["url"] == "" + STDERR.puts "ERROR: --exclude-status requires -u or --url flag.".colorize(:yellow) + STDERR.puts "Please use -u or --url to set the URL." + STDERR.puts "If you need help, use -h or --help." + exit(1) +end + # Run Noir app = NoirRunner.new noir_options start_time = Time.monotonic diff --git a/src/options.cr b/src/options.cr index b8c51913..8e2e190a 100644 --- a/src/options.cr +++ b/src/options.cr @@ -58,6 +58,8 @@ def run_options_parser noir_options["show_status"] = YAML::Any.new(true) end + parser.on "--exclude-status 404,500", "Exclude specific HTTP status codes" { |var| noir_options["exclude_status"] = YAML::Any.new(var) } + parser.on "--include-path", "Include file path in the plain result" do noir_options["include_path"] = YAML::Any.new(true) end @@ -65,6 +67,7 @@ def run_options_parser parser.on "--no-color", "Disable color output" do noir_options["color"] = YAML::Any.new(false) end + parser.on "--no-log", "Displaying only the results" do noir_options["nolog"] = YAML::Any.new(true) end diff --git a/src/output_builder/common.cr b/src/output_builder/common.cr index 9bad5fda..76c1c184 100644 --- a/src/output_builder/common.cr +++ b/src/output_builder/common.cr @@ -76,7 +76,7 @@ class OutputBuilderCommon < OutputBuilder end end - if any_to_bool(@options["show_status"]) == true + if any_to_bool(@options["show_status"]) == true || @options["exclude_status"] != "" r_status = endpoint.details.status_code.to_s.colorize(:light_yellow).toggle(@is_color) r_buffer += "\n ○ status: #{r_status}" end From 78477bcd2835ff18a42b46482c2a74cd35ac7502 Mon Sep 17 00:00:00 2001 From: ksg Date: Sun, 22 Sep 2024 05:17:22 +0900 Subject: [PATCH 7/9] refactor: refactor exclude_status option handling --- src/models/noir.cr | 12 +++--------- src/noir.cr | 27 ++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/models/noir.cr b/src/models/noir.cr index edc63be8..f0ccf2a7 100644 --- a/src/models/noir.cr +++ b/src/models/noir.cr @@ -272,15 +272,9 @@ class NoirRunner final = [] of Endpoint exclude_status = [] of Int32 - @options["exclude_status"].to_s.split(",").each do |code| - if code.size > 0 - begin - exclude_status << code.strip.to_i - rescue - @logger.error "Invalid --exclude-status option: '#{code}'" - @logger.error "Please use comma separated numbers." - exit(1) - end + if @options["exclude_status"].to_s != "" + @options["exclude_status"].to_s.split(",").each do |code| + exclude_status << code.strip.to_i end end diff --git a/src/noir.cr b/src/noir.cr index da139689..66126851 100644 --- a/src/noir.cr +++ b/src/noir.cr @@ -23,6 +23,11 @@ if noir_options["base"] == "" exit(1) end +if noir_options["url"] != "" && noir_options["url"].to_s.starts_with?("http") == false + STDERR.puts "ERROR: Invalid URL format: '#{noir_options["url"]}' (missing HTTP protocol).".colorize(:yellow) + noir_options["url"] = YAML::Any.new("http://#{noir_options["url"]}") +end + # Check URL if noir_options["show_status"] == true && noir_options["url"] == "" STDERR.puts "ERROR: --show-status requires -u or --url flag.".colorize(:yellow) @@ -32,11 +37,23 @@ if noir_options["show_status"] == true && noir_options["url"] == "" end # Check URL -if noir_options["exclude_status"] != "" && noir_options["url"] == "" - STDERR.puts "ERROR: --exclude-status requires -u or --url flag.".colorize(:yellow) - STDERR.puts "Please use -u or --url to set the URL." - STDERR.puts "If you need help, use -h or --help." - exit(1) +if noir_options["exclude_status"] != "" + if noir_options["url"] == "" + STDERR.puts "ERROR: --exclude-status requires -u or --url flag.".colorize(:yellow) + STDERR.puts "Please use -u or --url to set the URL." + STDERR.puts "If you need help, use -h or --help." + exit(1) + end + + noir_options["exclude_status"].to_s.split(",").each do |code| + begin + code.strip.to_i + rescue + STDERR.puts "ERROR: Invalid --exclude-status option: '#{code}'".colorize(:yellow) + STDERR.puts "Please use comma-separated numbers." + exit(1) + end + end end # Run Noir From 36b8ead1713be4ea5d10eb0b32e8e091d19c89e7 Mon Sep 17 00:00:00 2001 From: ksg Date: Sun, 22 Sep 2024 14:34:05 +0900 Subject: [PATCH 8/9] Refactor: rename the option and update the output color. --- docs/_advanced/configuration.md | 4 ++-- docs/_includes/usage.md | 4 ++-- src/completions.cr | 8 ++++---- src/config_initializer.cr | 14 +++++--------- src/models/noir.cr | 14 +++++++------- src/noir.cr | 16 ++++++++-------- src/options.cr | 12 ++++++------ src/output_builder/common.cr | 24 +++++++++++++++++++----- 8 files changed, 53 insertions(+), 43 deletions(-) diff --git a/docs/_advanced/configuration.md b/docs/_advanced/configuration.md index f19a0a54..5ca6553f 100644 --- a/docs/_advanced/configuration.md +++ b/docs/_advanced/configuration.md @@ -52,10 +52,10 @@ exclude_techs: "" format: "plain" # Whether to display HTTP status codes in the output -show_status: "false" +status_codes: "false" # Whether to exclude HTTP status codes from the output -exclude_status: "" +exclude_codes: "" # Whether to include the path in the output include_path: "false" diff --git a/docs/_includes/usage.md b/docs/_includes/usage.md index 55e5e903..8216b124 100644 --- a/docs/_includes/usage.md +++ b/docs/_includes/usage.md @@ -18,8 +18,8 @@ FLAGS: --set-pvalue-form VALUE Specifies the value of the identified parameter for form data --set-pvalue-json VALUE Specifies the value of the identified parameter for JSON data --set-pvalue-path VALUE Specifies the value of the identified parameter for path parameters - --show-status Display HTTP status codes for discovered endpoints - --exclude-status Exclude specific HTTP status code + --status-codes Display HTTP status codes for discovered endpoints + --exclude-codes Exclude specific HTTP status code --include-path Include file path in the plain result --no-color Disable color output --no-log Displaying only the results diff --git a/src/completions.cr b/src/completions.cr index fcc3a68c..dc6f996c 100644 --- a/src/completions.cr +++ b/src/completions.cr @@ -14,8 +14,8 @@ def generate_zsh_completion_script '--set-pvalue-form[Specifies the value of the identified parameter for form data]:value:' \\ '--set-pvalue-json[Specifies the value of the identified parameter for JSON data]:value:' \\ '--set-pvalue-path[Specifies the value of the identified parameter for path parameters]:value:' \\ - '--show-status[Display HTTP status codes for discovered endpoints]' \\ - '--exclude-status[Exclude specific HTTP status codes from the results]:status:' \\ + '--status-codes[Display HTTP status codes for discovered endpoints]' \\ + '--exclude-codes[Exclude specific HTTP response codes (comma-separated)]:status:' \\ '--include-path[Include file path in the plain result]' \\ '--no-color[Disable color output]' \\ '--no-log[Displaying only the results]' \\ @@ -60,8 +60,8 @@ def generate_bash_completion_script --set-pvalue-form --set-pvalue-json --set-pvalue-path - --show-status - --exclude-status + --status-codes + --exclude-codes --include-path --no-color --no-log diff --git a/src/config_initializer.cr b/src/config_initializer.cr index 9210045d..47dbb045 100644 --- a/src/config_initializer.cr +++ b/src/config_initializer.cr @@ -47,10 +47,8 @@ class ConfigInitializer symbolized_hash = parsed_yaml.transform_keys(&.to_s) # Transform specific keys from "yes"/"no" to true/false for old version noir config - ["color", "debug", "show_status", "exclude_status", "include_path", "nolog", "send_req", "all_taggers"].each do |key| - if !symbolized_hash.has_key?(key) - symbolized_hash[key] = default_options[key] - elsif symbolized_hash[key] == "yes" + ["color", "debug", "include_path", "nolog", "send_req", "all_taggers"].each do |key| + if symbolized_hash[key] == "yes" symbolized_hash[key] = YAML::Any.new(true) elsif symbolized_hash[key] == "no" symbolized_hash[key] = YAML::Any.new(false) @@ -63,9 +61,7 @@ class ConfigInitializer "set_pvalue", "set_pvalue_header", "set_pvalue_cookie", "set_pvalue_query", "set_pvalue_form", "set_pvalue_json", "set_pvalue_path", ].each do |key| - if !symbolized_hash.has_key?(key) - symbolized_hash[key] = default_options[key] - elsif symbolized_hash[key].to_s == "" + if symbolized_hash[key].to_s == "" # If the value is an empty string, initialize it as an empty array of YAML::Any symbolized_hash[key] = YAML::Any.new([] of YAML::Any) else @@ -98,8 +94,8 @@ class ConfigInitializer "debug" => YAML::Any.new(false), "exclude_techs" => YAML::Any.new(""), "format" => YAML::Any.new("plain"), - "show_status" => YAML::Any.new(false), - "exclude_status" => YAML::Any.new(""), + "status_codes" => YAML::Any.new(false), + "exclude_codes" => YAML::Any.new(""), "include_path" => YAML::Any.new(false), "nolog" => YAML::Any.new(false), "output" => YAML::Any.new(""), diff --git a/src/models/noir.cr b/src/models/noir.cr index f0ccf2a7..727df551 100644 --- a/src/models/noir.cr +++ b/src/models/noir.cr @@ -86,7 +86,7 @@ class NoirRunner add_path_parameters # Set status code - if any_to_bool(@options["show_status"]) == true || any_to_bool(@options["exclude_status"]) != "" + if any_to_bool(@options["status_codes"]) == true || any_to_bool(@options["exclude_codes"]) != "" update_status_codes end @@ -271,10 +271,10 @@ class NoirRunner @logger.info "Updating status codes." final = [] of Endpoint - exclude_status = [] of Int32 - if @options["exclude_status"].to_s != "" - @options["exclude_status"].to_s.split(",").each do |code| - exclude_status << code.strip.to_i + exclude_codes = [] of Int32 + if @options["exclude_codes"].to_s != "" + @options["exclude_codes"].to_s.split(",").each do |code| + exclude_codes << code.strip.to_i end end @@ -303,7 +303,7 @@ class NoirRunner read_timeout: 5.second ) endpoint.details.status_code = response.status_code - unless exclude_status.includes?(response.status_code) + unless exclude_codes.includes?(response.status_code) final << endpoint end else @@ -316,7 +316,7 @@ class NoirRunner read_timeout: 5.second ) endpoint.details.status_code = response.status_code - unless exclude_status.includes?(response.status_code) + unless exclude_codes.includes?(response.status_code) final << endpoint end end diff --git a/src/noir.cr b/src/noir.cr index 66126851..9ab27afe 100644 --- a/src/noir.cr +++ b/src/noir.cr @@ -23,33 +23,33 @@ if noir_options["base"] == "" exit(1) end -if noir_options["url"] != "" && noir_options["url"].to_s.starts_with?("http") == false - STDERR.puts "ERROR: Invalid URL format: '#{noir_options["url"]}' (missing HTTP protocol).".colorize(:yellow) +if noir_options["url"] != "" && !noir_options["url"].to_s.includes?("://") + STDERR.puts "WARNING: The protocol (http or https) is missing in the URL '#{noir_options["url"]}'.".colorize(Colorize::Color256.new(208)) noir_options["url"] = YAML::Any.new("http://#{noir_options["url"]}") end # Check URL -if noir_options["show_status"] == true && noir_options["url"] == "" - STDERR.puts "ERROR: --show-status requires -u or --url flag.".colorize(:yellow) +if noir_options["status_codes"] == true && noir_options["url"] == "" + STDERR.puts "ERROR: The --status-codes option requires the -u or --url flag to be specified.".colorize(:yellow) STDERR.puts "Please use -u or --url to set the URL." STDERR.puts "If you need help, use -h or --help." exit(1) end # Check URL -if noir_options["exclude_status"] != "" +if noir_options["exclude_codes"] != "" if noir_options["url"] == "" - STDERR.puts "ERROR: --exclude-status requires -u or --url flag.".colorize(:yellow) + STDERR.puts "ERROR: The --exclude-codes option requires the -u or --url flag to be specified.".colorize(:yellow) STDERR.puts "Please use -u or --url to set the URL." STDERR.puts "If you need help, use -h or --help." exit(1) end - noir_options["exclude_status"].to_s.split(",").each do |code| + noir_options["exclude_codes"].to_s.split(",").each do |code| begin code.strip.to_i rescue - STDERR.puts "ERROR: Invalid --exclude-status option: '#{code}'".colorize(:yellow) + STDERR.puts "ERROR: Invalid --exclude-codes option: '#{code}'".colorize(:yellow) STDERR.puts "Please use comma-separated numbers." exit(1) end diff --git a/src/options.cr b/src/options.cr index 8e2e190a..a8406c21 100644 --- a/src/options.cr +++ b/src/options.cr @@ -54,11 +54,11 @@ def run_options_parser append_to_yaml_array(noir_options, set_pvalue_path, var) end - parser.on "--show-status", "Display HTTP status codes for discovered endpoints" do - noir_options["show_status"] = YAML::Any.new(true) + parser.on "--status-codes", "Display HTTP status codes for discovered endpoints" do + noir_options["status_codes"] = YAML::Any.new(true) end - parser.on "--exclude-status 404,500", "Exclude specific HTTP status codes" { |var| noir_options["exclude_status"] = YAML::Any.new(var) } + parser.on "--exclude-codes 404,500", "Exclude specific HTTP response codes (comma-separated)" { |var| noir_options["exclude_codes"] = YAML::Any.new(var) } parser.on "--include-path", "Include file path in the plain result" do noir_options["include_path"] = YAML::Any.new(true) @@ -133,7 +133,7 @@ def run_options_parser puts "\n" puts "> Instructions: Copy the content above and save it in the .bashrc file as noir.".colorize(:yellow) else - puts "ERROR: Invalid completion type." + puts "ERROR: Invalid completion type.".colorize(:yellow) puts "e.g., noir --generate-completion zsh" puts "e.g., noir --generate-completion bash" end @@ -171,12 +171,12 @@ def run_options_parser exit end parser.invalid_option do |flag| - STDERR.puts "ERROR: #{flag} is not a valid option." + STDERR.puts "ERROR: #{flag} is not a valid option.".colorize(:yellow) STDERR.puts parser exit(1) end parser.missing_option do |flag| - STDERR.puts "ERROR: #{flag} is missing an argument." + STDERR.puts "ERROR: #{flag} is missing an argument.".colorize(:yellow) exit(1) end end diff --git a/src/output_builder/common.cr b/src/output_builder/common.cr index 76c1c184..88caa892 100644 --- a/src/output_builder/common.cr +++ b/src/output_builder/common.cr @@ -20,6 +20,25 @@ class OutputBuilderCommon < OutputBuilder r_ws = "" r_buffer = "\n#{r_method} #{r_url}" + if any_to_bool(@options["status_codes"]) == true || @options["exclude_codes"] != "" + status_color = :light_green + status_code = endpoint.details.status_code + if status_code + if status_code >= 500 + status_color = :light_magenta + elsif status_code >= 400 + status_color = :light_red + elsif status_code >= 300 + status_color = :cyan + end + else + status_code = "error" + status_color = :light_red + end + + r_buffer += " [#{status_code}]".to_s.colorize(status_color).toggle(@is_color).to_s + end + if endpoint.protocol == "ws" r_ws = "[websocket]".colorize(:light_red).toggle(@is_color) r_buffer += " #{r_ws}" @@ -76,11 +95,6 @@ class OutputBuilderCommon < OutputBuilder end end - if any_to_bool(@options["show_status"]) == true || @options["exclude_status"] != "" - r_status = endpoint.details.status_code.to_s.colorize(:light_yellow).toggle(@is_color) - r_buffer += "\n ○ status: #{r_status}" - end - ob_puts r_buffer end end From 18e9620bf9d6dcdb726f790f97a833273ff55c3c Mon Sep 17 00:00:00 2001 From: ksg Date: Sun, 22 Sep 2024 14:46:19 +0900 Subject: [PATCH 9/9] Refactor: update usage.md formatting --- docs/_includes/usage.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/_includes/usage.md b/docs/_includes/usage.md index 8216b124..4883c74b 100644 --- a/docs/_includes/usage.md +++ b/docs/_includes/usage.md @@ -18,8 +18,8 @@ FLAGS: --set-pvalue-form VALUE Specifies the value of the identified parameter for form data --set-pvalue-json VALUE Specifies the value of the identified parameter for JSON data --set-pvalue-path VALUE Specifies the value of the identified parameter for path parameters - --status-codes Display HTTP status codes for discovered endpoints - --exclude-codes Exclude specific HTTP status code + --status-codes Display HTTP status codes for discovered endpoints + --exclude-codes Exclude specific HTTP status code --include-path Include file path in the plain result --no-color Disable color output --no-log Displaying only the results