mirror of https://github.com/perkeep/perkeep.git
Updates to latest Go language + library changes.
This commit is contained in:
parent
3edbfd3f26
commit
f70cc6d2e5
|
@ -80,7 +80,7 @@ func handleEnumerateBlobs(conn http.ResponseWriter, req *http.Request, storage b
|
|||
}
|
||||
}
|
||||
|
||||
conn.SetHeader("Content-Type", "text/javascript; charset=utf-8")
|
||||
conn.Header().Set("Content-Type", "text/javascript; charset=utf-8")
|
||||
fmt.Fprintf(conn, "{\n \"blobs\": [\n")
|
||||
|
||||
blobch := make(chan *blobref.SizedBlobRef, 100)
|
||||
|
|
|
@ -131,12 +131,12 @@ func serveBlobRef(conn http.ResponseWriter, req *http.Request,
|
|||
}
|
||||
input = bufReader
|
||||
|
||||
conn.SetHeader("Content-Length", strconv.Itoa64(size))
|
||||
conn.Header().Set("Content-Length", strconv.Itoa64(size))
|
||||
}
|
||||
|
||||
conn.SetHeader("Content-Type", contentType)
|
||||
conn.Header().Set("Content-Type", contentType)
|
||||
if !reqRange.IsWholeFile() {
|
||||
conn.SetHeader("Content-Range",
|
||||
conn.Header().Set("Content-Range",
|
||||
fmt.Sprintf("bytes %d-%d/%d", reqRange.SkipBytes(),
|
||||
reqRange.SkipBytes()+remainBytes,
|
||||
size))
|
||||
|
|
|
@ -34,8 +34,9 @@ func (cp *chanPeeker) Peek() *blobref.SizedBlobRef {
|
|||
if cp.peek != nil {
|
||||
return cp.peek
|
||||
}
|
||||
cp.peek = <-cp.ch
|
||||
if closed(cp.ch) {
|
||||
var ok bool
|
||||
cp.peek, ok = <-cp.ch
|
||||
if !ok {
|
||||
cp.Closed = true
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ func RequireAuth(handler func(conn http.ResponseWriter, req *http.Request)) func
|
|||
return func (conn http.ResponseWriter, req *http.Request) {
|
||||
if !IsAuthorized(req) {
|
||||
req.Body.Close() // http://code.google.com/p/go/issues/detail?id=1306
|
||||
conn.SetHeader("WWW-Authenticate", "Basic realm=\"camlistored\"")
|
||||
conn.Header().Set("WWW-Authenticate", "Basic realm=\"camlistored\"")
|
||||
conn.WriteHeader(http.StatusUnauthorized)
|
||||
fmt.Fprintf(conn, "Authentication required.\n")
|
||||
return
|
||||
|
|
|
@ -36,7 +36,7 @@ func ServerError(conn http.ResponseWriter, err os.Error) {
|
|||
}
|
||||
|
||||
func ReturnJson(conn http.ResponseWriter, data interface{}) {
|
||||
conn.SetHeader("Content-Type", "text/javascript")
|
||||
conn.Header().Set("Content-Type", "text/javascript")
|
||||
bytes, err := json.MarshalIndent(data, "", " ")
|
||||
if err != nil {
|
||||
BadRequestError(conn, fmt.Sprintf(
|
||||
|
|
|
@ -3,7 +3,6 @@ include $(GOROOT)/src/Make.inc
|
|||
TARG=camweb
|
||||
GOFILES=\
|
||||
camweb.go\
|
||||
cgi.go\
|
||||
logging.go\
|
||||
|
||||
include $(GOROOT)/src/Make.cmd
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"http"
|
||||
"http/cgi"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
@ -41,7 +42,7 @@ var (
|
|||
root = flag.String("root", "", "Website root (parent of 'static', 'content', and 'tmpl")
|
||||
gitwebScript = flag.String("gitwebscript", "/usr/lib/cgi-bin/gitweb.cgi", "Path to gitweb.cgi, or blank to disable.")
|
||||
gitwebFiles = flag.String("gitwebfiles", "/usr/share/gitweb", "Path to gitweb's static files.")
|
||||
logDir = flag.String("logdir", "-", "Directory to write log files to (one per hour), or empty to not log.")
|
||||
logDir = flag.String("logdir", "", "Directory to write log files to (one per hour), or empty to not log.")
|
||||
logStdout = flag.Bool("logstdout", true, "Write to stdout?")
|
||||
pageHtml, errorHtml *template.Template
|
||||
)
|
||||
|
@ -241,7 +242,7 @@ func main() {
|
|||
mux.Handle("/robots.txt", http.FileServer(path.Join(*root, "static"), "/"))
|
||||
mux.Handle("/static/", http.FileServer(path.Join(*root, "static"), "/static/"))
|
||||
|
||||
testCgi := &CgiHandler{ExecutablePath: path.Join(*root, "test.cgi"),
|
||||
testCgi := &cgi.Handler{Path: path.Join(*root, "test.cgi"),
|
||||
Root: "/test.cgi",
|
||||
}
|
||||
mux.Handle("/test.cgi", testCgi)
|
||||
|
@ -253,10 +254,10 @@ func main() {
|
|||
env = append(env, "GITWEB_CONFIG="+path.Join(*root, "gitweb-camli.conf"))
|
||||
env = append(env, "CAMWEB_ROOT="+path.Join(*root))
|
||||
mux.Handle("/code/", &fixUpGitwebUrls{&gitwebHandler{
|
||||
Cgi: &CgiHandler{
|
||||
ExecutablePath: *gitwebScript,
|
||||
Cgi: &cgi.Handler{
|
||||
Path: *gitwebScript,
|
||||
Root: "/code/",
|
||||
Environ: env,
|
||||
Env: env,
|
||||
},
|
||||
Static: http.FileServer(*gitwebFiles, "/code/"),
|
||||
}})
|
||||
|
|
187
website/cgi.go
187
website/cgi.go
|
@ -1,187 +0,0 @@
|
|||
/*
|
||||
Copyright 2011 Google Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
// Package cgi implements a CGI (Common Gateway Interface) HTTP handler as specified
|
||||
// in RFC 3875. Using CGI isn't usually incredibly efficient and this package
|
||||
// is intended primarily for compatibility.
|
||||
|
||||
import (
|
||||
"encoding/line"
|
||||
"exec"
|
||||
"fmt"
|
||||
"http"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var trailingPort = regexp.MustCompile(`:([0-9]+)$`)
|
||||
|
||||
type CgiHandler struct {
|
||||
ExecutablePath string
|
||||
Root string // empty is "/"; otherwise must start with "/"
|
||||
Environ []string
|
||||
// TODO: custom log.Logger
|
||||
}
|
||||
|
||||
func (h *CgiHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
pathInfo := req.URL.Path
|
||||
if strings.HasPrefix(pathInfo, h.Root) {
|
||||
pathInfo = pathInfo[len(h.Root):]
|
||||
}
|
||||
|
||||
port := "80"
|
||||
if matches := trailingPort.FindStringSubmatch(req.Host); len(matches) != 0 {
|
||||
port = matches[1]
|
||||
}
|
||||
|
||||
env := []string{
|
||||
"SERVER_SOFTWARE=golang",
|
||||
"SERVER_NAME=" + req.Host,
|
||||
"HTTP_HOST=" + req.Host,
|
||||
"GATEWAY_INTERFACE=CGI/1.1",
|
||||
"REQUEST_METHOD=" + req.Method,
|
||||
"QUERY_STRING=" + req.URL.RawQuery,
|
||||
"REQUEST_URI=" + req.URL.RawPath,
|
||||
"PATH_INFO=" + pathInfo,
|
||||
"SCRIPT_NAME=" + h.Root,
|
||||
"SCRIPT_FILENAME=" + h.ExecutablePath,
|
||||
"REMOTE_ADDR=0.0.0.0", // TODO
|
||||
"REMOTE_HOST=", // TODO
|
||||
"SERVER_PORT=" + port,
|
||||
}
|
||||
|
||||
for k, _ := range req.Header {
|
||||
k = strings.Map(upperCaseAndUnderscore, k)
|
||||
env = append(env, "HTTP_"+k+"="+req.Header.Get(k))
|
||||
}
|
||||
|
||||
if req.ContentLength > 0 {
|
||||
env = append(env, fmt.Sprintf("CONTENT_LENGTH=%d", req.ContentLength))
|
||||
}
|
||||
if ctype := req.Header.Get("Content-Type"); ctype != "" {
|
||||
env = append(env, "CONTENT_TYPE="+ctype)
|
||||
}
|
||||
|
||||
if h.Environ != nil {
|
||||
env = append(env, h.Environ...)
|
||||
}
|
||||
|
||||
cwd := h.ExecutablePath
|
||||
if slash := strings.LastIndex(cwd, "/"); slash != -1 {
|
||||
cwd = cwd[0:slash]
|
||||
}
|
||||
if !strings.HasPrefix(cwd, "/") {
|
||||
cwd = "."
|
||||
}
|
||||
|
||||
cmd, err := exec.Run(
|
||||
h.ExecutablePath,
|
||||
[]string{h.ExecutablePath},
|
||||
env,
|
||||
cwd,
|
||||
exec.Pipe, // stdin
|
||||
exec.Pipe, // stdout
|
||||
exec.PassThrough, // stderr (for now)
|
||||
)
|
||||
if err != nil {
|
||||
rw.WriteHeader(http.StatusInternalServerError)
|
||||
log.Printf("CGI error: %v", err)
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
cmd.Stdin.Close()
|
||||
cmd.Stdout.Close()
|
||||
cmd.Wait(0) // no zombies
|
||||
}()
|
||||
|
||||
if req.ContentLength != 0 {
|
||||
go func() {
|
||||
io.Copy(cmd.Stdin, req.Body)
|
||||
}()
|
||||
}
|
||||
|
||||
linebody := line.NewReader(cmd.Stdout, 1024)
|
||||
headers := make(map[string]string)
|
||||
statusCode := http.StatusOK
|
||||
for {
|
||||
line, isPrefix, err := linebody.ReadLine()
|
||||
if isPrefix {
|
||||
rw.WriteHeader(http.StatusInternalServerError)
|
||||
log.Printf("CGI: long header line from subprocess.")
|
||||
return
|
||||
}
|
||||
if err == os.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
rw.WriteHeader(http.StatusInternalServerError)
|
||||
log.Printf("CGI: error reading headers: %v", err)
|
||||
return
|
||||
}
|
||||
if len(line) == 0 {
|
||||
break
|
||||
}
|
||||
parts := strings.Split(string(line), ":", 2)
|
||||
if len(parts) < 2 {
|
||||
log.Printf("CGI: bogus header line: %s", string(line))
|
||||
continue
|
||||
}
|
||||
h, v := parts[0], parts[1]
|
||||
h = strings.TrimSpace(h)
|
||||
v = strings.TrimSpace(v)
|
||||
switch {
|
||||
case h == "Status":
|
||||
if len(v) < 3 {
|
||||
log.Printf("CGI: bogus status (short): %q", v)
|
||||
return
|
||||
}
|
||||
code, err := strconv.Atoi(v[0:3])
|
||||
if err != nil {
|
||||
log.Printf("CGI: bogus status: %q", v)
|
||||
log.Printf("CGI: line was %q", line)
|
||||
return
|
||||
}
|
||||
statusCode = code
|
||||
default:
|
||||
headers[h] = v
|
||||
}
|
||||
}
|
||||
for h, v := range headers {
|
||||
rw.SetHeader(h, v)
|
||||
}
|
||||
rw.WriteHeader(statusCode)
|
||||
|
||||
_, err = io.Copy(rw, linebody)
|
||||
if err != nil {
|
||||
log.Printf("CGI: copy error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func upperCaseAndUnderscore(rune int) int {
|
||||
switch {
|
||||
case rune >= 'a' && rune <= 'z':
|
||||
return rune - ('a' - 'A')
|
||||
case rune == '-':
|
||||
return '_'
|
||||
}
|
||||
return rune
|
||||
}
|
|
@ -41,7 +41,7 @@ func NewLoggingHandler(handler http.Handler, dir string, writeStdout bool) http.
|
|||
|
||||
func (h *logHandler) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
|
||||
// Strip port number from address
|
||||
addr := rw.RemoteAddr()
|
||||
addr := r.RemoteAddr
|
||||
if colon := strings.LastIndex(addr, ":"); colon != -1 {
|
||||
addr = addr[:colon]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue