summaryrefslogtreecommitdiff
path: root/src/pkg/http/cgi
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-07-08 09:16:22 +0200
committerOndřej Surý <ondrej@sury.org>2011-07-08 09:52:32 +0200
commit85cafef129c3826b0c5e290c89cfc7251fba43d5 (patch)
treee59b124753eb1eec194ec682a7815c401388f10d /src/pkg/http/cgi
parent67c487c4bd0fc91c2ce5972886d108e0d2939064 (diff)
downloadgolang-85cafef129c3826b0c5e290c89cfc7251fba43d5.tar.gz
Imported Upstream version 2011.07.07
Diffstat (limited to 'src/pkg/http/cgi')
-rw-r--r--src/pkg/http/cgi/host.go26
-rw-r--r--src/pkg/http/cgi/host_test.go78
-rwxr-xr-xsrc/pkg/http/cgi/testdata/test.cgi51
3 files changed, 145 insertions, 10 deletions
diff --git a/src/pkg/http/cgi/host.go b/src/pkg/http/cgi/host.go
index 2be3ede77..059fc758e 100644
--- a/src/pkg/http/cgi/host.go
+++ b/src/pkg/http/cgi/host.go
@@ -46,6 +46,12 @@ type Handler struct {
Path string // path to the CGI executable
Root string // root URI prefix of handler or empty for "/"
+ // Dir specifies the CGI executable's working directory.
+ // If Dir is empty, the base directory of Path is used.
+ // If Path has no base directory, the current working
+ // directory is used.
+ Dir string
+
Env []string // extra environment variables to set, if any, as "key=value"
InheritEnv []string // environment variables to inherit from host, as "key"
Logger *log.Logger // optional log for errors or nil to use log.Print
@@ -125,11 +131,11 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
env = append(env, h.Env...)
}
- path := os.Getenv("PATH")
- if path == "" {
- path = "/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin"
+ envPath := os.Getenv("PATH")
+ if envPath == "" {
+ envPath = "/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin"
}
- env = append(env, "PATH="+path)
+ env = append(env, "PATH="+envPath)
for _, e := range h.InheritEnv {
if v := os.Getenv(e); v != "" {
@@ -143,7 +149,13 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
}
}
- cwd, pathBase := filepath.Split(h.Path)
+ var cwd, path string
+ if h.Dir != "" {
+ path = h.Path
+ cwd = h.Dir
+ } else {
+ cwd, path = filepath.Split(h.Path)
+ }
if cwd == "" {
cwd = "."
}
@@ -154,7 +166,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
}
cmd := &exec.Cmd{
- Path: pathBase,
+ Path: path,
Args: append([]string{h.Path}, h.Args...),
Dir: cwd,
Env: env,
@@ -197,7 +209,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
if len(line) == 0 {
break
}
- parts := strings.Split(string(line), ":", 2)
+ parts := strings.SplitN(string(line), ":", 2)
if len(parts) < 2 {
h.printf("cgi: bogus header line: %s", string(line))
continue
diff --git a/src/pkg/http/cgi/host_test.go b/src/pkg/http/cgi/host_test.go
index bbdb715cf..b08d8bbf6 100644
--- a/src/pkg/http/cgi/host_test.go
+++ b/src/pkg/http/cgi/host_test.go
@@ -13,8 +13,10 @@ import (
"http"
"http/httptest"
"os"
+ "path/filepath"
"strings"
"testing"
+ "runtime"
)
func newRequest(httpreq string) *http.Request {
@@ -46,7 +48,7 @@ readlines:
}
linesRead++
trimmedLine := strings.TrimRight(line, "\r\n")
- split := strings.Split(trimmedLine, "=", 2)
+ split := strings.SplitN(trimmedLine, "=", 2)
if len(split) != 2 {
t.Fatalf("Unexpected %d parts from invalid line number %v: %q; existing map=%v",
len(split), linesRead, line, m)
@@ -301,3 +303,77 @@ func TestInternalRedirect(t *testing.T) {
}
runCgiTest(t, h, "GET /test.cgi?loc=/foo HTTP/1.0\nHost: example.com\n\n", expectedMap)
}
+
+func TestDirUnix(t *testing.T) {
+ if runtime.GOOS == "windows" {
+ return
+ }
+
+ cwd, _ := os.Getwd()
+ h := &Handler{
+ Path: "testdata/test.cgi",
+ Root: "/test.cgi",
+ Dir: cwd,
+ }
+ expectedMap := map[string]string{
+ "cwd": cwd,
+ }
+ runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+
+ cwd, _ = os.Getwd()
+ cwd = filepath.Join(cwd, "testdata")
+ h = &Handler{
+ Path: "testdata/test.cgi",
+ Root: "/test.cgi",
+ }
+ expectedMap = map[string]string{
+ "cwd": cwd,
+ }
+ runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
+
+func TestDirWindows(t *testing.T) {
+ if runtime.GOOS != "windows" {
+ return
+ }
+
+ cgifile, _ := filepath.Abs("testdata/test.cgi")
+
+ var perl string
+ var err os.Error
+ perl, err = exec.LookPath("perl")
+ if err != nil {
+ return
+ }
+ perl, _ = filepath.Abs(perl)
+
+ cwd, _ := os.Getwd()
+ h := &Handler{
+ Path: perl,
+ Root: "/test.cgi",
+ Dir: cwd,
+ Args: []string{cgifile},
+ Env: []string{"SCRIPT_FILENAME=" + cgifile},
+ }
+ expectedMap := map[string]string{
+ "cwd": cwd,
+ }
+ runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+
+ // If not specify Dir on windows, working directory should be
+ // base directory of perl.
+ cwd, _ = filepath.Split(perl)
+ if cwd != "" && cwd[len(cwd)-1] == filepath.Separator {
+ cwd = cwd[:len(cwd)-1]
+ }
+ h = &Handler{
+ Path: perl,
+ Root: "/test.cgi",
+ Args: []string{cgifile},
+ Env: []string{"SCRIPT_FILENAME=" + cgifile},
+ }
+ expectedMap = map[string]string{
+ "cwd": cwd,
+ }
+ runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}
diff --git a/src/pkg/http/cgi/testdata/test.cgi b/src/pkg/http/cgi/testdata/test.cgi
index a1b2ff893..36c107f76 100755
--- a/src/pkg/http/cgi/testdata/test.cgi
+++ b/src/pkg/http/cgi/testdata/test.cgi
@@ -6,9 +6,9 @@
# Test script run as a child process under cgi_test.go
use strict;
-use CGI;
+use Cwd;
-my $q = CGI->new;
+my $q = MiniCGI->new;
my $params = $q->Vars;
if ($params->{"loc"}) {
@@ -39,3 +39,50 @@ foreach my $k (sort keys %ENV) {
$clean_env =~ s/[\n\r]//g;
print "env-$k=$clean_env\n";
}
+
+# NOTE: don't call getcwd() for windows.
+# msys return /c/go/src/... not C:\go\...
+my $dir;
+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();
+}
+print "cwd=$dir\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
+# some distros now bundle perl-base and perl-modules separately...)
+package MiniCGI;
+
+sub new {
+ my $class = shift;
+ return bless {}, $class;
+}
+
+sub Vars {
+ my $self = shift;
+ my $pairs;
+ if ($ENV{CONTENT_LENGTH}) {
+ $pairs = do { local $/; <STDIN> };
+ } else {
+ $pairs = $ENV{QUERY_STRING};
+ }
+ my $vars = {};
+ foreach my $kv (split(/&/, $pairs)) {
+ my ($k, $v) = split(/=/, $kv, 2);
+ $vars->{_urldecode($k)} = _urldecode($v);
+ }
+ return $vars;
+}
+
+sub _urldecode {
+ my $v = shift;
+ $v =~ tr/+/ /;
+ $v =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
+ return $v;
+}