aofei / air Goto Github PK
View Code? Open in Web Editor NEWAn ideally refined web framework for Go.
Home Page: https://pkg.go.dev/github.com/aofei/air
License: MIT License
An ideally refined web framework for Go.
Home Page: https://pkg.go.dev/github.com/aofei/air
License: MIT License
That will simplify dependency management.
Do you plan to follow SemVer?
air.GET("/auth/:verifier", func(req *air.Request, res *air.Response) error {
user, err := VerifyUser(req.Param("verifier").Value().String())
if err != nil || user == nil {
if DevMode {
fmt.Println("Unable to Authenticate user: ", err)
}
return UnauthorizedError.Send(res)
}
newtoken, err := GenerateAuthToken(user, false)
if err == nil {
// This Cookie never reaches the client
res.SetCookie("Auth", &air.Cookie{
Value: newtoken,
Path: "/",
MaxAge: 60 * 60 * 24 * 7,
Domain: AppDomain,
HTTPOnly: !DevMode,
Secure: !DevMode,
})
} else {
if DevMode {
fmt.Println("error verifying the user, GenerateAuthToken db problem: ", err)
}
}
if user.isAdmin() {
return res.Redirect("/admin")
}
return res.Redirect("/")
})
the problem is probably somewhere in res.Write
, but it looks like the Header application step of serving is ignored when content io.ReadSeeker
is nil, or something else is happening, not sure.
But I need cookies to set on redirects, it worked in echo
, it should work here.
package main
import (
"bytes"
"github.com/aofei/air"
)
var a = air.Default
func identicon(req *air.Request, res *air.Response) error {
return res.Write(bytes.NewReader(req.ParamValue("Name").Bytes()))
}
func main() {
a.DebugMode = true
a.GET("/identicons/:Name", identicon)
a.Serve() //8080
}
func airHandler(req *air.Request, res *air.Response) error {
return nil
}
func airHandlerWrite(req *air.Request, res *air.Response) error {
// io.WriteString(res, s)
return res.WriteString(req.Param("name").Value().String())
}
func airHandlerTest(req *air.Request, res *air.Response) error {
return res.WriteString(req.Path)
}
// func (a *air.Air) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// // a := air.New()
// a.server.ServeHTTP(r, w)
// }
func loadAir(routes []route) http.Handler {
h := airHandler
if loadTestHandler {
h = airHandlerTest
}
app := air.New()
for _, r := range routes {
switch r.method {
case "GET":
app.GET(r.path, h)
case "POST":
app.POST(r.path, h)
case "PUT":
app.PUT(r.path, h)
case "PATCH":
app.PATCH(r.path, h)
case "DELETE":
app.DELETE(r.path, h)
default:
panic("Unknow HTTP method: " + r.method)
}
}
return app
}
func loadAirSingle(method, path string, h air.Handler) http.Handler {
app := air.New()
// app.Middleware.Skip(nil, h)
switch method {
case "GET":
app.GET(path, h)
case "POST":
app.POST(path, h)
case "PUT":
app.PUT(path, h)
case "PATCH":
app.PATCH(path, h)
case "DELETE":
app.DELETE(path, h)
default:
panic("Unknow HTTP method: " + method)
}
return app
}
./router.go:557:6: cannot define new methods on non-local type air.Air
./router.go:559:3: a.server undefined (cannot refer to unexported field or method server)
./router.go:583:2: cannot use app (type *air.Air) as type http.Handler in return argument:
*air.Air does not implement http.Handler (missing ServeHTTP method)
./router.go:604:2: cannot use app (type *air.Air) as type http.Handler in return argument:
*air.Air does not implement http.Handler (missing ServeHTTP method)
The redirect from https://airwf.org to https://github.com/sheng/air currently flags an error in my browser as the certificate issued by Lets Encrypt is only valid until the 2nd of June 2017. It seems the (auto)renewal of it has failed.
<Tab>
to indentation.<Tab>
occupies 8 spaces.//
to comment.gofmt
to format all go files before git commit
.go test
to test whether the Air can server properly.the <link>
tag has several variations which don't always need pushing for example with preload
/favicon
pushing can disturb caching and cause needless bandwidth consumption and sometimes in the worst cases duplicate requests, so there should be a bit more specificity and potentially a feature to exclude/omit certain paths from the push list, (immutable/async cached assets assets that are very big)
see transplacer's take on this matter.
OPTIONS
is required for CORS Preflight: https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONSHEAD
is very useful for (custom) clients who want to check for the existence of a file without actually downloading it, e.g. link/image validation https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/HEADIt would be very nice to see a golang web framework handle gzip natively and do it well. There are various libraries and middlewares out there which purport a well adjusted and performant solution to serving gzipped content.
I've made a fairly primitive project some time ago, which provides an echo instance with the ability to read, monitor, cache and recache various static assets either within a specified folder or definitively located elsewhere; with this it would determine an asset's compress-ability and compress it thusly, serving it, thereby, only when a client's Accept-Encoding header indicates gzip support.
Desireable Features In a Gzipping Sollution:
- Cache Gzipped Assets:
cache-control
and etag
headers.- Compress at the highest level when caching, but automatically scale down with dynamic content.
Air does not seem to handle caching headers, (to my knowledge, I may be wrong), as all my coffer cached assets seem to be missing their cache-control
headers. While it would be possible to deliberately add such caching headers, it would certainly also have been nice had the air
sub systems managed cache headers when it detected that the higher level user has not set any or has not deliberately disabled cache-control
.
vmihailenco/msgpack has a fairly decent and easy to use golang msgpack implementation it would be great to see native support in air
, I've used echo and gin in the past and it would have been nice to see msgpack being handled natively the same way JSON is.
// WriteMsgPack responds to the client with the "application/msgpack" content v.
func (r *Response) WriteMsgPack(v interface{}) error {
var (
b []byte
err error
)
b, err = msgpack.Marshal(v)
if err != nil {
return err
}
r.Headers["content-type"] = &Header{
Name: "content-type",
Values: []string{"application/msgpack"},
}
return r.WriteBlob(b)
}
Also maybe there is a way to stream json and msgpack.
Streaming might be more performant and memory efficient than writing blobs.
But I'm not sure how to do it right and handle stream failures properly.
I'm using these functions in my Gin application
// SendMsgpack send a msgpack encoded response with a status code
func SendMsgpack(c ctx, code int, msg interface{}) error {
c.Status(code)
c.Header("Content-Type", "application/msgpack")
return msgpack.NewEncoder(c.Writer).Encode(msg)
}
// SendJSON send a json encoded response with a status code
func SendJSON(c ctx, code int, msg interface{}) error {
c.Status(code)
c.Header("Content-Type", "application/json")
return json.NewEncoder(c.Writer).Encode(msg)
}
ps. air 很牛,真的,谢谢你创造它
Simply cannot import /text/langauge for some reason.
go version
go version go1.11.2 windows/amd64
go get -u golang.org/x/text/language
go: finding golang.org/x/text/language latest
go get golang.org/x/text/language: no matching versions for query "latest"
on my DigitalOcean Debian server, there's been some trouble with these:
go: github.com/tdewolff/minify/[email protected]: go.mod has non-.../v2 module path "github.com/tdewolff/minify" (and .../v2/go.mod does not exist) at revision v2.3.7
go: error loading module requirements
though on my windows devbox it works fine.
on a side note, massive updates today, wow!
This project is growing and getting better everyday 😲, it's hard to keep up lol.
But it's all good, many of the changes in the last day have been breaking (to me at least), so
I'm going to stick to the vanilla version as it is and simply write my extentions
in an extention.go file as I see no reason to tediously duplicate all the awesome
progress and developments you're driving.
The only reason for my fork was to add a couple of convenience features, like:
req.Query("param")
is a nice to have feature.SetCookie(name, http.Cookie)
, or, gin style .SetCookie(name, all_the_params_laid_flat...)
req.GetCookie(name) -> *Cookie
And I see you've added many of these features already, so I'm wondering if
perhaps we could reach consensus on some of these features so that they can
potentially be integrated and made official.
Line 64 in e62e9ff
acm := autocert.Manager{
Prompt: autocert.AcceptTOS,
Cache: autocert.DirCache(ACMECertRoot),
}
if MaintainerEmail != "" {
acm.Email = MaintainerEmail
}
In the TOML maybe allow users to add maintainer_email
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.