diff --git a/CHANGES b/CHANGES index 40b9f84d04..7554c9fe88 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,9 @@ +2.3-254 | 2014-10-24 11:40:51 -0700 + + * Fix active-http.bro to deal reliably with empty server responses, + which will now be passed back as empty files. (Christian Struck) + 2.3-248 | 2014-10-23 14:20:59 -0700 * Change order in which a plugin's scripts are loaded at startup. diff --git a/VERSION b/VERSION index 762f2d22e9..6bd8c152a6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.3-248 +2.3-254 diff --git a/scripts/base/utils/active-http.bro b/scripts/base/utils/active-http.bro index 9f62e7bbaa..5dc512408a 100644 --- a/scripts/base/utils/active-http.bro +++ b/scripts/base/utils/active-http.bro @@ -65,12 +65,14 @@ function request2curl(r: Request, bodyfile: string, headersfile: string): string cmd = fmt("%s -m %.0f", cmd, r$max_time); if ( r?$client_data ) - cmd = fmt("%s -d -", cmd); + cmd = fmt("%s -d @-", cmd); if ( r?$addl_curl_args ) cmd = fmt("%s %s", cmd, r$addl_curl_args); cmd = fmt("%s \"%s\"", cmd, str_shell_escape(r$url)); + # Make sure file will exist even if curl did not write one. + cmd = fmt("%s && touch %s", cmd, str_shell_escape(bodyfile)); return cmd; } diff --git a/scripts/base/utils/exec.bro b/scripts/base/utils/exec.bro index 12f5a0087b..f38bf82978 100644 --- a/scripts/base/utils/exec.bro +++ b/scripts/base/utils/exec.bro @@ -106,6 +106,15 @@ event Input::end_of_data(name: string, source:string) local track_file = parts[2]; + # If the file is empty, still add it to the result$files table. This is needed + # because it is expected that the file was read even if it was empty. + local result = results[name]; + if ( ! result?$files ) + result$files = table(); + + if ( track_file !in result$files ) + result$files[track_file] = vector(); + Input::remove(name); if ( name !in pending_files ) diff --git a/testing/btest/Baseline/scripts.base.utils.active-http/bro..stdout b/testing/btest/Baseline/scripts.base.utils.active-http/bro..stdout index 0284eb19b3..eac07da9a8 100644 --- a/testing/btest/Baseline/scripts.base.utils.active-http/bro..stdout +++ b/testing/btest/Baseline/scripts.base.utils.active-http/bro..stdout @@ -1,4 +1,9 @@ -[code=200, msg=OK^M, body=It works!, headers={ +test1, [code=200, msg=OK^M, body=It works!, headers={ +[Server] = 1.0, +[Content-type] = text/plain, +[Date] = July 22, 2013 +}] +test2, [code=200, msg=OK^M, body=, headers={ [Server] = 1.0, [Content-type] = text/plain, [Date] = July 22, 2013 diff --git a/testing/btest/Baseline/scripts.base.utils.exec/bro..stdout b/testing/btest/Baseline/scripts.base.utils.exec/bro..stdout index 3cfdaafb4c..043e1d4baa 100644 --- a/testing/btest/Baseline/scripts.base.utils.exec/bro..stdout +++ b/testing/btest/Baseline/scripts.base.utils.exec/bro..stdout @@ -1,6 +1,10 @@ +test2, [exit_code=1, signal_exit=F, stdout=[here's something on stdout, some more stdout, last stdout], stderr=[and some stderr, more stderr, last stderr], files=] test1, [exit_code=0, signal_exit=F, stdout=[done, exit, stop], stderr=, files={ [out1] = [insert text here, and here], [out2] = [insert more text here, and there] }] -test2, [exit_code=1, signal_exit=F, stdout=[here's something on stdout, some more stdout, last stdout], stderr=[and some stderr, more stderr, last stderr], files=] test4, [exit_code=0, signal_exit=F, stdout=[hibye], stderr=, files=] +test5, [exit_code=0, signal_exit=F, stdout=, stderr=, files={ +[out4] = [test], +[out3] = [] +}] diff --git a/testing/btest/scripts/base/utils/active-http.test b/testing/btest/scripts/base/utils/active-http.test index 442d5b9e06..b910ea1c7e 100644 --- a/testing/btest/scripts/base/utils/active-http.test +++ b/testing/btest/scripts/base/utils/active-http.test @@ -1,7 +1,7 @@ # @TEST-REQUIRES: which python # @TEST-REQUIRES: which curl # -# @TEST-EXEC: btest-bg-run httpd python $SCRIPTS/httpd.py --max 1 --addr=127.0.0.1 +# @TEST-EXEC: btest-bg-run httpd python $SCRIPTS/httpd.py --max 2 --addr=127.0.0.1 # @TEST-EXEC: sleep 3 # @TEST-EXEC: btest-bg-run bro bro -b %INPUT # @TEST-EXEC: btest-bg-wait 15 @@ -11,18 +11,32 @@ @load base/frameworks/communication # let network-time run. otherwise there are no heartbeats... redef exit_only_after_terminate = T; -event bro_init() - { - local req = ActiveHTTP::Request($url="127.0.0.1:32123"); +global c: count = 0; - when ( local resp = ActiveHTTP::request(req) ) - { - print resp; +function check_exit_condition() + { + c += 1; + + if ( c == 2 ) terminate(); + } + +function test_request(label: string, req: ActiveHTTP::Request) + { + when ( local response = ActiveHTTP::request(req) ) + { + print label, response; + check_exit_condition(); } timeout 1min { print "HTTP request timeout"; - terminate(); + check_exit_condition(); } } + +event bro_init() + { + test_request("test1", [$url="127.0.0.1:32123"]); + test_request("test2", [$url="127.0.0.1:32123/empty", $method="POST"]); + } diff --git a/testing/btest/scripts/base/utils/exec.test b/testing/btest/scripts/base/utils/exec.test index 33ba10f97a..389527bcfc 100644 --- a/testing/btest/scripts/base/utils/exec.test +++ b/testing/btest/scripts/base/utils/exec.test @@ -14,7 +14,7 @@ function check_exit_condition() { c += 1; - if ( c == 3 ) + if ( c == 4 ) terminate(); } @@ -35,6 +35,8 @@ event bro_init() # Not sure of a portable way to test signals yet. #test_cmd("test3", [$cmd="bash ../suicide.sh"]); test_cmd("test4", [$cmd="bash ../stdin.sh", $stdin="hibye"]); + test_cmd("test5", [$cmd="bash ../empty_file.sh", + $read_files=set("out3", "out4")]); } @TEST-END-FILE @@ -73,3 +75,9 @@ echo "nope" read -r line echo "$line" @TEST-END-FILE + +@TEST-START-FILE empty_file.sh +#! /usr/bin/env bash +touch out3 +echo "test" > out4 +@TEST-END-FILE diff --git a/testing/scripts/httpd.py b/testing/scripts/httpd.py index 0732614bc2..feafa70d56 100755 --- a/testing/scripts/httpd.py +++ b/testing/scripts/httpd.py @@ -2,13 +2,28 @@ import BaseHTTPServer + class MyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header("Content-type", "text/plain") self.end_headers() - self.wfile.write("It works!") + + if "/empty" in self.path: + self.wfile.write("") + else: + self.wfile.write("It works!") + + def do_POST(self): + self.send_response(200) + self.send_header("Content-type", "text/plain") + self.end_headers() + + if "/empty" in self.path: + self.wfile.write("") + else: + self.wfile.write("It works!") def version_string(self): return "1.0"