diff options
Diffstat (limited to 'src/pkg/net/http/cgi')
-rw-r--r-- | src/pkg/net/http/cgi/child.go | 12 | ||||
-rw-r--r-- | src/pkg/net/http/cgi/child_test.go | 24 | ||||
-rw-r--r-- | src/pkg/net/http/cgi/host_test.go | 86 | ||||
-rw-r--r-- | src/pkg/net/http/cgi/plan9_test.go | 18 | ||||
-rw-r--r-- | src/pkg/net/http/cgi/posix_test.go | 21 | ||||
-rwxr-xr-x | src/pkg/net/http/cgi/testdata/test.cgi | 55 |
6 files changed, 131 insertions, 85 deletions
diff --git a/src/pkg/net/http/cgi/child.go b/src/pkg/net/http/cgi/child.go index 1ba7bec5f..100b8b777 100644 --- a/src/pkg/net/http/cgi/child.go +++ b/src/pkg/net/http/cgi/child.go @@ -91,10 +91,19 @@ func RequestFromMap(params map[string]string) (*http.Request, error) { // TODO: cookies. parsing them isn't exported, though. + uriStr := params["REQUEST_URI"] + if uriStr == "" { + // Fallback to SCRIPT_NAME, PATH_INFO and QUERY_STRING. + uriStr = params["SCRIPT_NAME"] + params["PATH_INFO"] + s := params["QUERY_STRING"] + if s != "" { + uriStr += "?" + s + } + } if r.Host != "" { // Hostname is provided, so we can reasonably construct a URL, // even if we have to assume 'http' for the scheme. - rawurl := "http://" + r.Host + params["REQUEST_URI"] + rawurl := "http://" + r.Host + uriStr url, err := url.Parse(rawurl) if err != nil { return nil, errors.New("cgi: failed to parse host and REQUEST_URI into a URL: " + rawurl) @@ -104,7 +113,6 @@ func RequestFromMap(params map[string]string) (*http.Request, error) { // Fallback logic if we don't have a Host header or the URL // failed to parse if r.URL == nil { - uriStr := params["REQUEST_URI"] url, err := url.Parse(uriStr) if err != nil { return nil, errors.New("cgi: failed to parse REQUEST_URI into a URL: " + uriStr) diff --git a/src/pkg/net/http/cgi/child_test.go b/src/pkg/net/http/cgi/child_test.go index ec53ab851..74e068014 100644 --- a/src/pkg/net/http/cgi/child_test.go +++ b/src/pkg/net/http/cgi/child_test.go @@ -82,6 +82,28 @@ func TestRequestWithoutHost(t *testing.T) { t.Fatalf("unexpected nil URL") } if g, e := req.URL.String(), "/path?a=b"; e != g { - t.Errorf("expected URL %q; got %q", e, g) + t.Errorf("URL = %q; want %q", g, e) + } +} + +func TestRequestWithoutRequestURI(t *testing.T) { + env := map[string]string{ + "SERVER_PROTOCOL": "HTTP/1.1", + "HTTP_HOST": "example.com", + "REQUEST_METHOD": "GET", + "SCRIPT_NAME": "/dir/scriptname", + "PATH_INFO": "/p1/p2", + "QUERY_STRING": "a=1&b=2", + "CONTENT_LENGTH": "123", + } + req, err := RequestFromMap(env) + if err != nil { + t.Fatalf("RequestFromMap: %v", err) + } + if req.URL == nil { + t.Fatalf("unexpected nil URL") + } + if g, e := req.URL.String(), "http://example.com/dir/scriptname/p1/p2?a=1&b=2"; e != g { + t.Errorf("URL = %q; want %q", g, e) } } diff --git a/src/pkg/net/http/cgi/host_test.go b/src/pkg/net/http/cgi/host_test.go index 4db3d850c..8c16e6897 100644 --- a/src/pkg/net/http/cgi/host_test.go +++ b/src/pkg/net/http/cgi/host_test.go @@ -19,7 +19,6 @@ import ( "runtime" "strconv" "strings" - "syscall" "testing" "time" ) @@ -63,17 +62,25 @@ readlines: } for key, expected := range expectedMap { - if got := m[key]; got != expected { + got := m[key] + if key == "cwd" { + // For Windows. golang.org/issue/4645. + fi1, _ := os.Stat(got) + fi2, _ := os.Stat(expected) + if os.SameFile(fi1, fi2) { + got = expected + } + } + if got != expected { t.Errorf("for key %q got %q; expected %q", key, got, expected) } } return rw } -var cgiTested = false -var cgiWorks bool +var cgiTested, cgiWorks bool -func skipTest(t *testing.T) bool { +func check(t *testing.T) { if !cgiTested { cgiTested = true cgiWorks = exec.Command("./testdata/test.cgi").Run() == nil @@ -81,16 +88,12 @@ func skipTest(t *testing.T) bool { if !cgiWorks { // No Perl on Windows, needed by test.cgi // TODO: make the child process be Go, not Perl. - t.Logf("Skipping test: test.cgi failed.") - return true + t.Skip("Skipping test: test.cgi failed.") } - return false } func TestCGIBasicGet(t *testing.T) { - if skipTest(t) { - return - } + check(t) h := &Handler{ Path: "testdata/test.cgi", Root: "/test.cgi", @@ -124,9 +127,7 @@ func TestCGIBasicGet(t *testing.T) { } func TestCGIBasicGetAbsPath(t *testing.T) { - if skipTest(t) { - return - } + check(t) pwd, err := os.Getwd() if err != nil { t.Fatalf("getwd error: %v", err) @@ -144,9 +145,7 @@ func TestCGIBasicGetAbsPath(t *testing.T) { } func TestPathInfo(t *testing.T) { - if skipTest(t) { - return - } + check(t) h := &Handler{ Path: "testdata/test.cgi", Root: "/test.cgi", @@ -163,9 +162,7 @@ func TestPathInfo(t *testing.T) { } func TestPathInfoDirRoot(t *testing.T) { - if skipTest(t) { - return - } + check(t) h := &Handler{ Path: "testdata/test.cgi", Root: "/myscript/", @@ -181,9 +178,7 @@ func TestPathInfoDirRoot(t *testing.T) { } func TestDupHeaders(t *testing.T) { - if skipTest(t) { - return - } + check(t) h := &Handler{ Path: "testdata/test.cgi", } @@ -203,9 +198,7 @@ func TestDupHeaders(t *testing.T) { } func TestPathInfoNoRoot(t *testing.T) { - if skipTest(t) { - return - } + check(t) h := &Handler{ Path: "testdata/test.cgi", Root: "", @@ -221,9 +214,7 @@ func TestPathInfoNoRoot(t *testing.T) { } func TestCGIBasicPost(t *testing.T) { - if skipTest(t) { - return - } + check(t) postReq := `POST /test.cgi?a=b HTTP/1.0 Host: example.com Content-Type: application/x-www-form-urlencoded @@ -250,9 +241,7 @@ func chunk(s string) string { // The CGI spec doesn't allow chunked requests. func TestCGIPostChunked(t *testing.T) { - if skipTest(t) { - return - } + check(t) postReq := `POST /test.cgi?a=b HTTP/1.1 Host: example.com Content-Type: application/x-www-form-urlencoded @@ -273,9 +262,7 @@ Transfer-Encoding: chunked } func TestRedirect(t *testing.T) { - if skipTest(t) { - return - } + check(t) h := &Handler{ Path: "testdata/test.cgi", Root: "/test.cgi", @@ -290,9 +277,7 @@ func TestRedirect(t *testing.T) { } func TestInternalRedirect(t *testing.T) { - if skipTest(t) { - return - } + check(t) baseHandler := http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { fmt.Fprintf(rw, "basepath=%s\n", req.URL.Path) fmt.Fprintf(rw, "remoteaddr=%s\n", req.RemoteAddr) @@ -312,8 +297,9 @@ func TestInternalRedirect(t *testing.T) { // TestCopyError tests that we kill the process if there's an error copying // its output. (for example, from the client having gone away) func TestCopyError(t *testing.T) { - if skipTest(t) || runtime.GOOS == "windows" { - return + check(t) + if runtime.GOOS == "windows" { + t.Skipf("skipping test on %q", runtime.GOOS) } h := &Handler{ Path: "testdata/test.cgi", @@ -353,11 +339,7 @@ func TestCopyError(t *testing.T) { } childRunning := func() bool { - p, err := os.FindProcess(pid) - if err != nil { - return false - } - return p.Signal(syscall.Signal(0)) == nil + return isProcessRunning(t, pid) } if !childRunning() { @@ -376,10 +358,10 @@ func TestCopyError(t *testing.T) { } func TestDirUnix(t *testing.T) { - if skipTest(t) || runtime.GOOS == "windows" { - return + check(t) + if runtime.GOOS == "windows" { + t.Skipf("skipping test on %q", runtime.GOOS) } - cwd, _ := os.Getwd() h := &Handler{ Path: "testdata/test.cgi", @@ -404,8 +386,8 @@ func TestDirUnix(t *testing.T) { } func TestDirWindows(t *testing.T) { - if skipTest(t) || runtime.GOOS != "windows" { - return + if runtime.GOOS != "windows" { + t.Skip("Skipping windows specific test.") } cgifile, _ := filepath.Abs("testdata/test.cgi") @@ -414,7 +396,7 @@ func TestDirWindows(t *testing.T) { var err error perl, err = exec.LookPath("perl") if err != nil { - return + t.Skip("Skipping test: perl not found.") } perl, _ = filepath.Abs(perl) @@ -456,7 +438,7 @@ func TestEnvOverride(t *testing.T) { var err error perl, err = exec.LookPath("perl") if err != nil { - return + t.Skipf("Skipping test: perl not found.") } perl, _ = filepath.Abs(perl) diff --git a/src/pkg/net/http/cgi/plan9_test.go b/src/pkg/net/http/cgi/plan9_test.go new file mode 100644 index 000000000..c8235831b --- /dev/null +++ b/src/pkg/net/http/cgi/plan9_test.go @@ -0,0 +1,18 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build plan9 + +package cgi + +import ( + "os" + "strconv" + "testing" +) + +func isProcessRunning(t *testing.T, pid int) bool { + _, err := os.Stat("/proc/" + strconv.Itoa(pid)) + return err == nil +} diff --git a/src/pkg/net/http/cgi/posix_test.go b/src/pkg/net/http/cgi/posix_test.go new file mode 100644 index 000000000..5ff9e7d5e --- /dev/null +++ b/src/pkg/net/http/cgi/posix_test.go @@ -0,0 +1,21 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !plan9 + +package cgi + +import ( + "os" + "syscall" + "testing" +) + +func isProcessRunning(t *testing.T, pid int) bool { + p, err := os.FindProcess(pid) + if err != nil { + return false + } + return p.Signal(syscall.Signal(0)) == nil +} diff --git a/src/pkg/net/http/cgi/testdata/test.cgi b/src/pkg/net/http/cgi/testdata/test.cgi index b46b1330f..3214df6f0 100755 --- a/src/pkg/net/http/cgi/testdata/test.cgi +++ b/src/pkg/net/http/cgi/testdata/test.cgi @@ -8,6 +8,8 @@ use strict; use Cwd; +binmode STDOUT; + my $q = MiniCGI->new; my $params = $q->Vars; @@ -16,51 +18,44 @@ if ($params->{"loc"}) { exit(0); } -my $NL = "\r\n"; -$NL = "\n" if $params->{mode} eq "NL"; - -my $p = sub { - print "$_[0]$NL"; -}; - -# With carriage returns -$p->("Content-Type: text/html"); -$p->("X-CGI-Pid: $$"); -$p->("X-Test-Header: X-Test-Value"); -$p->(""); +print "Content-Type: text/html\r\n"; +print "X-CGI-Pid: $$\r\n"; +print "X-Test-Header: X-Test-Value\r\n"; +print "\r\n"; if ($params->{"bigresponse"}) { - for (1..1024) { - print "A" x 1024, "\n"; + # 17 MB, for OS X: golang.org/issue/4958 + for (1..(17 * 1024)) { + print "A" x 1024, "\r\n"; } exit 0; } -print "test=Hello CGI\n"; +print "test=Hello CGI\r\n"; foreach my $k (sort keys %$params) { - print "param-$k=$params->{$k}\n"; + print "param-$k=$params->{$k}\r\n"; } foreach my $k (sort keys %ENV) { - my $clean_env = $ENV{$k}; - $clean_env =~ s/[\n\r]//g; - print "env-$k=$clean_env\n"; + my $clean_env = $ENV{$k}; + $clean_env =~ s/[\n\r]//g; + print "env-$k=$clean_env\r\n"; } -# NOTE: don't call getcwd() for windows. -# msys return /c/go/src/... not C:\go\... -my $dir; +# NOTE: msys perl returns /c/go/src/... not C:\go\.... +my $dir = getcwd(); if ($^O eq 'MSWin32' || $^O eq 'msys') { - my $cmd = $ENV{'COMSPEC'} || 'c:\\windows\\system32\\cmd.exe'; - $cmd =~ s!\\!/!g; - $dir = `$cmd /c cd`; - chomp $dir; -} else { - $dir = getcwd(); + if ($dir =~ /^.:/) { + $dir =~ s!/!\\!g; + } else { + my $cmd = $ENV{'COMSPEC'} || 'c:\\windows\\system32\\cmd.exe'; + $cmd =~ s!\\!/!g; + $dir = `$cmd /c cd`; + chomp $dir; + } } -print "cwd=$dir\n"; - +print "cwd=$dir\r\n"; # A minimal version of CGI.pm, for people without the perl-modules # package installed. (CGI.pm used to be part of the Perl core, but |