Source file src/net/http/cgi/cgi_main.go

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package cgi
     6  
     7  import (
     8  	"fmt"
     9  	"io"
    10  	"maps"
    11  	"net/http"
    12  	"os"
    13  	"path"
    14  	"slices"
    15  	"strings"
    16  	"time"
    17  )
    18  
    19  func cgiMain() {
    20  	switch path.Join(os.Getenv("SCRIPT_NAME"), os.Getenv("PATH_INFO")) {
    21  	case "/bar", "/test.cgi", "/myscript/bar", "/test.cgi/extrapath":
    22  		testCGI()
    23  		return
    24  	}
    25  	childCGIProcess()
    26  }
    27  
    28  // testCGI is a CGI program translated from a Perl program to complete host_test.
    29  // test cases in host_test should be provided by testCGI.
    30  func testCGI() {
    31  	req, err := Request()
    32  	if err != nil {
    33  		panic(err)
    34  	}
    35  
    36  	err = req.ParseForm()
    37  	if err != nil {
    38  		panic(err)
    39  	}
    40  
    41  	params := req.Form
    42  	if params.Get("loc") != "" {
    43  		fmt.Printf("Location: %s\r\n\r\n", params.Get("loc"))
    44  		return
    45  	}
    46  
    47  	fmt.Printf("Content-Type: text/html\r\n")
    48  	fmt.Printf("X-CGI-Pid: %d\r\n", os.Getpid())
    49  	fmt.Printf("X-Test-Header: X-Test-Value\r\n")
    50  	fmt.Printf("\r\n")
    51  
    52  	if params.Get("writestderr") != "" {
    53  		fmt.Fprintf(os.Stderr, "Hello, stderr!\n")
    54  	}
    55  
    56  	if params.Get("bigresponse") != "" {
    57  		// 17 MB, for OS X: golang.org/issue/4958
    58  		line := strings.Repeat("A", 1024)
    59  		for i := 0; i < 17*1024; i++ {
    60  			fmt.Printf("%s\r\n", line)
    61  		}
    62  		return
    63  	}
    64  
    65  	fmt.Printf("test=Hello CGI\r\n")
    66  
    67  	for _, key := range slices.Sorted(maps.Keys(params)) {
    68  		fmt.Printf("param-%s=%s\r\n", key, params.Get(key))
    69  	}
    70  
    71  	envs := envMap(os.Environ())
    72  	for _, key := range slices.Sorted(maps.Keys(envs)) {
    73  		fmt.Printf("env-%s=%s\r\n", key, envs[key])
    74  	}
    75  
    76  	cwd, _ := os.Getwd()
    77  	fmt.Printf("cwd=%s\r\n", cwd)
    78  }
    79  
    80  type neverEnding byte
    81  
    82  func (b neverEnding) Read(p []byte) (n int, err error) {
    83  	for i := range p {
    84  		p[i] = byte(b)
    85  	}
    86  	return len(p), nil
    87  }
    88  
    89  // childCGIProcess is used by integration_test to complete unit tests.
    90  func childCGIProcess() {
    91  	if os.Getenv("REQUEST_METHOD") == "" {
    92  		// Not in a CGI environment; skipping test.
    93  		return
    94  	}
    95  	switch os.Getenv("REQUEST_URI") {
    96  	case "/immediate-disconnect":
    97  		os.Exit(0)
    98  	case "/no-content-type":
    99  		fmt.Printf("Content-Length: 6\n\nHello\n")
   100  		os.Exit(0)
   101  	case "/empty-headers":
   102  		fmt.Printf("\nHello")
   103  		os.Exit(0)
   104  	}
   105  	Serve(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
   106  		if req.FormValue("nil-request-body") == "1" {
   107  			fmt.Fprintf(rw, "nil-request-body=%v\n", req.Body == nil)
   108  			return
   109  		}
   110  		rw.Header().Set("X-Test-Header", "X-Test-Value")
   111  		req.ParseForm()
   112  		if req.FormValue("no-body") == "1" {
   113  			return
   114  		}
   115  		if eb, ok := req.Form["exact-body"]; ok {
   116  			io.WriteString(rw, eb[0])
   117  			return
   118  		}
   119  		if req.FormValue("write-forever") == "1" {
   120  			io.Copy(rw, neverEnding('a'))
   121  			for {
   122  				time.Sleep(5 * time.Second) // hang forever, until killed
   123  			}
   124  		}
   125  		fmt.Fprintf(rw, "test=Hello CGI-in-CGI\n")
   126  		for k, vv := range req.Form {
   127  			for _, v := range vv {
   128  				fmt.Fprintf(rw, "param-%s=%s\n", k, v)
   129  			}
   130  		}
   131  		for _, kv := range os.Environ() {
   132  			fmt.Fprintf(rw, "env-%s\n", kv)
   133  		}
   134  	}))
   135  	os.Exit(0)
   136  }
   137  

View as plain text