]> Cypherpunks repositories - gostls13.git/commitdiff
http: add Date to server, Last-Modified and If-Modified-Since to file server
authorRuss Cox <rsc@golang.org>
Thu, 2 Sep 2010 18:21:11 +0000 (14:21 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 2 Sep 2010 18:21:11 +0000 (14:21 -0400)
R=r
CC=golang-dev
https://golang.org/cl/2051041

src/pkg/http/fs.go
src/pkg/http/server.go
src/pkg/http/triv.go

index 40bb3d1384c658f7c0f98441463ac7f0c8cf951b..db80b2f4dfd1b4ce9dfed9fca5d4d985925a6b08 100644 (file)
@@ -13,6 +13,7 @@ import (
        "os"
        "path"
        "strings"
+       "time"
        "utf8"
 )
 
@@ -61,8 +62,7 @@ func dirList(c *Conn, f *os.File) {
        fmt.Fprintf(c, "</pre>\n")
 }
 
-
-func serveFileInternal(c *Conn, r *Request, name string, redirect bool) {
+func serveFile(c *Conn, r *Request, name string, redirect bool) {
        const indexPage = "/index.html"
 
        // 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
        if d.IsDirectory() {
                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.
 func ServeFile(c *Conn, r *Request, name string) {
-       serveFileInternal(c, r, name, false)
+       serveFile(c, r, name, false)
 }
 
 type fileHandler struct {
@@ -166,5 +172,5 @@ func (f *fileHandler) ServeHTTP(c *Conn, r *Request) {
                return
        }
        path = path[len(f.prefix):]
-       serveFileInternal(c, r, f.root+"/"+path, true)
+       serveFile(c, r, f.root+"/"+path, true)
 }
index 430f65ad9ec27425d05322fda3787b8cfa0c2466..2de0748677670b421196be5a0ecd7da57b0b8bd4 100644 (file)
@@ -101,6 +101,12 @@ func (ecr *expectContinueReader) Close() os.Error {
        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.
 func (c *Conn) readRequest() (req *Request, err os.Error) {
        if c.hijacked {
@@ -124,6 +130,7 @@ func (c *Conn) readRequest() (req *Request, err os.Error) {
 
        // Default output is HTML encoded in UTF-8.
        c.SetHeader("Content-Type", "text/html; charset=utf-8")
+       c.SetHeader("Date", time.UTC().Format(TimeFormat))
 
        if req.ProtoAtLeast(1, 1) {
                // HTTP/1.1 or greater: use chunked transfer encoding
index 612b6161e348f83421b5543d6d5508ddd0becfd7..957ca5f94e436dab92a1ae3408eff7d1b22593e9 100644 (file)
@@ -52,25 +52,6 @@ func (ctr *Counter) ServeHTTP(c *http.Conn, req *http.Request) {
        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
 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() {
        flag.Parse()
 
@@ -153,7 +136,7 @@ func main() {
        expvar.Publish("counter", ctr)
 
        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("/args", http.HandlerFunc(ArgServer))
        http.Handle("/go/hello", http.HandlerFunc(HelloServer))