go-ozzo / ozzo-routing Goto Github PK
View Code? Open in Web Editor NEWAn extremely fast Go (golang) HTTP router that supports regular expression route matching. Comes with full support for building RESTful APIs.
License: MIT License
An extremely fast Go (golang) HTTP router that supports regular expression route matching. Comes with full support for building RESTful APIs.
License: MIT License
Hi,
I wrote middleware for JWT authorization for your framework go-ozzo, ozzo-routing.
If You want i can transfer code of JWT for you without any limits from me
I have plan to write tests for this code and fix comments in code
https://github.com/vvv-v13/ozzo-jwt
Thanks.
Reading array query parameters doesn't seem to work with common non primitive types (eg. []time.Time
, []uuid.UUID
, etc.).
Example:
// url: http://localhost:8090/api/test?Names=test1&Dates=2020-10-11T21%3A00%3A00.000Z
data := &struct{
Names []string
Dates []time.Time
}{}
ctx.Read(data) // result: { Names: [ "test1" ], Dates: [] }
I guess if an alias type with custom encoding.TextUnmarshaler
is provided it would work, but that seems redundant because the non slice version is correctly unmarshalized.
Hi!
I think that you need to specify in README that the handler for serving static files must be the latest handler in the routing tree.
test code is:
package main
import (
"github.com/go-ozzo/ozzo-routing"
"github.com/go-ozzo/ozzo-routing/fault"
"log"
"net/http"
)
func main() {
router := routing.New()
router.Use(
fault.Recovery(log.Printf, func(c *routing.Context, err error) error {
c.Write(err)
return nil
}),
)
http.Handle("/", router)
http.ListenAndServe(":8123", nil)
}
on error occurred, it will log an additional message: http: multiple response.WriteHeader calls
2018/01/24 12:08:54 Not Found
2018/01/24 12:08:54 http: multiple response.WriteHeader calls
您好,
请问context中的变量data有什么作用呢,想把他利用起来,却无从下手,求解答。
Qiang, do you plan to develop ozzo like yii in the future? I like yii, but I think that my new project is to big for yii.
I would like to start developing a big project on golang using ozzo right now.)
But I would like to understand the perspectives...
Hi! I think this is a error:
token, err := auth.NewJWT(jwt.StandardClaims{
Id: id
}, signingKey)
func NewJWT(claims jwt.MapClaims, signingKey string, signingMethod ...jwt.SigningMethod) (string, error) {
var sm jwt.SigningMethod = jwt.SigningMethodHS256
if len(signingMethod) > 0 {
sm = signingMethod[0]
}
return jwt.NewWithClaims(sm, claims).SignedString([]byte(signingKey))
}
Hello,
In the API layer of my app, Every call can return HTTPError with various Status.
For exemple in case of a no found objet for a GET call I return :
return routing.NewHTTPError(http.StatusNotFound, err.Error())
The response head will be correctly set.
But when I use the http.StatusBadRequest in the exact same way (for example a POST with invalid validation):
return routing.NewHTTPError(http.StatusBadRequest)
The response header is set to 500 Internal Server Error instead of 400 Bad request.
Thanks,
Regards,
Arthur
In the following code, the slash remover works as expected when I do a GET request against /api/users/
package main
import (
"net/http"
"github.com/go-ozzo/ozzo-routing"
"github.com/go-ozzo/ozzo-routing/slash"
)
func main() {
router := routing.New()
router.Use(
slash.Remover(http.StatusMovedPermanently),
)
api := router.Group("/api")
api.Get("/users", func(c *routing.Context) error {
return c.Write("user list")
})
http.Handle("/", router)
http.ListenAndServe(":8080", nil)
}
curl -v http://localhost:8080/api/users/
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /api/users/ HTTP/1.1
> Host: localhost:8080
> User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
> Accept: */*
> Referer:
>
< HTTP/1.1 301 Moved Permanently
< Location: /api/users
< Date: Tue, 18 Apr 2017 14:46:41 GMT
< Content-Length: 45
< Content-Type: text/html; charset=utf-8
<
<a href="/api/users">Moved Permanently</a>.
However, when I put the handler declaration in the route group, by calling api.Use, the slash remover no longer works.
package main
import (
"net/http"
"github.com/go-ozzo/ozzo-routing"
"github.com/go-ozzo/ozzo-routing/slash"
)
func main() {
router := routing.New()
api := router.Group("/api")
api.Use(
slash.Remover(http.StatusMovedPermanently),
)
api.Get("/users", func(c *routing.Context) error {
return c.Write("user list")
})
http.Handle("/", router)
http.ListenAndServe(":8080", nil)
}
curl -v http://localhost:8080/api/users/
* Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
> GET /api/users/ HTTP/1.1
> Host: localhost:8080
> User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
> Accept: */*
> Referer:
>
< HTTP/1.1 404 Not Found
< Content-Type: text/plain; charset=utf-8
< X-Content-Type-Options: nosniff
< Date: Tue, 18 Apr 2017 14:47:57 GMT
< Content-Length: 10
<
Not Found
In our services we use version numbers in the accept like:
"application/json;v=1" - however in testing i found that gddo doesnt correctly parse the accept header in this form - see pull #30
It seems that the "Routing.context
" is handling a goroutine process, quite similar to the standard library "context
" package.
However, the standard library's "context
" interface have:
type Context interface {
Done() <-chan struct{}
Err() error
Deadline() (deadline time.Time, ok bool)
Value(key interface{}) interface{}
}
Is it possible to implement those methods in the "Routing.context
"?
I am using other library which uses the standard library "context
" as shwon
ctx := context.Background()
posts, resp, err := client.GetPosts.List(ctx, opt)
If the "Routing.context" implements the interface's methods, probably I can just wired the function in a routing handler as such
func getAllPost(c *routing.Context) error {
posts, resp, err := client.GetPosts.List(c, opt)
//...
}
Else, may I know what is the best way to create a context
within a routing context
?
Any reason not to implement the standard "context" method in "routing.context"? I am new to Go, may please advice... ^_^
I want to serve images, and those images are saved in a tree-structure directories. The images are saved in the directory based on their first 3 characters of their name.
Example:
If user:
GET /uploads/t4s1h9k0px12.jpg
, then serve /uploads/t/4/s/t4s1h9k0px12.jpg
GET /uploads/ya5sx76hgx21_b_adbj65xcgd16.jpg
, then serve /uploads/y/a/5/ya5sx76hgx21_b_adbj65xcgd16.jpg
How can I use the file.Server
? How to configure the file.PathMap
?
router.Get("/*", file.Server(file.PathMap{
"/": "/ui/",
}))
Do I need to implement a custom routing handler that process the URL, and then just use the standard http library http.ServeContent
to serve the corresponding file?
I receive 404 error while trying to request /
2016/01/02 15:33:17 [127.0.0.1] [0.095ms] GET / HTTP/1.1 404 9
using the example code
r.Get("", func(c *routing.Context) {
c.Write("Welcome, ozzo!")
})
If I change code to
r.Get("/", func(c *routing.Context) {...})
then request is successful
Tests are running successfully
Hi,强哥
在使用auth.JWT过程中,signingKey是根据二级域名动态变化的,那么我要如何使用 r.Use(auth.JWT(signingKey)) ?
I start two servers:
http on port 8080
https on port 8088
go func() {
s := app.C.GetString("WebServer.Domain") + ":" + app.C.GetString("WebServer.PortHTTPS")
l.Info("Start Serving HTTPS on " + s)
err := http.ListenAndServeTLS(s, "./ssl/cert.pem", "./ssl/key.pem", nil)
if err != nil {
l.Emergency(err.Error())
}
}()
s := app.C.GetString("WebServer.Domain") + ":" + app.C.GetString("WebServer.PortHTTP")
l.Info("Start Serving HTTP on " + s)
// Запуск HTTP сервера и редирект всех входящих запросов на HTTPS
err := http.ListenAndServe(s, http.HandlerFunc(redirectToHttps))
if err != nil {
l.Emergency(err.Error())
}
If i connecting to port 8088 without https begins, Chrome will download a file as follows:
0000000: 1503 0100 0202 0a
What this?
Hi! I try to run code sample:
r := routing.NewRouter()
// serves the files under working-dir/web/assets
r.To("/assets(/.*)?", routing.Static("web"))
But Error is:
not enough arguments in call to routing.Static
if I use:
// serves the files under working-dir/web/assets
st := routing.StaticOptions{"", "", nil}
r.To("(/.*)?", routing.Static("/", st))
everything is working
Thanks!
I have a struct Person
with custom JSON MarshalJSON
and UnmarshalJSON
methods. When I use the the Write()
in a routing handler, it skips these custom methods and use the default JSON marshal/unmarshal.
func GetPerson (c *routing.Context) error {
// ...
return c.Write(p) // print JSON with default JSON method, expect custom marshal to be used
}
However, if I wrap the struct in another struct or slice, e.g. :
type User struct {
UserID int `json:"userID"`
Details Person `json:"details"`
}
Or
[]Person{}
and c.Write(...)
these values, the custom marshal methods is used.
E.g.
func GetPerson (c *routing.Context) error {
u := User{}
// ... more code
return c.Write(u) // the custom marshal methods in Person is used (e.g. Birthday in Person have the correct time format)
}
func GetPeople (c *routing.Context) error {
people := []Person{}
// ... more code
return c.Write(people) // the custom marshal methods is being used too (e.g. time format is converted as expected)
}
Is it a bug?* I guess it is something related to http Writter*... Hmmm... may please have a look? :)
Note: the Person
struct is included below
type Person struct {
Name string `json:"name"`
Birthday time.Time `json:"birthday"`
Hobbies []Sharing `json:"hobbies"`
}
// MarshalJSON marshal struct.
// - Convert empty slice to "[]" instead of "null"
// - Custom manipulation to certain fields
// - Output time.Time in specific time format used by the app
func (m *Person) MarshalJSON() ([]byte, error) {
type Alias Person
if m.Hobbies == nil {
m.Hobbies = make([]Sharing, 0) //convert to empty array if slice is nil
}
return json.Marshal(&struct {
Name string `json:"name"`
Birthday string `json:"birthday"`
*Alias
}{
Name: "Oh, you need to guess it!", //custom manipulation
Birthday: app.TimeToString(m.Birthday), //change time format
Alias: (*Alias)(m),
})
}
// UnmarshalJSON unmarshal JSON to struct data
func (m *Person) UnmarshalJSON(data []byte) error {
type Alias Person
aux := &struct {
Birthday string `json:"birthday"`
*Alias
}{
Alias: (*Alias)(m),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
t, err = app.StringToTime(aux.Birthday)
if err != nil {
return err
}
m.Birthday = t
return nil
}
In PHP we create root folder and project in it. Such as:
root
-config
-controllers
-models
-views
-utils
-vendor
etc.
My project is an angular.js project.
I need to have one or more index.html file(s) which will load some .js and .css files.
And then Angular.js on frontend will use REST API on backend.
Golang is not a PHP.
Qiang, what is the best way to organaize a project in the root folder?
What do you think about this?
Thanks!
Hi! I try to find the way to populate DDD aggregate with simple joined query. At this moment it possible only by giving all needed fields in select query. I whant to use this way to populate all struct with nested struct fields at once.
https://stackoverflow.com/a/13153422
For example:
type Wagon struct {
Wagon
State WagonState
Location WagonLocation
}
with
...
Select(
"w.*",
"ws.*",
"wl.*"
).From("wagon w").
InnerJoin("wagon_state ws", dbx.NewExp("ws.id=w.state_id")).
InnerJoin("wagon_location wl", dbx.NewExp("wl.id=w.location_id")).
...
Is it possible to add to this lib?
the router sets for each error case a content type "text/plain" but that behavior is to static. Could you introduce a customizable error handler that the user can decide self what kind of content he wants sending to the cunsomer back or you could extending the collection of http errors (JSON, XML, Text, etc) and error matching.
Behavior of content type
Type
https://tools.ietf.org/search/rfc2616#section-7.2
Entity body
https://tools.ietf.org/search/rfc2616#section-7.2.1
Hi!
How to rewrite all incoming request to index.html exclude existing routes, such as /api and other?
It's for https://github.com/ui-router/quickstart-ng2 (HTML5 mode)
func main() {
// r := routing.New()
// r.Use(auth.Basic(func(c *routing.Context, username, password string) (auth.Identity, error) {
// if username == "demo" && password == "foo" {
// return auth.Identity(username), nil
// }
// return nil, errors.New("invalid credential")
// }))
// r.Get("/demo", func(c *routing.Context) error {
// fmt.Fprintf(res, "Hello, %v", c.Get(auth.User))
// return nil
// })
// }
})) - lost closing bracket in example
why don't you use your http router as your main router (stable high performance). (fasthttp,gin and ozzo-routing and unexpectedly slow in tests)
Hi!
How to set default charset UTF-8 for json writer?
by default I see:
HTTP/1.1 200 OK
Content-Type: application/json
Date: Tue, 16 May 2017 16:55:58 GMT
Transfer-Encoding: chunked
强哥,context中的router是否可以放在router的结构体中呢?该怎么做
Im want to do some permission check in middleware.
It would be great adding support for fasthttp in ozzo-routing. Fasthttp is extremely fast and it doesn't allocate memory in fast paths. So fasthttp-backed ozzo-routing will allow writing low-overhead http servers with advanced routing capabilities.
I was going through the documentation and I saw the explanation given about error handling.
What I am trying to achieve is being able to return an html file in a situation where the endpoint is not provided. I wanted to just go ahead and add my function for 404/not found errors.
But, I was concerned about it interfering with situations where I return a 404 itself. E.g: When a user makes a request to get information about a user and the user isn't available.
Your response and suggestion would be greatly appreciated.
Thanks
强哥,当我调用Use()后
router.Use(
// all these handlers are shared by every route
access.Logger(log.Printf),
slash.Remover(http.StatusMovedPermanently),
fault.Recovery(log.Printf),
)
之后的操作我没太明白,access.Logger(log.Printf),slash.Remover(http.StatusMovedPermanently),fault.Recovery(log.Printf),在以后的程序中是如何使用的呢?
Hi,强哥:
一直想问您,有没有写关于server优雅重启的组件。热更新配置,http请求超时处理这些功能的组件。
the performance is comparative to that of httprouter and gin
Do you have benchmarks that show this?
I'm trying to write a unit test, as I would in Express+Supertest. I'm finding that when I provide a test URL, that the parameters are not parsed.
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/go-ozzo/ozzo-routing"
"github.com/go-ozzo/ozzo-routing/content"
"github.com/stretchr/testify/assert"
)
func TestContextParamsPopulatedByOzzo(test *testing.T) {
assert := assert.New(test)
// Initialize app
router := routing.New()
router.Get("/test/<id>", routing.NotFoundHandler)
// Mock up a request
res := httptest.NewRecorder()
req, err := http.NewRequest("GET", "/test/23", nil)
assert.NoError(err)
// Mock up a routing context
routeCtx := routing.NewContext(res, req)
// Sanity check
assert.Equal("23", routeCtx.Param("id"))
}
Hi!
ozzo-config is a Go package that supports request routing and processing for Web applications.
Is this correct?
Hi!
Is a way to bypass handler in server func? I try to find way to bypass auth handler for public routes.
Or the best way to have diferent routes for private and public?
Hi!
I think we need to create a common repository for discussion on common framework questions and future requests.
Hi!
How to do this correctly?
https://github.com/jung-kurt/gofpdf
Thanks!
It seem setting a data writer through Context.SetDataWriter() doesn't make Context.Write call the SetHeader()
I suppose that is a bug since (to be symmetric) Context.Read() does take the Content-Type header into account.
hi~,I do not know how to use the Use() after seeing the example ,how can i use?Could you give a example ?
thanks
Hi! I Got issue when there is no way to get data with content-type app/json (while urlencoded form works fine)
I tried both of methods (in source code they looks similar):
email := c.PostForm("email")
email := c.Form("email")
Also tried context.Read()
like it was shown in README but with no result - also empty response.
Here is the example of my request:
POST http://localhost:8080/api/user/username/create HTTP/1.1
Accept: application/json
Content-Type: application/json
{
"about": "About me.",
"email": "[email protected]",
"fullname": "John Smith"
}
All of theese fields are empty in c *routing.Context
. Can you help me and show me what I'm doing wrong? Thanks in advice!
Hi!
Are you planning to add VGO support?
Hi!
I am using content.TypeNegotiator(content.JSON)
But for some reason there is no encoding set (charset=UTF-8).
How do I better set the response encoding for the all application at once?
Thank you!
how to serving static file from go-binddata-assetfs files?
thanks
We use c.Set("isUser", true)
to pass data to other handlers, sometimes in complex functions, we may use a few handlers inside a handler, some handlers may required some internal data to be set while other handlers do not need those data, so hope to have a function to "delete" the context.data
func abc123(c *routing.Context) error {
c.Set("name1", true)
err := cde123(c)
c.Delete("name1") // <-- hope to have something like that to delete internal data
err := cde123(c)
return nil
}
What is the best way to working with subdomains in ozzo-routing?
I would like to be able to take a URI from the body of an HTTP request, something like:
/products/1234
and programmatically determine that this matches to a route:
/products/{id}
with "id" = 1234. This is obviously something the ozzo-routing framework is doing internally, and from a cursory inspection it looks like it could probably be accomplished by exposing the "store" object publicly.
Does this make sense? I'm happy to have a look at how it could be done in a separate fork... would a PR be considered if I can get it to work?
I am missing the abillity to find out which route actually matched.
The use case for this would be for example rendering a menu and highlighting the item matching the current route.
Dear Qian,
I use Yii1/2 for create some web solutions:) Thanks for your fantastic framework.
We know the trend will be more JS frontend + RESTful backend, so that may be your reason to start pay time to golang, and create new web framework.
Could you advise what is the meaning of ozzo?
In one of your article, you compare many routing fw, do the ozzo will be beat them:)
And what is your philosophy and road map for this ozzo web framework?
I would like to be act as early adopter:) Thanks.
Regards,
Scott Huang
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.