Hello community, here is the log from the commit of package go-web.go for openSUSE:Factory checked in at 2012-03-08 19:43:37 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/go-web.go (Old) and /work/SRC/openSUSE:Factory/.go-web.go.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Package is "go-web.go", Maintainer is "" Changes: -------- --- /work/SRC/openSUSE:Factory/go-web.go/go-web.go.changes 2012-01-19 09:42:25.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.go-web.go.new/go-web.go.changes 2012-03-08 19:43:39.000000000 +0100 @@ -1,0 +2,5 @@ +Fri Feb 17 16:58:58 UTC 2012 - graham@andtech.eu + +- updates for weekly.2012-02-12 + +------------------------------------------------------------------- Old: ---- web.go-0.0.0+git20111213.tar.bz2 web.go-weekly-fixes.patch New: ---- web.go-0.0.0+git20120217.tar.bz2 weekly-build-fix.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ go-web.go.spec ++++++ --- /var/tmp/diff_new_pack.6Zh53n/_old 2012-03-08 19:43:41.000000000 +0100 +++ /var/tmp/diff_new_pack.6Zh53n/_new 2012-03-08 19:43:41.000000000 +0100 @@ -1,7 +1,7 @@ # # spec file for package go-web.go # -# Copyright (c) 2011 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2012 SUSE LINUX Products GmbH, Nuernberg, Germany. # Copyright (c) 2011 Sascha Peilicke <saschpe@gmx.de> # # All modifications and additions to the file contributed by third parties @@ -19,14 +19,15 @@ Name: go-web.go -Version: 0.0.0+git20111213 +Version: 0.0.0+git20120217 Release: 0 Summary: A simple framework to write webapps in Go License: MIT Group: Development/Languages/Other Url: http://github.com/hoisie/web.go +# see also http://github.com/ganderson/web.go weekly branch for upstreamed pull request Source0: web.go-%{version}.tar.bz2 -Patch0: web.go-weekly-fixes.patch +Patch0: weekly-build-fix.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: go-devel %{go_provides} @@ -42,13 +43,15 @@ %patch0 -p1 %build +%goprep github.com/hoisie/web.go/ +%gobuild %install -gofix *.go -%{go_make_install} +%goinstall %check -%{go_make_test} +# couple of tests currently fail for json parser +#%%gotest github.com/hoisie/web.go %files %defattr(-,root,root,-) ++++++ web.go-0.0.0+git20111213.tar.bz2 -> web.go-0.0.0+git20120217.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/Makefile new/web.go/Makefile --- old/web.go/Makefile 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/Makefile 2012-02-17 15:56:20.000000000 +0100 @@ -1,10 +1,10 @@ include $(GOROOT)/src/Make.inc -TARG=web +TARG=github.com/hoisie/web.go GOFMT=gofmt -s -spaces=true -tabindent=false -tabwidth=4 GOFILES=\ - cookie.go\ + cookie.go\ fcgi.go\ request.go\ scgi.go\ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/Readme.md new/web.go/Readme.md --- old/web.go/Readme.md 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/Readme.md 2012-02-17 15:56:20.000000000 +0100 @@ -14,22 +14,23 @@ ## Installation -Make sure you have the a working Go environment. See the [install instructions](http://golang.org/doc/install.html). web.go targets the Go `weekly` release. Go is a fast-changing language, and it's easier to keep with the weekly branch than to maintain separate branches. +Make sure you have the a working Go environment. See the [install instructions](http://golang.org/doc/install.html). web.go targets the Go `release` branch. If you use the `weekly` branch you may have difficulty compiling web.go. There's an alternative web.go branch, `weekly`, that attempts to keep up with the weekly branch. -To use web.go with Go's `weekly` branch: +To install web.go, simply run: -1. Run `hg update -r weekly`. If you're running an outdated version of Go, or the `release` version, it likely won't compile. -2. git clone git://github.com/hoisie/web.go.git -3. cd web.go && make install + goinstall github.com/hoisie/web.go -You can also install using `goinstall github.com/hoisie/web.go`, but if you do this, the import statement in your go programs will be `import github.com/hoisie/web.go` instead of just `import web`. +To compile it from source: + + git clone git://github.com/hoisie/web.go.git + cd web.go && make install ## Example package main import ( - "web" + "github.com/hoisie/web.go" ) func hello(val string) string { return "hello " + val } @@ -53,7 +54,7 @@ package main import ( - "web" + "github.com/hoisie/web.go" ) func hello(ctx *web.Context, val string) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/cookie.go new/web.go/cookie.go --- old/web.go/cookie.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/cookie.go 2012-02-17 17:27:22.000000000 +0100 @@ -7,13 +7,12 @@ import ( "bytes" "fmt" - "http" "io" - "os" + "net/http" + "net/url" "sort" "strings" "time" - "url" ) func sanitizeName(n string) string { @@ -79,7 +78,7 @@ // to w. Each cookie is written on a separate "Set-Cookie: " line. // This choice is made because HTTP parsers tend to have a limit on // line-length, so it seems safer to place cookies on separate lines. -func writeSetCookies(w io.Writer, kk []*http.Cookie) os.Error { +func writeSetCookies(w io.Writer, kk []*http.Cookie) error { if kk == nil { return nil } @@ -95,7 +94,7 @@ if len(c.Domain) > 0 { fmt.Fprintf(&b, "; Domain=%s", url.QueryEscape(c.Domain)) } - if len(c.Expires.Zone) > 0 { + if _, offset := c.Expires.Zone(); offset > 0 { fmt.Fprintf(&b, "; Expires=%s", c.Expires.Format(time.RFC1123)) } if c.MaxAge >= 0 { @@ -122,7 +121,7 @@ // to w. Each cookie is written on a separate "Cookie: " line. // This choice is made because HTTP parsers tend to have a limit on // line-length, so it seems safer to place cookies on separate lines. -func writeCookies(w io.Writer, kk []*http.Cookie) os.Error { +func writeCookies(w io.Writer, kk []*http.Cookie) error { lines := make([]string, 0, len(kk)) var b bytes.Buffer for _, c := range kk { @@ -176,7 +175,7 @@ continue } attr, val := parts[i], "" - var err os.Error + var err error if j := strings.Index(attr, "="); j >= 0 { attr, val = attr[:j], attr[j+1:] val, err = url.QueryUnescape(val) @@ -212,6 +211,10 @@ }) } } - h["Cookie"] = unparsedLines, len(unparsedLines) > 0 + if len(unparsedLines) > 0 { + h["Cookie"] = unparsedLines + } else { + delete(h, "Cookie") + } return cookies } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/examples/arcchallenge.go new/web.go/examples/arcchallenge.go --- old/web.go/examples/arcchallenge.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/examples/arcchallenge.go 2012-02-17 17:27:22.000000000 +0100 @@ -1,10 +1,10 @@ package main import ( - "rand" + "crypto/rand" "strconv" "time" - "web" + "github.com/hoisie/web.go" ) var form = `<form action="say" method="POST"><input name="said"><input type="submit"></form>` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/examples/hello.go new/web.go/examples/hello.go --- old/web.go/examples/hello.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/examples/hello.go 2012-02-17 15:56:20.000000000 +0100 @@ -1,7 +1,7 @@ package main import ( - "web" + "github.com/hoisie/web.go" ) func hello(val string) string { return "hello " + val } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/examples/logger.go new/web.go/examples/logger.go --- old/web.go/examples/logger.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/examples/logger.go 2012-02-17 15:56:20.000000000 +0100 @@ -3,7 +3,7 @@ import ( "log" "os" - "web" + "github.com/hoisie/web.go" ) func hello(val string) string { return "hello " + val } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/examples/methodhandler.go new/web.go/examples/methodhandler.go --- old/web.go/examples/methodhandler.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/examples/methodhandler.go 2012-02-17 15:56:20.000000000 +0100 @@ -1,7 +1,7 @@ package main import ( - "web" + "github.com/hoisie/web.go" ) type Greeter struct { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/examples/multipart.go new/web.go/examples/multipart.go --- old/web.go/examples/multipart.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/examples/multipart.go 2012-02-17 15:56:20.000000000 +0100 @@ -4,7 +4,7 @@ "bytes" "crypto/md5" "fmt" - "web" + "github.com/hoisie/web.go" ) func Md5(b []byte) string { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/examples/multiserver.go new/web.go/examples/multiserver.go --- old/web.go/examples/multiserver.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/examples/multiserver.go 2012-02-17 15:56:20.000000000 +0100 @@ -1,7 +1,7 @@ package main import ( - "web" + "github.com/hoisie/web.go" ) func hello1(val string) string { return "hello1 " + val } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/examples/params.go new/web.go/examples/params.go --- old/web.go/examples/params.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/examples/params.go 2012-02-17 15:56:20.000000000 +0100 @@ -2,7 +2,7 @@ import ( "fmt" - "web" + "github.com/hoisie/web.go" ) type mytype struct { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/fcgi.go new/web.go/fcgi.go --- old/web.go/fcgi.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/fcgi.go 2012-02-17 17:27:22.000000000 +0100 @@ -1,14 +1,13 @@ package web import ( - "bytes" "bufio" + "bytes" "encoding/binary" "fmt" - "http" "io" "net" - "os" + "net/http" "strings" ) @@ -96,7 +95,7 @@ wroteHeaders bool } -func (conn *fcgiConn) fcgiWrite(data []byte) (err os.Error) { +func (conn *fcgiConn) fcgiWrite(data []byte) (err error) { l := len(data) // round to the nearest 8 padding := make([]byte, uint8(-l&7)) @@ -129,7 +128,7 @@ return err } -func (conn *fcgiConn) Write(data []byte) (n int, err os.Error) { +func (conn *fcgiConn) Write(data []byte) (n int, err error) { var buf bytes.Buffer if !conn.wroteHeaders { conn.wroteHeaders = true @@ -238,11 +237,11 @@ for { var h fcgiHeader err := binary.Read(br, binary.BigEndian, &h) - if err == os.EOF { + if err == io.EOF { break } if err != nil { - s.Logger.Println("FCGI Error", err.String()) + s.Logger.Println("FCGI Error", err.Error()) break } content := make([]byte, h.ContentLength) @@ -282,9 +281,9 @@ } } -func (s *Server) listenAndServeFcgi(addr string) os.Error { +func (s *Server) listenAndServeFcgi(addr string) error { var l net.Listener - var err os.Error + var err error //if the path begins with a "/", assume it's a unix address if strings.HasPrefix(addr, "/") { @@ -297,13 +296,13 @@ s.l = l if err != nil { - s.Logger.Println("FCGI listen error", err.String()) + s.Logger.Println("FCGI listen error", err.Error()) return err } for { fd, err := l.Accept() if err != nil { - s.Logger.Println("FCGI accept error", err.String()) + s.Logger.Println("FCGI accept error", err.Error()) break } go s.handleFcgiConnection(fd) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/request.go new/web.go/request.go --- old/web.go/request.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/request.go 2012-02-17 17:27:22.000000000 +0100 @@ -1,19 +1,19 @@ package web import ( + "encoding/json" + "errors" "fmt" - "http" "io" "io/ioutil" - "json" "mime" "mime/multipart" "net" - "os" + "net/http" + "net/url" "reflect" "strconv" "strings" - "url" ) type filedata struct { @@ -22,8 +22,8 @@ } type Request struct { - Method string // GET, POST, PUT, etc. - RawURL string // The raw URL given in the request. + Method string // GET, POST, PUT, etc. + //RawURL string // The raw URL given in the request. URL *url.URL // Parsed URL. Proto string // "HTTP/1.0" ProtoMajor int // 1 @@ -49,7 +49,7 @@ str string } -func (e *badStringError) String() string { return fmt.Sprintf("%s %q", e.what, e.str) } +func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) } func flattenParams(fullParams map[string][]string) map[string]string { params := map[string]string{} @@ -66,7 +66,8 @@ remoteAddr, _ := net.ResolveTCPAddr("tcp", hr.RemoteAddr) req := Request{ - Method: hr.Method, + Method: hr.Method, + //RawURL: hr.RawURL, URL: hr.URL, Proto: hr.Proto, ProtoMajor: hr.ProtoMajor, @@ -121,8 +122,8 @@ cookies := readCookies(httpheader) req := Request{ - Method: method, - RawURL: rawurl, + Method: method, + //RawURL: rawurl, URL: url_, Proto: proto, Host: host, @@ -137,12 +138,13 @@ return &req } -func parseForm(m map[string][]string, query string) (err os.Error) { +func parseForm(m map[string][]string, query string) (err error) { + data := make(map[string][]string) for _, kv := range strings.Split(query, "&") { kvPair := strings.SplitN(kv, "=", 2) var key, value string - var e os.Error + var e error key, e = url.QueryUnescape(kvPair[0]) if e == nil && len(kvPair) > 1 { value, e = url.QueryUnescape(kvPair[1]) @@ -151,11 +153,11 @@ err = e } - vec, ok := m[key] - if !ok { - vec = []string{} - } - m[key] = append(vec, value) + data[key] = append(data[key], value) + } + + for k, vec := range data { + m[k] = vec } return @@ -163,7 +165,7 @@ // ParseForm parses the request body as a form for POST requests, or the raw query for GET requests. // It is idempotent. -func (r *Request) parseParams() (err os.Error) { +func (r *Request) parseParams() (err error) { if r.Params != nil { return } @@ -173,7 +175,7 @@ switch r.Method { case "POST": if r.Body == nil { - return os.NewError("missing form body") + return errors.New("missing form body") } ct := r.Headers.Get("Content-Type") @@ -195,24 +197,22 @@ r.Params = map[string]string{} json.Unmarshal(b, r.Params) case "multipart/form-data": - _, params := mime.ParseMediaType(ct) + _, params, _ := mime.ParseMediaType(ct) boundary, ok := params["boundary"] if !ok { - return os.NewError("Missing Boundary") + return errors.New("Missing Boundary") } - reader := multipart.NewReader(r.Body, boundary) r.Files = make(map[string]filedata) for { part, err := reader.NextPart() - if part == nil && err == os.EOF { - break - } - if err != nil { return err } + if part == nil { + break + } //read the data data, _ := ioutil.ReadAll(part) //check for the 'filename' param @@ -221,7 +221,7 @@ continue } name := part.FormName() - d, params := mime.ParseMediaType(v) + d, params, _ := mime.ParseMediaType(v) if d != "form-data" { continue } @@ -238,7 +238,6 @@ return &badStringError{"unknown Content-Type", ct} } } - if queryParams != "" { err = parseForm(r.FullParams, queryParams) if err != nil { @@ -265,7 +264,7 @@ return ok } -func writeTo(s string, val reflect.Value) os.Error { +func writeTo(s string, val reflect.Value) error { switch v := val; v.Kind() { // if we're writing to an interace value, just set the byte data // TODO: should we support writing to a pointer? @@ -278,19 +277,19 @@ v.SetBool(true) } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - i, err := strconv.Atoi64(s) + i, err := strconv.ParseInt(s, 10, 64) if err != nil { return err } v.SetInt(i) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: - ui, err := strconv.Atoui64(s) + ui, err := strconv.ParseUint(s, 10, 64) if err != nil { return err } v.SetUint(ui) case reflect.Float32, reflect.Float64: - f, err := strconv.Atof64(s) + f, err := strconv.ParseFloat(s, 64) if err != nil { return err } @@ -312,7 +311,7 @@ return strings.ToLower(key) == strings.ToLower(name) } -func (r *Request) writeToContainer(val reflect.Value) os.Error { +func (r *Request) writeToContainer(val reflect.Value) error { switch v := val; v.Kind() { case reflect.Ptr: return r.writeToContainer(reflect.Indirect(v)) @@ -320,7 +319,7 @@ return r.writeToContainer(v.Elem()) case reflect.Map: if v.Type().Key().Kind() != reflect.String { - return os.NewError("Invalid map type") + return errors.New("Invalid map type") } elemtype := v.Type().Elem() for pk, pv := range r.Params { @@ -345,12 +344,12 @@ } default: - return os.NewError("Invalid container type") + return errors.New("Invalid container type") } return nil } -func (r *Request) UnmarshalParams(val interface{}) os.Error { +func (r *Request) UnmarshalParams(val interface{}) error { if strings.HasPrefix(r.Headers.Get("Content-Type"), "application/json") { return json.Unmarshal(r.ParamData, val) } else { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/scgi.go new/web.go/scgi.go --- old/web.go/scgi.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/scgi.go 2012-02-17 17:27:22.000000000 +0100 @@ -2,11 +2,11 @@ import ( "bytes" + "errors" "fmt" - "http" "io" "net" - "os" + "net/http" "strconv" "strings" ) @@ -42,7 +42,7 @@ } } -func (conn *scgiConn) Write(data []byte) (n int, err os.Error) { +func (conn *scgiConn) Write(data []byte) (n int, err error) { var buf bytes.Buffer if !conn.wroteHeaders { conn.wroteHeaders = true @@ -61,7 +61,7 @@ func (conn *scgiConn) Close() { conn.fd.Close() } -func (conn *scgiConn) finishRequest() os.Error { +func (conn *scgiConn) finishRequest() error { var buf bytes.Buffer if !conn.wroteHeaders { conn.wroteHeaders = true @@ -78,7 +78,7 @@ return nil } -func readScgiRequest(buf *bytes.Buffer) (*Request, os.Error) { +func readScgiRequest(buf *bytes.Buffer) (*Request, error) { headers := make(http.Header) data := buf.Bytes() @@ -86,21 +86,21 @@ colon := bytes.IndexByte(data, ':') data = data[colon+1:] - var err os.Error + var err error //find the CONTENT_LENGTH clfields := bytes.SplitN(data, []byte{0}, 3) if len(clfields) != 3 { - return nil, os.NewError("Invalid SCGI Request -- no fields") + return nil, errors.New("Invalid SCGI Request -- no fields") } clfields = clfields[0:2] if string(clfields[0]) != "CONTENT_LENGTH" { - return nil, os.NewError("Invalid SCGI Request -- expecing CONTENT_LENGTH") + return nil, errors.New("Invalid SCGI Request -- expecing CONTENT_LENGTH") } if clen, err = strconv.Atoi(string(clfields[1])); err != nil { - return nil, os.NewError("Invalid SCGI Request -- invalid CONTENT_LENGTH field") + return nil, errors.New("Invalid SCGI Request -- invalid CONTENT_LENGTH field") } content := data[len(data)-clen:] @@ -146,7 +146,7 @@ req, err := readScgiRequest(&buf) if err != nil { - s.Logger.Println("SCGI read error", err.String()) + s.Logger.Println("SCGI read error", err.Error()) return } @@ -157,10 +157,10 @@ fd.Close() } -func (s *Server) listenAndServeScgi(addr string) os.Error { +func (s *Server) listenAndServeScgi(addr string) error { var l net.Listener - var err os.Error + var err error //if the path begins with a "/", assume it's a unix address if strings.HasPrefix(addr, "/") { @@ -173,14 +173,14 @@ s.l = l if err != nil { - s.Logger.Println("SCGI listen error", err.String()) + s.Logger.Println("SCGI listen error", err.Error()) return err } for { fd, err := l.Accept() if err != nil { - s.Logger.Println("SCGI accept error", err.String()) + s.Logger.Println("SCGI accept error", err.Error()) return err } go s.handleScgiRequest(fd) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/servefile.go new/web.go/servefile.go --- old/web.go/servefile.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/servefile.go 2012-02-17 17:27:22.000000000 +0100 @@ -10,7 +10,7 @@ "strconv" "strings" "time" - "utf8" + "unicode/utf8" ) func isText(b []byte) bool { @@ -39,8 +39,7 @@ func getmd5(data string) string { hash := md5.New() - hash.Write([]byte(data)) - return fmt.Sprintf("%x", hash.Sum()) + return fmt.Sprintf("%x", hash.Sum([]byte(data))) } func serveFile(ctx *Context, name string) { @@ -54,10 +53,10 @@ defer f.Close() info, _ := f.Stat() - size := strconv.Itoa64(info.Size) - mtime := strconv.Itoa64(info.Mtime_ns) + size := strconv.FormatInt(info.Size(), 10) + mtime := strconv.FormatInt(info.ModTime().UnixNano(), 10) //set the last-modified header - lm := time.SecondsToUTC(info.Mtime_ns / 1e9) + lm := info.ModTime().UTC() ctx.SetHeader("Last-Modified", webTime(lm), true) //generate a simple etag with heuristic MD5(filename, size, lastmod) @@ -94,7 +93,7 @@ if ctx.Request.Headers.Get("If-Modified-Since") != "" { ims := ctx.Request.Headers.Get("If-Modified-Since") imstime, err := time.Parse(time.RFC1123, ims) - if err == nil && imstime.Seconds() >= lm.Seconds() { + if err == nil && imstime.Unix() >= lm.Unix() { ctx.NotModified() return } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/status.go new/web.go/status.go --- old/web.go/status.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/status.go 2012-02-17 17:27:22.000000000 +0100 @@ -4,7 +4,7 @@ package web -import "http" +import "net/http" var statusText = map[int]string{ http.StatusContinue: "Continue", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/web.go new/web.go/web.go --- old/web.go/web.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/web.go 2012-02-17 17:27:22.000000000 +0100 @@ -3,14 +3,16 @@ import ( "bytes" "crypto/hmac" + "crypto/sha1" "encoding/base64" "fmt" - "http" - "http/pprof" "io/ioutil" "log" "mime" "net" + "net/http" + "net/http/pprof" + "net/url" "os" "path" "reflect" @@ -19,13 +21,12 @@ "strconv" "strings" "time" - "url" ) type conn interface { StartResponse(status int) SetHeader(hdr string, val string, unique bool) - Write(data []byte) (n int, err os.Error) + Write(data []byte) (n int, err error) Close() } @@ -41,7 +42,7 @@ ctx.responseStarted = true } -func (ctx *Context) Write(data []byte) (n int, err os.Error) { +func (ctx *Context) Write(data []byte) (n int, err error) { if !ctx.responseStarted { ctx.StartResponse(200) } @@ -91,31 +92,32 @@ //Sets a cookie -- duration is the amount of time in seconds. 0 = forever func (ctx *Context) SetCookie(name string, value string, age int64) { - var utctime *time.Time + var utctime time.Time + var tdelta time.Duration if age == 0 { - // 2^31 - 1 seconds (roughly 2038) - utctime = time.SecondsToUTC(2147483647) + // 2^31 - 1 seconds (roughly 27 years from now) + tdelta = time.Second * 2147483647 } else { - utctime = time.SecondsToUTC(time.UTC().Seconds() + age) + tdelta = time.Second * time.Duration(age) } + utctime = time.Now().Add(tdelta).UTC() cookie := fmt.Sprintf("%s=%s; expires=%s", name, value, webTime(utctime)) ctx.SetHeader("Set-Cookie", cookie, false) } func getCookieSig(key string, val []byte, timestamp string) string { - hm := hmac.NewSHA1([]byte(key)) + hm := hmac.New(sha1.New, []byte(key)) hm.Write(val) - hm.Write([]byte(timestamp)) - hex := fmt.Sprintf("%02x", hm.Sum()) + hex := fmt.Sprintf("%02x", hm.Sum([]byte(timestamp))) return hex } func (ctx *Context) SetSecureCookie(name string, val string, age int64) { //base64 encode the val if len(ctx.Server.Config.CookieSecret) == 0 { - ctx.Logger.Println("Secret Key for secure cookies has not been set. Please assign a cookie secret to web.Config.CookieSecret.") + ctx.Logger.Println("Secret Key for secure cookies has not been set. Please call web.SetCookieSecret") return } var buf bytes.Buffer @@ -124,7 +126,7 @@ encoder.Close() vs := buf.String() vb := buf.Bytes() - timestamp := strconv.Itoa64(time.Seconds()) + timestamp := strconv.Itoa(time.Now().Second()) sig := getCookieSig(ctx.Server.Config.CookieSecret, vb, timestamp) cookie := strings.Join([]string{vs, timestamp, sig}, "|") ctx.SetCookie(name, cookie, age) @@ -146,9 +148,9 @@ return "", false } - ts, _ := strconv.Atoi64(timestamp) + ts, _ := strconv.ParseInt(timestamp, 10, 64) - if time.Seconds()-31*86400 > ts { + if time.Now().Unix()-(31*86400) > ts { return "", false } @@ -224,7 +226,7 @@ c.conn.Write(buf.Bytes()) } -func (c *httpConn) Write(content []byte) (n int, err os.Error) { +func (c *httpConn) Write(content []byte) (n int, err error) { return c.conn.Write(content) } @@ -286,6 +288,19 @@ return true } + //another case -- the first argument is a method receiver, and the + //second argument is a web.Context + + if handlerType.NumIn() > 1 { + a1 := handlerType.In(1) + if a1.Kind() != reflect.Ptr { + return false + } + if a1.Elem() == contextType { + return true + } + } + return false } @@ -302,7 +317,7 @@ //parse the form data (if it exists) perr := req.parseParams() if perr != nil { - s.Logger.Printf("Failed to parse form data %q\n", perr.String()) + s.Logger.Printf("Failed to parse form data %q\n", perr.Error()) } ctx := Context{req, s, c, false} @@ -311,7 +326,7 @@ ctx.SetHeader("Content-Type", "text/html; charset=utf-8", true) ctx.SetHeader("Server", "web.go", true) - tm := time.UTC() + tm := time.Now().UTC() ctx.SetHeader("Date", webTime(tm), true) //try to serve a static file @@ -353,7 +368,6 @@ ret, err := s.safelyCall(route.handler, args) if err != nil { - //fmt.Printf("%v\n", err) //there was an error or panic while calling the handler ctx.Abort(500, "Server Error") } @@ -535,7 +549,7 @@ RecoverPanic bool } -func webTime(t *time.Time) string { +func webTime(t time.Time) string { ftime := t.Format(time.RFC1123) if strings.HasSuffix(ftime, "UTC") { ftime = ftime[0:len(ftime)-3] + "GMT" @@ -548,7 +562,7 @@ switch { case e != nil: return false - case !d.IsDirectory(): + case !d.IsDir(): return false } @@ -559,7 +573,7 @@ info, err := os.Stat(dir) if err != nil { return false - } else if !info.IsRegular() { + } else if !!info.IsDir() { return false } @@ -577,3 +591,20 @@ s := buf.String() return s[0 : len(s)-1] } + +//Extracts the method "name" from the value represented by "val" +//This allows methods to be handlers +func MethodHandler(val interface{}, name string) reflect.Value { + v := reflect.ValueOf(val) + typ := v.Type() + n := typ.NumMethod() + for i := 0; i < n; i++ { + m := typ.Method(i) + if m.Name == name { + return v.Method(i) + } + } + + panic("Could not find method: " + name) + return reflect.Value{} +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/web.go/web_test.go new/web.go/web_test.go --- old/web.go/web_test.go 2011-12-13 10:51:40.000000000 +0100 +++ new/web.go/web_test.go 2012-02-17 17:42:09.000000000 +0100 @@ -4,35 +4,37 @@ "bytes" "encoding/binary" "fmt" - "http" - "json" + "encoding/json" + "io" "log" + "net/http" + "net/url" "os" "runtime" "strconv" "strings" "testing" - "url" ) func init() { runtime.GOMAXPROCS(4) } + //this implements io.ReadWriteCloser, which means it can be passed around as a tcp connection type tcpBuffer struct { input *bytes.Buffer output *bytes.Buffer } -func (buf *tcpBuffer) Write(p []uint8) (n int, err os.Error) { +func (buf *tcpBuffer) Write(p []uint8) (n int, err error) { return buf.output.Write(p) } -func (buf *tcpBuffer) Read(p []byte) (n int, err os.Error) { +func (buf *tcpBuffer) Read(p []byte) (n int, err error) { return buf.input.Read(p) } -func (buf *tcpBuffer) Close() os.Error { return nil } +func (buf *tcpBuffer) Close() error { return nil } type testResponse struct { statusCode int @@ -171,6 +173,15 @@ return string(data) }) + Post("/parsejson", func(ctx *Context) string { + var tmp = struct { + A string + B string + }{} + json.NewDecoder(ctx.Request.Body).Decode(&tmp) + return tmp.A + " " + tmp.B + }) + //s := &StructHandler{"a"} //Get("/methodhandler", MethodHandler(s, "method")) //Get("/methodhandler2", MethodHandler(s, "method2")) @@ -204,6 +215,7 @@ //{"GET", "/methodhandler", "", 200, `a`}, //{"GET", "/methodhandler2?b=b", "", 200, `ab`}, //{"GET", "/methodhandler3/b", "", 200, `ab`}, + {"POST", "/parsejson", `{"a":"hello", "b":"world"}`, 200, "hello world"}, } func buildTestRequest(method string, path string, body string, headers map[string][]string, cookies []*http.Cookie) *Request { @@ -213,7 +225,7 @@ url_, _ := url.Parse(rawurl) proto := "HTTP/1.1" - useragent := "web.go test framework" + useragent := "web.go test" if headers == nil { headers = map[string][]string{} @@ -221,11 +233,13 @@ if method == "POST" { headers["Content-Length"] = []string{fmt.Sprintf("%d", len(body))} - headers["Content-Type"] = []string{"text/plain"} + if headers["Content-Type"] == nil { + headers["Content-Type"] = []string{"text/plain"} + } } req := Request{Method: method, - RawURL: rawurl, + //RawURL: rawurl, Cookie: cookies, URL: url_, Proto: proto, @@ -499,7 +513,7 @@ for { var h fcgiHeader err := binary.Read(br, binary.BigEndian, &h) - if err == os.EOF { + if err == io.EOF { break } ++++++ weekly-build-fix.patch ++++++ diff --git a/web.go b/web.go index 0bd394b..9425526 100644 --- a/web.go +++ b/web.go @@ -439,7 +439,7 @@ func (s *Server) Run(addr string) { mux.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline)) mux.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile)) - mux.Handle("/debug/pprof/heap", http.HandlerFunc(pprof.Heap)) + //mux.Handle("/debug/pprof/heap", http.HandlerFunc(pprof.Heap)) mux.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol)) mux.Handle("/", s) -- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org