mirror of
https://github.com/golang/go
synced 2024-11-22 04:44:39 -07:00
http: add Date to server, Last-Modified and If-Modified-Since to file server
R=r CC=golang-dev https://golang.org/cl/2051041
This commit is contained in:
parent
5bf658cc8f
commit
8d7ae528bf
@ -13,6 +13,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
"utf8"
|
"utf8"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -61,8 +62,7 @@ func dirList(c *Conn, f *os.File) {
|
|||||||
fmt.Fprintf(c, "</pre>\n")
|
fmt.Fprintf(c, "</pre>\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func serveFile(c *Conn, r *Request, name string, redirect bool) {
|
||||||
func serveFileInternal(c *Conn, r *Request, name string, redirect bool) {
|
|
||||||
const indexPage = "/index.html"
|
const indexPage = "/index.html"
|
||||||
|
|
||||||
// redirect .../index.html to .../
|
// redirect .../index.html to .../
|
||||||
@ -103,6 +103,12 @@ func serveFileInternal(c *Conn, r *Request, name string, redirect bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if t, _ := time.Parse(TimeFormat, r.Header["If-Modified-Since"]); t != nil && d.Mtime_ns/1e9 <= t.Seconds() {
|
||||||
|
c.WriteHeader(StatusNotModified)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.SetHeader("Last-Modified", time.SecondsToUTC(d.Mtime_ns/1e9).Format(TimeFormat))
|
||||||
|
|
||||||
// use contents of index.html for directory, if present
|
// use contents of index.html for directory, if present
|
||||||
if d.IsDirectory() {
|
if d.IsDirectory() {
|
||||||
index := name + indexPage
|
index := name + indexPage
|
||||||
@ -145,7 +151,7 @@ func serveFileInternal(c *Conn, r *Request, name string, redirect bool) {
|
|||||||
|
|
||||||
// ServeFile replies to the request with the contents of the named file or directory.
|
// ServeFile replies to the request with the contents of the named file or directory.
|
||||||
func ServeFile(c *Conn, r *Request, name string) {
|
func ServeFile(c *Conn, r *Request, name string) {
|
||||||
serveFileInternal(c, r, name, false)
|
serveFile(c, r, name, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
type fileHandler struct {
|
type fileHandler struct {
|
||||||
@ -166,5 +172,5 @@ func (f *fileHandler) ServeHTTP(c *Conn, r *Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
path = path[len(f.prefix):]
|
path = path[len(f.prefix):]
|
||||||
serveFileInternal(c, r, f.root+"/"+path, true)
|
serveFile(c, r, f.root+"/"+path, true)
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,12 @@ func (ecr *expectContinueReader) Close() os.Error {
|
|||||||
return ecr.readCloser.Close()
|
return ecr.readCloser.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TimeFormat is the time format to use with
|
||||||
|
// time.Parse and time.Time.Format when parsing
|
||||||
|
// or generating times in HTTP headers.
|
||||||
|
// It is like time.RFC1123 but hard codes GMT as the time zone.
|
||||||
|
const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||||
|
|
||||||
// Read next request from connection.
|
// Read next request from connection.
|
||||||
func (c *Conn) readRequest() (req *Request, err os.Error) {
|
func (c *Conn) readRequest() (req *Request, err os.Error) {
|
||||||
if c.hijacked {
|
if c.hijacked {
|
||||||
@ -124,6 +130,7 @@ func (c *Conn) readRequest() (req *Request, err os.Error) {
|
|||||||
|
|
||||||
// Default output is HTML encoded in UTF-8.
|
// Default output is HTML encoded in UTF-8.
|
||||||
c.SetHeader("Content-Type", "text/html; charset=utf-8")
|
c.SetHeader("Content-Type", "text/html; charset=utf-8")
|
||||||
|
c.SetHeader("Date", time.UTC().Format(TimeFormat))
|
||||||
|
|
||||||
if req.ProtoAtLeast(1, 1) {
|
if req.ProtoAtLeast(1, 1) {
|
||||||
// HTTP/1.1 or greater: use chunked transfer encoding
|
// HTTP/1.1 or greater: use chunked transfer encoding
|
||||||
|
@ -52,25 +52,6 @@ func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) {
|
|||||||
fmt.Fprintf(c, "counter = %d\n", ctr.n)
|
fmt.Fprintf(c, "counter = %d\n", ctr.n)
|
||||||
}
|
}
|
||||||
|
|
||||||
// simple file server
|
|
||||||
var webroot = flag.String("root", "/home/rsc", "web root directory")
|
|
||||||
var pathVar = expvar.NewMap("file-requests")
|
|
||||||
|
|
||||||
func FileServer(c *http.Conn, req *http.Request) {
|
|
||||||
c.SetHeader("content-type", "text/plain; charset=utf-8")
|
|
||||||
pathVar.Add(req.URL.Path, 1)
|
|
||||||
path := *webroot + req.URL.Path // TODO: insecure: use os.CleanName
|
|
||||||
f, err := os.Open(path, os.O_RDONLY, 0)
|
|
||||||
if err != nil {
|
|
||||||
c.WriteHeader(http.StatusNotFound)
|
|
||||||
fmt.Fprintf(c, "open %s: %v\n", path, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n, _ := io.Copy(c, f)
|
|
||||||
fmt.Fprintf(c, "[%d bytes]\n", n)
|
|
||||||
f.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// simple flag server
|
// simple flag server
|
||||||
var booleanflag = flag.Bool("boolean", true, "another flag for testing")
|
var booleanflag = flag.Bool("boolean", true, "another flag for testing")
|
||||||
|
|
||||||
@ -144,6 +125,8 @@ func Logger(c *http.Conn, req *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var webroot = flag.String("root", "/home/rsc", "web root directory")
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@ -153,7 +136,7 @@ func main() {
|
|||||||
expvar.Publish("counter", ctr)
|
expvar.Publish("counter", ctr)
|
||||||
|
|
||||||
http.Handle("/", http.HandlerFunc(Logger))
|
http.Handle("/", http.HandlerFunc(Logger))
|
||||||
http.Handle("/go/", http.HandlerFunc(FileServer))
|
http.Handle("/go/", http.FileServer(*webroot, "/go/"))
|
||||||
http.Handle("/flags", http.HandlerFunc(FlagServer))
|
http.Handle("/flags", http.HandlerFunc(FlagServer))
|
||||||
http.Handle("/args", http.HandlerFunc(ArgServer))
|
http.Handle("/args", http.HandlerFunc(ArgServer))
|
||||||
http.Handle("/go/hello", http.HandlerFunc(HelloServer))
|
http.Handle("/go/hello", http.HandlerFunc(HelloServer))
|
||||||
|
Loading…
Reference in New Issue
Block a user