Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(695)

Side by Side Diff: src/pkg/http/cgi/child.go

Issue 4432079: code review 4432079: cgi: set Request.TLS and Request.RemoteAddr for children (Closed)
Patch Set: diff -r d93b5329ae9f https://go.googlecode.com/hg Created 13 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/pkg/http/cgi/child_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 The Go Authors. All rights reserved. 1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // This file implements CGI from the perspective of a child 5 // This file implements CGI from the perspective of a child
6 // process. 6 // process.
7 7
8 package cgi 8 package cgi
9 9
10 import ( 10 import (
11 "bufio" 11 "bufio"
12 "crypto/tls"
12 "fmt" 13 "fmt"
13 "http" 14 "http"
14 "io" 15 "io"
15 "io/ioutil" 16 "io/ioutil"
17 "net"
16 "os" 18 "os"
17 "strconv" 19 "strconv"
18 "strings" 20 "strings"
19 ) 21 )
20 22
21 // Request returns the HTTP request as represented in the current 23 // Request returns the HTTP request as represented in the current
22 // environment. This assumes the current program is being run 24 // environment. This assumes the current program is being run
23 // by a web server in a CGI environment. 25 // by a web server in a CGI environment.
26 // The returned Request's Body is populated, if applicable.
24 func Request() (*http.Request, os.Error) { 27 func Request() (*http.Request, os.Error) {
25 r, err := RequestFromMap(envMap(os.Environ())) 28 r, err := RequestFromMap(envMap(os.Environ()))
26 if err != nil { 29 if err != nil {
27 return nil, err 30 return nil, err
28 } 31 }
29 if r.ContentLength > 0 { 32 if r.ContentLength > 0 {
30 r.Body = ioutil.NopCloser(io.LimitReader(os.Stdin, r.ContentLeng th)) 33 r.Body = ioutil.NopCloser(io.LimitReader(os.Stdin, r.ContentLeng th))
31 } 34 }
32 return r, nil 35 return r, nil
33 } 36 }
34 37
35 func envMap(env []string) map[string]string { 38 func envMap(env []string) map[string]string {
36 m := make(map[string]string) 39 m := make(map[string]string)
37 for _, kv := range env { 40 for _, kv := range env {
38 if idx := strings.Index(kv, "="); idx != -1 { 41 if idx := strings.Index(kv, "="); idx != -1 {
39 m[kv[:idx]] = kv[idx+1:] 42 m[kv[:idx]] = kv[idx+1:]
40 } 43 }
41 } 44 }
42 return m 45 return m
43 } 46 }
44 47
45 // These environment variables are manually copied into Request 48 // These environment variables are manually copied into Request
46 var skipHeader = map[string]bool{ 49 var skipHeader = map[string]bool{
47 "HTTP_HOST": true, 50 "HTTP_HOST": true,
48 "HTTP_REFERER": true, 51 "HTTP_REFERER": true,
49 "HTTP_USER_AGENT": true, 52 "HTTP_USER_AGENT": true,
50 } 53 }
51 54
52 // RequestFromMap creates an http.Request from CGI variables. 55 // RequestFromMap creates an http.Request from CGI variables.
56 // The returned Request's Body field is not populated.
53 func RequestFromMap(params map[string]string) (*http.Request, os.Error) { 57 func RequestFromMap(params map[string]string) (*http.Request, os.Error) {
54 r := new(http.Request) 58 r := new(http.Request)
55 r.Method = params["REQUEST_METHOD"] 59 r.Method = params["REQUEST_METHOD"]
56 if r.Method == "" { 60 if r.Method == "" {
57 return nil, os.NewError("cgi: no REQUEST_METHOD in environment") 61 return nil, os.NewError("cgi: no REQUEST_METHOD in environment")
58 } 62 }
59 63
60 r.Proto = params["SERVER_PROTOCOL"] 64 r.Proto = params["SERVER_PROTOCOL"]
61 var ok bool 65 var ok bool
62 r.ProtoMajor, r.ProtoMinor, ok = http.ParseHTTPVersion(r.Proto) 66 r.ProtoMajor, r.ProtoMinor, ok = http.ParseHTTPVersion(r.Proto)
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 // Fallback logic if we don't have a Host header or the URL 107 // Fallback logic if we don't have a Host header or the URL
104 // failed to parse 108 // failed to parse
105 if r.URL == nil { 109 if r.URL == nil {
106 r.RawURL = params["REQUEST_URI"] 110 r.RawURL = params["REQUEST_URI"]
107 url, err := http.ParseURL(r.RawURL) 111 url, err := http.ParseURL(r.RawURL)
108 if err != nil { 112 if err != nil {
109 return nil, os.NewError("cgi: failed to parse REQUEST_UR I into a URL: " + r.RawURL) 113 return nil, os.NewError("cgi: failed to parse REQUEST_UR I into a URL: " + r.RawURL)
110 } 114 }
111 r.URL = url 115 r.URL = url
112 } 116 }
117
118 // There's apparently a de-facto standard for this.
119 // http://docstore.mik.ua/orelly/linux/cgi/ch03_02.htm#ch03-35636
120 if s := params["HTTPS"]; s == "on" || s == "ON" || s == "1" {
121 r.TLS = &tls.ConnectionState{HandshakeComplete: true}
122 }
123
124 // Request.RemoteAddr has its port set by Go's standard http
125 // server, so we do here too. We don't have one, though, so we
126 // use a dummy one.
127 r.RemoteAddr = net.JoinHostPort(params["REMOTE_ADDR"], "0")
128
113 return r, nil 129 return r, nil
114 } 130 }
115 131
116 // Serve executes the provided Handler on the currently active CGI 132 // Serve executes the provided Handler on the currently active CGI
117 // request, if any. If there's no current CGI environment 133 // request, if any. If there's no current CGI environment
118 // an error is returned. The provided handler may be nil to use 134 // an error is returned. The provided handler may be nil to use
119 // http.DefaultServeMux. 135 // http.DefaultServeMux.
120 func Serve(handler http.Handler) os.Error { 136 func Serve(handler http.Handler) os.Error {
121 req, err := Request() 137 req, err := Request()
122 if err != nil { 138 if err != nil {
(...skipping 18 matching lines...) Expand all
141 req *http.Request 157 req *http.Request
142 header http.Header 158 header http.Header
143 bufw *bufio.Writer 159 bufw *bufio.Writer
144 headerSent bool 160 headerSent bool
145 } 161 }
146 162
147 func (r *response) Flush() { 163 func (r *response) Flush() {
148 r.bufw.Flush() 164 r.bufw.Flush()
149 } 165 }
150 166
151 func (r *response) RemoteAddr() string {
152 return os.Getenv("REMOTE_ADDR")
153 }
154
155 func (r *response) Header() http.Header { 167 func (r *response) Header() http.Header {
156 return r.header 168 return r.header
157 } 169 }
158 170
159 func (r *response) Write(p []byte) (n int, err os.Error) { 171 func (r *response) Write(p []byte) (n int, err os.Error) {
160 if !r.headerSent { 172 if !r.headerSent {
161 r.WriteHeader(http.StatusOK) 173 r.WriteHeader(http.StatusOK)
162 } 174 }
163 return r.bufw.Write(p) 175 return r.bufw.Write(p)
164 } 176 }
165 177
166 func (r *response) WriteHeader(code int) { 178 func (r *response) WriteHeader(code int) {
167 if r.headerSent { 179 if r.headerSent {
168 // Note: explicitly using Stderr, as Stdout is our HTTP output. 180 // Note: explicitly using Stderr, as Stdout is our HTTP output.
169 fmt.Fprintf(os.Stderr, "CGI attempted to write header twice on r equest for %s", r.req.URL) 181 fmt.Fprintf(os.Stderr, "CGI attempted to write header twice on r equest for %s", r.req.URL)
170 return 182 return
171 } 183 }
172 r.headerSent = true 184 r.headerSent = true
173 fmt.Fprintf(r.bufw, "Status: %d %s\r\n", code, http.StatusText(code)) 185 fmt.Fprintf(r.bufw, "Status: %d %s\r\n", code, http.StatusText(code))
174 186
175 // Set a default Content-Type 187 // Set a default Content-Type
176 if _, hasType := r.header["Content-Type"]; !hasType { 188 if _, hasType := r.header["Content-Type"]; !hasType {
177 r.header.Add("Content-Type", "text/html; charset=utf-8") 189 r.header.Add("Content-Type", "text/html; charset=utf-8")
178 } 190 }
179 191
180 r.header.Write(r.bufw) 192 r.header.Write(r.bufw)
181 r.bufw.WriteString("\r\n") 193 r.bufw.WriteString("\r\n")
182 r.bufw.Flush() 194 r.bufw.Flush()
183 } 195 }
OLDNEW
« no previous file with comments | « no previous file | src/pkg/http/cgi/child_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b