Responses and Debugging
How to inspect responses and check whether a request was sent as expected.
nil, status, and body
Section titled “nil, status, and body”res = send_request_cgi(...)fail_with(Failure::Unreachable, "#{peer} - no response") if res.nil?fail_with(Failure::UnexpectedReply, "HTTP #{res.code}") unless res.code == 200
print_status(res.headers['Server'].to_s)print_line(res.body[0, 200])Cookies, Location, JSON, HTML, and XML
Section titled “Cookies, Location, JSON, HTML, and XML”cookies = res.get_cookiesloc = res.redirection if res.redirect?json = res.get_json_documenthtml = res.get_html_documentxml = res.get_xml_documentinputs = res.get_hidden_inputs| Method | Return value |
|---|---|
get_json_document | Parsed JSON value; an empty Hash on a syntax error |
get_html_document | Nokogiri HTML document |
get_xml_document | Nokogiri XML document |
get_hidden_inputs | Array<Hash> containing each form’s hidden fields |
get_cookies | Cookie string built from Set-Cookie |
redirection | URI from the Location header, or nil if unavailable |
title = res.get_html_document.at('title')&.texttoken = res.get_html_document.at_xpath("//input[@name='csrf_token']/@value")&.textsession_id = res.get_hidden_inputs.dig(0, 'sessionid')Checking whether an RCE endpoint succeeded
Section titled “Checking whether an RCE endpoint succeeded”Judge whether execute_command succeeded according to the response the API actually returns.
| Actual response | Example handling |
|---|---|
| Request times out during command execution | Treat res.nil? as success only if asynchronous execution can be confirmed |
HTTP 200 with JSON (such as {"result": ...}) | Check res.code == 200 and get_json_document |
| HTTP 500 HTML error page | Inspect the status code, title, and body |
res = send_request_cgi(...)fail_with(Failure::Unreachable, "#{peer} - no response") if res.nil?json = res.get_json_documentfail_with(Failure::UnexpectedReply, "HTTP #{res.code}") unless res.code == 200 && json.is_a?(Hash) && json.key?('result')get_json_document returns an empty Hash on a JSON syntax error, so check for the expected key too. In this example, HTTP 200 and a result key are the success conditions.
Timeout
Section titled “Timeout”send_request_cgi({ ... }, datastore['HttpClientTimeout'] || 30)For slow uploads or logins, increase the module’s advanced HttpClientTimeout option.
HttpTrace
Section titled “HttpTrace”set HttpTrace trueset HttpTraceHeadersOnly falseset VERBOSE truerunYou can inspect the raw request and response. Be aware that credentials may remain in logs or spool output.
Evasion datastore (reference)
Section titled “Evasion datastore (reference)”These evasion options are usually unnecessary in a normal test environment, but HttpClient provides them:
HTTP::uri_encode_modeHTTP::pad_get_params/HTTP::pad_post_paramsHTTP::shuffle_get_params/HTTP::shuffle_post_paramsHTTP::header_foldingHTTP::method_random_case
Check with show evasion / show advanced.
Related pages
Section titled “Related pages”- Response handling and fail_with
- URI helpers
- Bundled wiki:
docs/metasploit-framework.wiki/How-to-Send-an-HTTP-Request-Using-HttpClient.md - Bundled wiki:
docs/metasploit-framework.wiki/How-to-parse-an-HTTP-response.md

