Commit 2f9fbad0 authored by Yasuhiro Matsumoto's avatar Yasuhiro Matsumoto Committed by Brad Fitzpatrick

http/cgi: add Handler.Dir to specify working directory

R=golang-dev, bradfitz, alex.brainman
CC=golang-dev
https://golang.org/cl/4635042
parent dd2074c8
...@@ -46,6 +46,12 @@ type Handler struct { ...@@ -46,6 +46,12 @@ type Handler struct {
Path string // path to the CGI executable Path string // path to the CGI executable
Root string // root URI prefix of handler or empty for "/" 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" Env []string // extra environment variables to set, if any, as "key=value"
InheritEnv []string // environment variables to inherit from host, as "key" InheritEnv []string // environment variables to inherit from host, as "key"
Logger *log.Logger // optional log for errors or nil to use log.Print 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) { ...@@ -125,11 +131,11 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
env = append(env, h.Env...) env = append(env, h.Env...)
} }
path := os.Getenv("PATH") envPath := os.Getenv("PATH")
if path == "" { if envPath == "" {
path = "/bin:/usr/bin:/usr/ucb:/usr/bsd:/usr/local/bin" 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 { for _, e := range h.InheritEnv {
if v := os.Getenv(e); v != "" { if v := os.Getenv(e); v != "" {
...@@ -143,7 +149,13 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { ...@@ -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 == "" { if cwd == "" {
cwd = "." cwd = "."
} }
...@@ -154,7 +166,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { ...@@ -154,7 +166,7 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
} }
cmd := &exec.Cmd{ cmd := &exec.Cmd{
Path: pathBase, Path: path,
Args: append([]string{h.Path}, h.Args...), Args: append([]string{h.Path}, h.Args...),
Dir: cwd, Dir: cwd,
Env: env, Env: env,
......
...@@ -13,8 +13,10 @@ import ( ...@@ -13,8 +13,10 @@ import (
"http" "http"
"http/httptest" "http/httptest"
"os" "os"
"path/filepath"
"strings" "strings"
"testing" "testing"
"runtime"
) )
func newRequest(httpreq string) *http.Request { func newRequest(httpreq string) *http.Request {
...@@ -301,3 +303,77 @@ func TestInternalRedirect(t *testing.T) { ...@@ -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) 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)
}
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
use strict; use strict;
use CGI; use CGI;
use Cwd;
my $q = CGI->new; my $q = CGI->new;
my $params = $q->Vars; my $params = $q->Vars;
...@@ -39,3 +40,16 @@ foreach my $k (sort keys %ENV) { ...@@ -39,3 +40,16 @@ foreach my $k (sort keys %ENV) {
$clean_env =~ s/[\n\r]//g; $clean_env =~ s/[\n\r]//g;
print "env-$k=$clean_env\n"; 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";
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment