]> Cypherpunks repositories - gostls13.git/commitdiff
http/cgi: add Handler.Dir to specify working directory
authorYasuhiro Matsumoto <mattn.jp@gmail.com>
Thu, 30 Jun 2011 16:44:23 +0000 (09:44 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Thu, 30 Jun 2011 16:44:23 +0000 (09:44 -0700)
R=golang-dev, bradfitz, alex.brainman
CC=golang-dev
https://golang.org/cl/4635042

src/pkg/http/cgi/host.go
src/pkg/http/cgi/host_test.go
src/pkg/http/cgi/testdata/test.cgi

index 01a941650bd34886127170adeb833a809f7b19f4..059fc758e360949b9bef9b9e8bca92e848de01b9 100644 (file)
@@ -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,
index 3b9dad5c0c584f8471264338f2986f39af8d5628..b08d8bbf6878cd2559648c50134bf60d729804cc 100644 (file)
@@ -13,8 +13,10 @@ import (
        "http"
        "http/httptest"
        "os"
+       "path/filepath"
        "strings"
        "testing"
+       "runtime"
 )
 
 func newRequest(httpreq string) *http.Request {
@@ -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)
+}
index a1b2ff893dc5579144ba82f196c8a668ddd81795..47798907034c919ef9a03db91dcce3644f3e0a26 100755 (executable)
@@ -7,6 +7,7 @@
 
 use strict;
 use CGI;
+use Cwd;
 
 my $q = CGI->new;
 my $params = $q->Vars;
@@ -39,3 +40,16 @@ 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";