summaryrefslogtreecommitdiff
path: root/src/pkg/net/http/cgi
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/net/http/cgi')
-rw-r--r--src/pkg/net/http/cgi/child.go12
-rw-r--r--src/pkg/net/http/cgi/child_test.go24
-rw-r--r--src/pkg/net/http/cgi/host_test.go86
-rw-r--r--src/pkg/net/http/cgi/plan9_test.go18
-rw-r--r--src/pkg/net/http/cgi/posix_test.go21
-rwxr-xr-xsrc/pkg/net/http/cgi/testdata/test.cgi55
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