]> Cypherpunks repositories - gostls13.git/commitdiff
http/cgi: clean up environment.
authorYasuhiro Matsumoto <mattn.jp@gmail.com>
Fri, 16 Sep 2011 17:36:54 +0000 (10:36 -0700)
committerBrad Fitzpatrick <bradfitz@golang.org>
Fri, 16 Sep 2011 17:36:54 +0000 (10:36 -0700)
clean up duplicate environment for CGI.
overriding former by latter.
On windows, When there are duplicated environments like following,

SCRIPT_FILENAME=c:/progra~1/php/php-cgi.exe
SCRIPT_FILENAME=/foo.php

CreateProcess use first entry.

If make cgi.Handle like following,

        cgih = cgi.Handler{
                Path: "c:/strawberry/perl/bin/perl.exe",
                Dir:  "c:/path/to/webroot",
                Root: "c:/path/to/webroot",
                Args: []string{"foo.php"},
                Env:  []string{"SCRIPT_FILENAME=foo.php"},
        }

http/cgi should behave "SCRIPT_FILENAME is foo.php".
But currently, http/cgi is set duplicate environment entries.
So, browser show binary dump of "php-cgi.exe" that is specified indented
SCRIPT_FILENAME in first entry.
This change clean up duplicates, and use latters.

R=golang-dev, bradfitz, bradfitz
CC=golang-dev
https://golang.org/cl/5010044

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

index bcd1477034f6d6c55d3e62587c82e02f6012a180..1d63821416ddd0e125248f460d50571321e55ff6 100644 (file)
@@ -69,6 +69,31 @@ type Handler struct {
        PathLocationHandler http.Handler
 }
 
+// removeLeadingDuplicates remove leading duplicate in environments.
+// It's possible to override environment like following.
+//    cgi.Handler{
+//      ...
+//      Env: []string{"SCRIPT_FILENAME=foo.php"},
+//    }
+func removeLeadingDuplicates(env []string) (ret []string) {
+       n := len(env)
+       for i := 0; i < n; i++ {
+               e := env[i]
+               s := strings.SplitN(e, "=", 2)[0]
+               found := false
+               for j := i + 1; j < n; j++ {
+                       if s == strings.SplitN(env[j], "=", 2)[0] {
+                               found = true
+                               break
+                       }
+               }
+               if !found {
+                       ret = append(ret, e)
+               }
+       }
+       return
+}
+
 func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
        root := h.Root
        if root == "" {
@@ -150,6 +175,8 @@ func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
                }
        }
 
+       env = removeLeadingDuplicates(env)
+
        var cwd, path string
        if h.Dir != "" {
                path = h.Path
index 1dc3abdbb32d5fce6de3777a74d3cc02f83fcf65..8111ba19e3089db24f8ab80f8936783eacd2b0b9 100644 (file)
@@ -447,3 +447,32 @@ func TestDirWindows(t *testing.T) {
        }
        runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
 }
+
+func TestEnvOverride(t *testing.T) {
+       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,
+                       "REQUEST_URI=/foo/bar"},
+       }
+       expectedMap := map[string]string{
+               "cwd": cwd,
+               "env-SCRIPT_FILENAME": cgifile,
+               "env-REQUEST_URI":     "/foo/bar",
+       }
+       runCgiTest(t, h, "GET /test.cgi HTTP/1.0\nHost: example.com\n\n", expectedMap)
+}