hoisie / web Goto Github PK
View Code? Open in Web Editor NEWThe easiest way to create web applications with Go
License: MIT License
The easiest way to create web applications with Go
License: MIT License
Many times you are going to use an URL prefix, like:
urlPrefix = "/wiki/"
web.Get(urlPrefix+"view/(.+)", viewHandler)
web.Post(urlPrefix+"save/(.+)", saveHandler)
so it would be helpful a function that stores that prefix and then were inserted at the string, i.e.
web.Prefix("/wiki/")
web.Get("view/(.+)", viewHandler) // => /wiki/view/
web.Post("save/(.+)", saveHandler) // => /wiki/save/
web.Prefix("/blog/")
web.Get("view/(.+)", viewHandler) // => /blog/view/
// Prefix Cleaning
web.Prefix("")
web.Get("view/(.+)", viewHandler) // => view/
http://github.com/hoisie/web.go/blob/master/request.go#L32
It would be nice to have websocket handler support:
web.Websocket("/test", websocketTest)
It's something I like in Mojolicious and would like to see in web.go.
web.go line 78
The cookie age parameter is ignored. The cookie expiration is hard-coded for 30 minutes.
I think the SetCookie function should be replaced with this:
//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
if age == 0 {
// 2^31 - 1 seconds (roughly 2038)
utctime = time.SecondsToUTC(2147483647)
} else {
utctime = time.SecondsToUTC(time.UTC().Seconds() + age)
}
cookie := fmt.Sprintf("%s=%s; expires=%s", name, value, webTime(utctime))
ctx.SetHeader("Set-Cookie", cookie, false)
}
I dug around in the HTTP RFC and googled my heart out and I couldn't find the max allowed value of "expires". I figure 2^31 - 1 (sometime in 2038) is a reasonable value of "forever".
BTW web.go is awesome! :-)
When doing a build using 8g / 386 I see this:
8g -o go.8 fcgi.go request.go scgi.go servefile.go status.go web.go
fcgi.go:6: syntax error: unexpected :, expecting }
make: *** [go.8] Error 1
8g -o _go_.8 fcgi.go request.go scgi.go servefile.go status.go web.go
web.go:449: undefined: log.Exit
When a request has Accept-Encoding: compress, gzip, it should encode the content as gzip
Also, add a Vary: Accept-Encoding to the response header
In the code you special-case "/static/" but I think there should rather be a "static handler" that can be attached to routes like everything else. Maybe that's naive, but it seems weird looking at the code to have that special case.
I have a subdirectory in my static directory which contains an index.html, however, requests on either /subdir or /subdir/ 404, only /subdir/index.html works. Is this intended behavior?
can we access databases like mysql or oracle using go programming language..?
Currently getting this error if I try and build (either direct from git or using goinstall).
make
6g -o go.6 fcgi.go request.go scgi.go servefile.go status.go web.go
request.go:75: cannot use hr.Header (type http.Header) as type map[string] string in field value
I'm running latest go build on Ubuntu 10.10 64bit.
See the suggestions from redbot
Many shared hosting services (ie. dreamhost for me) don't allow you to specify an external fcgi by address:port and instead using fd 0 as the listen socket for the FastCGI. It would be cool if web.go supported this mode of operation unlocking relatively cheap hosting of go applications.
I find it useful to be able to specify the cookie path when setting the cookie. What if we have an extra argument to the SetCookie/SetSecureCookie functions...
If there were
web.Handle(route string, handler http.Handler)
or something similar, it would be possible to more easily port old web code that uses the standard http packge to web.go.
More interestingly, it would make it possible to register websockets handlers and other things that require lower level control.
To deal with the naming constraints of a struct, the json
module allows one too specify tags to guide unmarshaling/marshaling:
type MyParams struct {
FooBar string "foo_bar"
}
This would serialize the contents of FooBar with the key "foo_bar" and deserialize such that an item with the "foo_bar" will be placed into FooBar.
I added this modification to allow web.go use these tags to guide parameter unmarshaling in the same manner:
diff --git a/request.go b/request.go
index 0e2fc4c..9df8837 100644
--- a/request.go
+++ b/request.go
@@ -328,17 +328,33 @@ func (r *Request) writeToContainer(val reflect.Value) os.Error {
v.SetElem(mk, mv)
}
case *reflect.StructValue:
+ // A little preprocessing to make this faster
+ tagMap := map[string](reflect.Value) {}
+ nameMap := map[string](reflect.Value) {}
+
+ ty := v.Type().(*reflect.StructType)
+ for i := v.NumField(); i >= 0; i-- {
+ field := ty.Field(i)
+ if len(field.Tag) > 0 {
+ tagMap[strings.ToLower(field.Tag)] = v.Field(i)
+ }
+
+ if len(field.Name) > 0 {
+ nameMap[strings.ToLower(field.Name)] = v.Field(i)
+ }
+ }
+
for pk, pv := range r.Params {
- //try case sensitive match
- field := v.FieldByName(pk)
- if field != nil {
+ // try struct tag matching first
+ if field, ok := tagMap[strings.ToLower(pk)]; ok {
writeTo(pv, field)
+ continue
}
- //try case insensitive matching
- field = v.FieldByNameFunc(func(s string) bool { return matchName(pk, s) })
- if field != nil {
+ // now try case-insensitive
+ if field, ok := nameMap[strings.ToLower(pk)]; ok {
writeTo(pv, field)
+ continue
}
}
For instance, the route "/([0-9]+), should be able to be passed to the following handler:
func handler ( n int ) string { ... }
You should try to get a CL into the Go tree approved so you don't have to copy the status messages. DRY and all that. :-D I can do it if you don't have time for the process. Of course they could turn us down... :-/
This is important. Cookies are easily forged, so securing cookies is the right approach.
Hi,
I am using a version of Go, but I don't know which, (man 6c, go -v or go --version does not work on my system). The package version is, "2010_09_29-1", however.
When I pull web.go from git and try to compile it, I get:
make
6g -o go.6 fcgi.go request.go scgi.go servefile.go status.go web.go
fcgi.go:244: s.Logger.Println undefined (type log.Logger has no field or method Println)
fcgi.go:299: s.Logger.Println undefined (type log.Logger has no field or method Println)
fcgi.go:305: s.Logger.Println undefined (type log.Logger has no field or method Println)
scgi.go:148: s.Logger.Println undefined (type log.Logger has no field or method Println)
scgi.go:175: s.Logger.Println undefined (type log.Logger has no field or method Println)
scgi.go:182: s.Logger.Println undefined (type log.Logger has no field or method Println)
web.go:117: ctx.Server.Logger.Println undefined (type log.Logger has no field or method Println)
web.go:418: cannot use "" (type string) as type io.Writer in function argument:
string does not implement io.Writer (missing Write method)
web.go:418: cannot use log.Ldate (type int) as type string in function argument
web.go:418: not enough arguments to function call
web.go:117: too many errors
make: *** [go.6] Error 1
Replacing the log statements with fmt.Printf and fmt.Println makes it compile, but logging is more useful...
How to reproduce:
Just type "make".
Thanks.
in commit 0554b31
you changed the way in which the filedate is initialized:
- r.Files[name] = filedata{filename, rest}
+ if params["filename"] != "" {
+ r.Files[name] = filedata{name, data}
and the result is that the filename is no longer available:
the Filename field of filedata now contains the value of the 'name' attribute of the file input form field.
I solved this for me by changing it back as follows
- r.Files[name] = filedata{name, data}
+ r.Files[name] = filedata{params["filename"], data}
... Following output:
:~/web.go$ gomake
6g -o _go_.6 fcgi.go request.go scgi.go servefile.go status.go web.go
scgi.go:106: cannot use &tmp (type *[1024]uint8) as type []uint8 in function argument
scgi.go:118: cannot use &tmp (type *[1024]uint8) as type []uint8 in function argument
servefile.go:75: cannot use &buf (type *[1024]uint8) as type []uint8 in function argument
make: *** [_go_.6] Error 1
web.go:229: c.conn.Hijack undefined (type http.ResponseWriter has no field or method Hijack)
Pls refer to : http://codereview.appspot.com/4245064/
Currently I have fixed the issue on my box follow the guide in above link. Hope you can include this change.
Thanks,
Cj
This is (almost) my first experience with web development using a compiled language. I've become extremely used to being able to just change my code, and when I refresh the page, it runs differently. I do this literally more than once a minute.
Compiling a binary every time I want to see a change, even if compilation is almost instantaneous, is hard work. I don't think it's a fundamental issue with compiled languages, though -- how about if some scheme like the following was followed:
The system is aware of the source from which it is compiled, and tracks those files for changes. When a new HTTP request comes in, if changes to the source have been made, it dies, recompiles, starts again, and then handles the request. There'd be issues if you're storing application state in memory, but ... I don't.
I should say, this management would be done by another binary rather than the app itself. Let's call it runwebgo
, and I can call it as with any other binary. And let's say for my application, called blog
, I provide a plaintext file called .runwebgo
, which contains:
make
)Now, instead of running make
and then ./blog
every time, I just run runwebgo
in the top level of my app directory. runwebgo
then:
.runwebgo
file for the list of files, the command, and the portchanged
flag when a file changeschanged
flag. If things have changed, it kills my app, recompiles it, re-runs it. In either case, it then sends on the request to the port of my app.It could also observe changes to the .runwebgo
file itself, and dynamically update the source list if I resave it.
I imagine creating this would not be too hard or use anything outside the standard library. The upshot IMO is massive: I just run one command and leave it for my whole coding session.
Cookies (by default) should expire 30 minutes after the last request
It's a hack right now -- maybe add a plugin for it down the line. As long as SetCookie works, that's good enough
Maybe have a logger object that defaults to stdout
As an example, multiple Set-Cookie headers
Reported by Alexey Zilber:
Running a web.go app with spawn-fcgi doesn't work:
sudo -u lighttpd spawn-fcgi -f /path/to/app -a localhost -p 8803
spawn-fcgi.c.230: child exited with: 0
In this case, as far as I know, web.go should read from stdin and write to stdout
Information about client remote address is required for some class of web applications.
In the GetSecureCookie function if the cookie content doesn't fit the required format we can expect index out of range errors.
parts := strings.Split(cookie, "|", 3) val := parts[0] timestamp := parts[1] sig := parts[2]
Programmation/Go/web.go % git pull
Already up-to-date.
Programmation/Go/web.go % make
/home/bortzmeyer/bin/8g -o go.8 fcgi.go request.go scgi.go servefile.go web.go
web.go:76: utc1.RFC1123 undefined (type time.Time has no field RFC1123)
make: *** [go.8] Error 1
the pkg/template makes writing web templates difficult. web.go needs something better suited for the web, like mustache
Hello,
web.SetCookieSecret is mentioned in web.go line 103
ctx.Logger.Println("Secret Key for secure cookies has not been set. Please call web.SetCookieSecret")
but does not exist in web.go.
on tip of go and tip of web.go:
/home/ericvh/bin/6g -o go.6 fcgi.go request.go scgi.go servefile.go status.go web.go
request.go:129: vec.Data undefined (type vector.StringVector has no field Data)
make: *** [go.6] Error 1
One URL may match many regexes. The order in which route regexes are tested is therefore significant. This order, in my experience, is "top to bottom" -- this is present in Django, and in web.py from which web.go is vaguely inspired.
Thus, I would expect a call to http://localhost:9999/ to respond with the string first
, given the following program:
package main
import (
"web"
)
func main() {
web.Get("/", func() string { return "first" } )
web.Get("/", func() string { return "second" } )
web.Run("0.0.0.0:9999")
}
However, it responds with second
.
I only started Go today :\ -- but looking at http://github.com/hoisie/web.go/blob/master/web.go ,
the reason is that routes
is a map rather than an array. routes
is only used when iterating over it, suggesting the want of an array rather than map. Nor is the map key (a compiled regex) necessary as each route
struct has the compiled regex inside it. Am I right?
Lately I've been finding use cases for a middleware system. For example - generic cache-control handling and authentication
It will most likely follow the wsgi format -- something very simple for now
It is not that uncommon to have a POST body large enough to get split into multiple FCGI_STDIN chunks, so this should just be appending to the buffer, rather than assigning it.
case FcgiStdin:
if h.ContentLength > 0 {
var buf bytes.Buffer
buf.Write(content)
req.Body = &buf
And despite the spec not being very clear on what FCGI_DATA is used for, browsers do use it; so it should probably be handled the same way.
[ Great framework, btw, keep improving it :) ]
goinstall github.com/hoisie/web.go
8g -o main.8 main.go resume.go /mnt/home/droundy/src/go/pkg/linux_386/github.com/hoisie/web.go.a
main.go:8: inconsistent definition for type reflect.FuncType during import
struct { reflect.commonType "func"; dotdotdot bool; in []_runtime.Type; out []_runtime.Type }
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.