go-goyave / goyave Goto Github PK
View Code? Open in Web Editor NEWπ The enterprise REST API framework
Home Page: https://goyave.dev
License: MIT License
π The enterprise REST API framework
Home Page: https://goyave.dev
License: MIT License
Your work on this project is amazing. I think it's the most accurate docs ever seen for a Go framework.
But I think it would also be nice to create a "real demo" repo both to learn even better the "best practices" for proper use and to use as a benchmark in the following projects:
And it's better for the author himself to use his framework for those benchmarks rather than someone who doesn't understand 100% how to best use it.
What do you think about it?
Thanks again for the wonderful work!
It is currently not possible to add extra data to requests other than using request.Data
or request.User
. http.Request
has WithContext()
, which allows to add a context (WithValue()
) to it.
Extra data in requests would allow middleware to process data that is not part of the request's body.
The simplest solution would be to add a map[string]interface{}
named Extra
to the request structure. Initialize it empty to avoid memory usage.
None
.
To make rate limiting easier, a middleware could be developed. This middleware would use a new config entry making it possible to adjust the rate easily. The real goal is to make a basic rate limiter middleware, which would cover most cases and be easy to use, mostly to protect from attacks.
The middleware will have to correctly set the following headers, following this IETF spec:
RateLimit-Limit
: the rate limit ceilingRateLimit-Remaining
: the number of requests leftRateLimit-Reset
: the number of seconds until the quota resetsNote: the IETF spec doesn't use the X-
header prefix, unlike popular APIs such as Github's. It would be worth making some research to know if it would be better to add the X-
prefix or keep it as defined in the IETF spec.
In case of cancelled request because of limiting, the middleware would be stopping (don't call next()
) and would respond with the HTTP status 429 Too Many Requests
, in accordance with RFC 6585
. The default status handler can be kept and developers will be able to define the behavior of their choice when a request is rate limited.
Limiting will be done using an in-memory storage directly implemented in the middleware. A simple map and a struct containing the user's information (IP, time frame, remaining requests) are probably more than enough. The storage needs to be thread-safe, as requests can be served in parallel.
The official go package golang.org/x/time/rate
could be used, but it would need to be extended a little bit to support multiple clients. We want to limit IPs that keep requesting the server, but not the other legitimate users.
I would like to start with a simple rate limiter, as mentioned above, but a more advanced rate limiter could be developed next to it later on. There is no design or clear requirements specification for it yet. For example, this advanced rate limiter could:
X-Forwarded-For
and X-Real-IP
headers if the application is running behind a reverse proxyEither way, this middleware has to be compliant with previously mentioned IETF spec.
Rate limiting can have a slight impact of performance, and especially on memory usage if using in-memory storage. However, it is a mandatory feature for public APIs and well worth the upfront cost.
This issue is a feature proposal and is meant to be discussed.
It is also a good candidate if you want to contribute to the project.
Create a CLI Utility called goyave-cli
or gyv
to make Goyave development easier. The utility would be an interactive, a bit like gh
go test
)None
.
This issue is a feature proposal and is meant to be discussed. If you have any other idea for this CLI Utility, feel free to suggest it!
It is also a good candidate if you want to contribute to the project.
This should probably be developed as a side-project.
Is there already an authentication system backed in? I couldn't find anything.
Go's 1.16 new embed feature is great to bundle static resources into the binary, making it easier to distribute it. Currently, the frameworks relies on a non-interfaced filesystem, which makes it a bit harder to use embedded resources. Only the configuration supports it. I would like to provide a solution for developers wanting to embed their files.
router.Static()
, but taking io/fs.FS
as a parameter.io/fs.FS
to load language files. (This may require a bit of refactoring into the framework so it's possible to load a language file by file)helper/filesystem
package so it works with io/fs
too.On top of adding the ability to embed files, this would also let developers use virtual filesystems and fetch files from other sources more easily. However, the io/fs packge is still a bit young in my opinion, and lacks interfaces for writable FS. I wouldn't want to create a temporary non-standard interface that will probably not be compatible with a potential future standard one. So for now, this issue will stay on standby until more development on the io/fs package.
Because the embed feature is only available in go 1.16+ and that the With v4, I dropped go versions < 1.16.io.FS
interface is required for what I would like to achieve here, we can't build this into the framework without breaking compatibility with prior versions. I don't want to stop supporting older versions (yet), so we could create an external library. Later on, we could consider merging this library into the framework.
None
.
This issue is a feature proposal and is meant to be discussed. The design is not set yet neither.
It is also a good candidate if you want to contribute to the project.
Hi,
I am evaluating this framework, and based on the journey I would also try to contribute. π
Just one remark for the moment: since the generated project includes - besides the /hello
- also a /echo
implementation, a cURL example how to call it might help also. Something like this:
curl -G -w '\n' http://localhost:8080/echo -d text=abc123
abc123
$
$ curl -G -w '\n' http://localhost:8080/echo --data-urlencode 'text=abc 123'
abc 123
$
Expand the placeholder system currently used in validation lines to be usable in any localized string. It could be possible to add support for pluralization at the same time: the ability to add a string somewhere in the language line depending on a parameter or the value of a placeholder.
This potential feature's target usage is not defined yet, feel free to suggest one.
Depending on the implementation, using localization may have a little bit bigger impact on performances.
This issue is a feature proposal and is meant to be discussed.
It is also a good candidate if you want to contribute to the project.
Version: 2.10.2
Environment: Ubuntu 20.04, Go 1.14.6
Reproduces: always
Validation error: "validation.rules.size.unsupported" when a field is validated with type-dependent rule and it's entirely absent from the request body.
Expected result:
The message shouldn't be shown or should use a generic message.
With the following rule set:
var (
TestRequest validation.RuleSet = validation.RuleSet{
"test": {"required", "string", "size:2"},
}
)
Send a request with the following body:
{}
Response is:
{
"validationError": {
"test": [
"The test is required.",
"The test must be a string.",
"validation.rules.size.unsupported"
]
}
}
Sometimes it could be handy to be able to use another rule set inside a larger rule set by using composition. Example:
CreateUserRequest = validation.RuleSet{
"email": {"required", "email"},
"password": {"required", "min:6"},
}
CreateManyUsersRequest = validation.RuleSet{
"users": {"required", "array:object"},
"users[]": CreateUserRequest,
}
Note: could use an interface so both types ([]string{}
and RuleSet
) can be used as a value inside a RuleSet. Don't forget about alternative syntax too!
None
.
Guards are an extension of the authentication system using user-defined fields from the authenticator's user model to allow or deny specific actions to an authenticated user.
For example, a Goyave application will define a guard for forums moderation. A moderator is allowed to modify the posts of other users, but regular users aren't. A guard update-others
will be implemented, using the IsModerator
field from the user model and the route parameter to check if the user is a moderator or if its own post.
Guards could be used in two ways:
This system could support OAuth in some way too.
The implementation is not defined yet, so feel free to discuss and suggest one.
None
.
This issue is a feature proposal and is meant to be discussed.
It is also a good candidate if you want to contribute to the project.
The Goyave summary of Gorm's migration is incorrect. Gorm states that tables, columns, and indexes are create. Goyave states that columns and indexes won't be created.
From the Gorm documentation:
AutoMigrate will ONLY create tables, missing columns and missing indexes, and WONβT change existing columnβs type or delete unused columns to protect your data.
As written in Goyave:
Automatic migrations only creates tables. Missing columns and indexes won't be created, modified columns won't be changed and unused columns won't be deleted.
Version: v3.8.0
Environment: Ubuntu 20.04, Go 1.16
Reproduces: rarely
Because validation.Rules
is a map, iteration order is not guaranteed, meaning that rules that rely on a certain order of validation (such as dates before/after) and where conversion is needed will randomly not pass even if the request is valid.
Potential fix: pre-process sorted list of keys by checking presence of field comparison rules
Migrate from the dgrijalva/jwt-go library to the maintained golang-jwt/jwt.
Breaking change because of import paths.
Route parameter converters are functions converting route parameters into another type of data, typically models. The main use-case would be to create a built-in url converter for models removing parameter int conversion and SQL query from the controller.
For example, for the following route definition:
GET /user/{User}
The route parameter converter would take the "User" route parameter and search for the "User" registered model based on its primary key (defined by the gorm tag) in database. If no record is found, then the route will not match and a 404 error will be returned.
This feature could be implemented in a middleware or in the core of the router. However, for performance reasons, a middleware called after the route matched with the current simple matching process would be preferred. That would avoid a lot of unnecessary SQL queries.
Developers using the framework should be able to implement route parameter converters. How to define which converter to use when defining a route is a question that remains open.
It may be difficult to handle multi-parameter routes and especially relations between models. For example, the following route is retrieving a forum post from the author "User":
GET /user/{User}/post/{Post}
How could we check and guarantee that the Post is related to User? Should we use the gorm field tags? What if there are multiple foreign keys to the same table?
An expensive work of reflection may be needed for this kind of use-case.
This issue is a feature proposal and is meant to be discussed.
It is also a good candidate if you want to contribute to the project.
Goyave is a very powerful framework but it is not reaching many gophers because you have not been leveraging social media and other platforms to reach developers.
Reach more Gophers and more contributors
I am a beginner in Golang and would love to contribute to this framework by promoting it to gophers.
Add support for websockets by building an adapter for gorilla's websocket library.
None
.
This issue is a feature proposal and is meant to be discussed.
It is also a good candidate if you want to contribute to the project.
This could be built as a separate project.
Currently, the built-in JWT is using jwt.SigningMethodHS256
. Using another method is not possible without re-implementing entirely the GenerateToken
function and the JWTController
. Adding support for customizable signing method, and more specifically, supporting asymmetric signing methods. That would enable federated or central authentication without leaking the JWT secret, which is an obvious security concern.
Implementation details can be discussed below.
None
.
Hello, firstly thank you for this project.
Add the context goyave.Request
in the validation.
This gives the possibility to create custom validations with parameters from the Request like the user.
Current custom validation from the documentation:
func validateCustomFormat(field string, value interface{}, parameters []string, form map[string]interface{}) bool {
str, ok := value.(string)
if ok { // The data under validation is a string
return regexp.MustCompile(parameters[0]).MatchString(str)
}
return false // Cannot validate this field
}
Proposal:
func validateUserIsAdmin(request *Goyave.Request, field string, value interface{}, parameters []string, form map[string]interface{}) bool {
if value != nil {
user := request.User.(*model.User)
userIsAdmin := user.isAdmin
return userIsAdmin
}
return true
}
With the fields in Request.Extra this opens more possibility to create validations that match use cases.
A changes in the organization of structures to avoid cyclical imports.
Version: v2.2.0
Commit: bc72e19
Version: v2.2.0
Environment: Mac Catalina, go1.13.4
Hi, I just noticed this when I tried to consume API within my vuejs app, it always blocked by CORS. I did use package "github.com/rs/cors" on middleware, but still can't solve it. And it said "OPTIONS 405 (Method Not Allowed" which I guess I handled on middleware.
first, I tried manual way to handle cors through middleware:
func EnableCORS(next goyave.Handler) goyave.Handler {
return func(response *goyave.Response, request *goyave.Request) {
(*response).Header().Set("Access-Control-Allow-Origin", "*")
(*response).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
(*response).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
(*response).Header().Set("Content-Type", "application/json")
(*response).Header().Set("Content-Type", "text/html; charset=utf-8")
(*response).Header().Set("Access-Control-Allow-Credentials", "true")
log.Println(request.Method())
if (*request).Method() == "OPTIONS" {
response.WriteHeader(http.StatusOK)
return
}
next(response, request) // Pass to the next handler
}
}
And I tried to use this pkg too "github.com/rs/cors" on the route register:
routers := router.Subrouter("/")
middlewareCors := goyave.NativeMiddleware(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
handler := cors.AllowAll().Handler(next)
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
handler.ServeHTTP(w, r) // Don't call "next" if your middleware is blocking.
})
})
routers.Middleware(middlewareCors)
But none of them can solve cors or handle Preflight request. Or I miss something...
Can you give me example of handling cors with goyave? That would be great.
Thanks!
Version: v2.2.0
Environment: Mac Catalina, go1.13.4
Reproduces: always
Hi,
I tried to handle raw json request with Request.Data["key"], but got nil, first I sent this as my request on postman body raw json:
{
"name": "John Doe",
"tags": ["tag1", "tag2"]
}
Then I log print out the result, got this:
map[]
And I also tried the Request.Integer(), Request.Bool() and some of them got error like this:
#Case Request.Integer()
Field \"test\" is not an integer
#Case Request.Bool()
Field \"test\" is not a bool
And this is log on terminal:
2020/01/02 12:16:49 Server is running on port: 8090
2020/01/02 12:16:54 Field "test" is not an integer
2020/01/02 12:16:54 Field "test" is not an integer
goroutine 35 [running]: runtime/debug.Stack(0x10e47ec, 0xc0000b2000, 0x2)
/usr/local/Cellar/go/1.13.4/libexec/src/runtime/debug/stack.go:24 +0x9d
runtime/debug.PrintStack()
/usr/local/Cellar/go/1.13.4/libexec/src/runtime/debug/stack.go:16 +0x22
github.com/System-Glitch/goyave/v2.(*Response).Error(0xc00000e0a0, 0x148e4a0, 0xc000020190, 0xc0000c3748, 0x100dbc6)
/Users/ridwankustanto/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/response.go:118 +0x96
github.com/System-Glitch/goyave/v2.recoveryMiddleware.func1.1(0xc00000e0a0)
/Users/ridwankustanto/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/middleware.go:25 +0x4b
panic(0x148e4a0, 0xc000020190)
/usr/local/Cellar/go/1.13.4/libexec/src/runtime/panic.go:679 +0x1b2
log.Panicf(0x1549f5c, 0x1c, 0xc0000c3810, 0x1, 0x1)
/usr/local/Cellar/go/1.13.4/libexec/src/log/log.go:345 +0xc0
github.com/System-Glitch/goyave/v2.(*Request).Integer(...)
/Users/ridwankustanto/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/request.go:127
karmapala-backend/http/controller/user.Register(0xc00000e0a0, 0xc0002960a0)
/Users/ridwankustanto/go/src/gitlab.com/ridwankustanto/karmapala-backend/http/controller/user/user.go:24 +0x137
github.com/System-Glitch/goyave/v2.validateRequestMiddleware.func1(0xc00000e0a0, 0xc0002960a0)
/Users/ridwankustanto/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/middleware.go:106 +0xa5
karmapala-backend/http/middleware.EnableCORS.func1(0xc00000e0a0, 0xc0002960a0)
/Users/ridwankustanto/go/src/gitlab.com/ridwankustanto/karmapala-backend/http/middleware/cors.go:26 +0x580
github.com/System-Glitch/goyave/v2.languageMiddleware.func1(0xc00000e0a0, 0xc0002960a0)
/Users/ridwankustanto/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/middleware.go:139 +0xa9
github.com/System-Glitch/goyave/v2.parseRequestMiddleware.func1(0xc00000e0a0, 0xc0002960a0)
/Users/ridwankustanto/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/middleware.go:56 +0x118
github.com/System-Glitch/goyave/v2.recoveryMiddleware.func1(0xc00000e0a0, 0xc0002960a0)
/Users/ridwankustanto/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/middleware.go:29 +0x77
github.com/System-Glitch/goyave/v2.(*Router).requestHandler(0xc0002545a0, 0x15f2220, 0xc0002c6000, 0xc0002a6200, 0x1561998, 0x0)
/Users/ridwankustanto/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/router.go:120 +0x147
github.com/System-Glitch/goyave/v2.(*Router).Route.func1(0x15f2220, 0xc0002c6000, 0xc0002a6200)
/Users/ridwankustanto/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/router.go:55 +0x5a
net/http.HandlerFunc.ServeHTTP(0xc0002547e0, 0x15f2220, 0xc0002c6000, 0xc0002a6200)
/usr/local/Cellar/go/1.13.4/libexec/src/net/http/server.go:2007 +0x44
github.com/gorilla/mux.(*Router).ServeHTTP(0xc0000d8600, 0x15f2220, 0xc0002c6000, 0xc0002c0000)
/Users/ridwankustanto/go/pkg/mod/github.com/gorilla/[email protected]/mux.go:212 +0xe2
net/http.serverHandler.ServeHTTP(0xc000248380, 0x15f2220, 0xc0002c6000, 0xc0002c0000)
/usr/local/Cellar/go/1.13.4/libexec/src/net/http/server.go:2802 +0xa4
net/http.(*conn).serve(0xc0002b0000, 0x15f36e0, 0xc0002bc000)
/usr/local/Cellar/go/1.13.4/libexec/src/net/http/server.go:1890 +0x875
created by net/http.(*Server).Serve
/usr/local/Cellar/go/1.13.4/libexec/src/net/http/server.go:2927 +0x38e
Expected result:
Got value on a specific key.
Anyway, happy new year everyone!! πππ
On the Table of Contents, the first link says Leaning, instead of Learning. It is missing the letter 'r' after the letter 'a'.
Is this loosly based on PHP Laravel framework?
v2.10.1 is expected to be the last release before v3, unless critical issues have to be addressed while developing this new major version.
v3 will contain a number of breaking changes. To avoid moving to a new major version too often, required breaking changes are pushed back as much as possible and grouped into a single release.
For the moment, v3 will contain the following changes:
init()
functionrequest
package and move rule sets to a requests.go
file inside the controller packages. This change would make route definition cleaner and easier, and the directory structure lighter. The requests package naming was inconvenient too.Before the development of v3 starts, please let me know if you think of any breaking or major change that you think would be good for the framework, and feel free to discuss the points above.
The "unique" validation rules checks if a resource doesn't exist. If you just want to know if a resource exists, you currently have to implement a custom validation rule. I'd like to add the "exists" validation rule into the framework directly.
None
.
Version: v2.3.0
Environment: [OS Windows 10, Go version go1.12.5]
Now I'm using Postgres as my database client, in config.json
I already add dbOptions sslmode=disable
, but the error always occurred.
Relevant logs: (if needed)
2020/01/02 17:05:36 pq: SSL is not enabled on the server
goroutine 21 [running]:
runtime/debug.Stack(0x4ebc43, 0xc00008c000, 0x2)
C:/Go/src/runtime/debug/stack.go:24 +0xa4
runtime/debug.PrintStack()
C:/Go/src/runtime/debug/stack.go:16 +0x29
github.com/System-Glitch/goyave/v2.(*Response).Error(0xc0001d6920, 0x82b6c0, 0xc0001864e0, 0xc000079638, 0x0)
C:/Users/Frontend/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/response.go:118 +0x9d
github.com/System-Glitch/goyave/v2.recoveryMiddleware.func1.1(0xc0001d6920)
C:/Users/Frontend/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/middleware.go:25 +0x52
panic(0x82b6c0, 0xc0001864e0)
C:/Go/src/runtime/panic.go:522 +0x1c3
github.com/System-Glitch/goyave/v2/database.newConnection(0x894e00)
C:/Users/Frontend/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/database/database.go:73 +0x2c7
github.com/System-Glitch/goyave/v2/database.GetConnection(...)
C:/Users/Frontend/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/database/database.go:22
spp-online/database/model.User.GetBy(0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)
D:/Ervan/Ext/spp-online/database/model/user.go:56 +0x284
spp-online/http/controller/auth.signIn(0xc0001d6920, 0xc0001727d0)
D:/Ervan/Ext/spp-online/http/controller/auth/auth.go:23 +0x91
github.com/System-Glitch/goyave/v2.validateRequestMiddleware.func1(0xc0001d6920, 0xc0001727d0)
C:/Users/Frontend/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/middleware.go:135 +0xac
github.com/System-Glitch/goyave/v2.corsMiddleware.func1(0xc0001d6920, 0xc0001727d0)
C:/Users/Frontend/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/middleware.go:84 +0x160
github.com/System-Glitch/goyave/v2.languageMiddleware.func1(0xc0001d6920, 0xc0001727d0)
C:/Users/Frontend/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/middleware.go:168 +0xb2
github.com/System-Glitch/goyave/v2.parseRequestMiddleware.func1(0xc0001d6920, 0xc0001727d0)
C:/Users/Frontend/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/middleware.go:56 +0xfa
github.com/System-Glitch/goyave/v2.recoveryMiddleware.func1(0xc0001d6920, 0xc0001727d0)
C:/Users/Frontend/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/middleware.go:29 +0x70
github.com/System-Glitch/goyave/v2.(*Router).requestHandler(0xc000171170, 0x940b00, 0xc0001e40e0, 0xc000180b00, 0x8c21b8, 0xc0001709c0)
C:/Users/Frontend/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/router.go:149 +0x165
github.com/System-Glitch/goyave/v2.(*Router).route.func1(0x940b00, 0xc0001e40e0, 0xc000180b00)
C:/Users/Frontend/go/pkg/mod/github.com/!system-!glitch/goyave/[email protected]/router.go:73 +0x61
net/http.HandlerFunc.ServeHTTP(0xc0001d6680, 0x940b00, 0xc0001e40e0, 0xc000180b00)
C:/Go/src/net/http/server.go:1995 +0x4b
github.com/gorilla/mux.(*Router).ServeHTTP(0xc0000e8540, 0x940b00, 0xc0001e40e0, 0xc000206000)
C:/Users/Frontend/go/pkg/mod/github.com/gorilla/[email protected]/mux.go:212 +0xea
net/http.serverHandler.ServeHTTP(0xc000050ea0, 0x940b00, 0xc0001e40e0, 0xc000206000)
C:/Go/src/net/http/server.go:2774 +0xaf
net/http.(*conn).serve(0xc00016d540, 0x941900, 0xc0001ea040)
C:/Go/src/net/http/server.go:1878 +0x858
created by net/http.(*Server).Serve
C:/Go/src/net/http/server.go:2884 +0x2fb
Every querying data
Every querying data
Version: v2.2.0
Commit: bc72e19
Hi, thank you for making this framework! I found it on Medium post, and it looks promising and I would give it a try for my next project.
But recently, I try to install and gave log a bit for knowning what app and port that I was running on with goyave config, everything was fine, till I try to dockerize this app. It was running but the config file fell into default.json, I use FROM alpine:3.9 as my production build phase:
FROM golang:alpine as builder
.
.
.
FROM alpine:3.9
RUN apk add --no-cache tzdata
ENV TZ Asia/Jakarta
COPY --from=builder /go/pkg/mod/github.com/!system-!glitch/goyave/ /go/pkg/mod/github.com/!system-!glitch/goyave/
COPY --from=builder /app/config.json /app/
COPY --from=builder /app/resources /app/resources
COPY --from=builder /app/app /app/app
# Run the binary.
ENTRYPOINT ["/app/app"]
docker-compose up and the container was running, but when I hit the default port for localhost:8080, the server not actually running.
Did I do wrong? What files that I need to copy in order to make the binary runs? as you can see I already copy config.json and resources as you mentioned on documents.
Thanks once again! π
Version: v3.6.0
Environment: Ubuntu 20.04, Go 1.15.6
Reproduces: always
This is not really a bug. Requests that don't match any route (404 or 405) are not logged by the logging middleware, because middleware are only executed if a route is matching.
Expected result:
Logging should probably log all requests, including 404 and 405.
router.Middleware(log.CombinedLogMiddleware())
Version: v2.10.2
Environment: Ubuntu 20.04, go 1.14.6
Reproduces: always
response.Render()
writes status header before checking if template renders, preventing the return of 500 error in case of error.
Take this opportunity to add an example of usage with error handling to documentation.
Version: v3.0.0
Environment: Mac OS Catalina, Go version go1.15.1 darwin/amd64
Reproduces: always
Setting a route poining to the root route ("/") return
{"error":"Not Found"}
Relevant logs: (if needed)
No logs present
Setting a route in route.go:
router.Get("/", page.Index)
Expected result:
Describe the expected result and how it differs from the actual result.
Point any route to "/" and start the server, then open browser and point to http://127.0.0.1:8080/
Goyave currently doesn't provide any built-in way to log activity or errors. You can however implement a middleware yourself and use chained writers if needed. Logging is an important part of all applications so a flexible implementation should be added to the framework. How logging is made in an application should still be decided by the developer, not the framework.
One or multiple interfaces will be needed and they should fit most (or all) popular logging libraries (such as logrus). A default logger can be provided.
The logging feature should allow:
The implementation is not defined yet, so feel free to discuss and suggest one.
None
.
This issue is a feature proposal and is meant to be discussed.
It is also a good candidate if you want to contribute to the project.
Version: v2.10.0
Can you please provide an example of a JSON body request controller with validation?
Hi all.
Before using the framework I usually care about its performance. Have you tried this framework benchmark?
You can refer here about benchmark: https://github.com/smallnest/go-web-framework-benchmark
Version: v3.10.0
Environment: Ubuntu 20.04, Go 1.16.2
Reproduces: always
The CORS options used by requestHandler
is always the one from the main router, meaning CORS options defined on subrouters won't work as expected.
I propose to support custom claims in the generated JWT token.
The user fields to be included as claims could be specified by adding auth:"jwtInclude"
(to follow current auth
prefix).
This would allow people putting custom information in the token, e.g. when thinking about username, some additional name fields or permissions (I saw you're planning support in the future).
By default - none, if someone uses too many fields then the token will be heavy, but that's up to user of the framework.
I think I can handle this contribution if you agree.
Version: 3.7.1
Environment: Ubuntu 20.04
Reproduces:
For the Given struct :
type MyStruct struct {
gorm.Model
ID uint `gorm:"primarykey"`
PosX float64
PosY float64
PosZ float64
}
"pos_x": {"required", "numeric"},
"pos_y": {"required", "numeric"},
"pos_z": {"required", "numeric"},
pos_x: -970.4351,
pos_y: -664.2330,
pos_z: 44.2087,
random := model.MyStruct{}
if err := request.ToStruct(&random); err != nil {
panic(err)
}
fmt.Print(random.PosX)
// 0.000000
Expected result:
fmt.Print(random.PosX)
// -970.4351
Problem from ToStruct() ?
Naming convention in POST request : pos_x -> PosX ?
It is currently not possible to validate the fields of each object in an array of objects. We would like the ability to validate the following body:
{
"array": [
{
"field1": "string",
"field2": 2,
"field3": {"subfield": "string"},
"field4": [1,2,3],
"field5": [
{"subfield": "string"}
],
}
]
}
Slightly slower startup time.
Version: 3.9.1
Environment: Mac OS, go1.15.2 darwin/amd64
Reproduces: always
Unable to set DisableForeignKeyConstraintWhenMigrating in gorm.Config
panic: constraints not implemented on sqlite, consider using DisableForeignKeyConstraintWhenMigrating, more details https://github.com/go-gorm/gorm/wiki/GORM-V2-Release-Note-Draft#all-new-migrator
Relevant logs:
SELECT count(*) FROM sqlite_master WHERE type = "table" AND tbl_name = "replies" AND (sql LIKE "%CONSTRAINT \"fk_replies_user\" %" OR sql LIKE "%CONSTRAINT fk_replies_user %" OR sql LIKE "%CONSTRAINT `fk_replies_user`%")
panic: constraints not implemented on sqlite, consider using DisableForeignKeyConstraintWhenMigrating, more details https://github.com/go-gorm/gorm/wiki/GORM-V2-Release-Note-Draft#all-new-migrator
goroutine 1 [running]:
goyave.dev/goyave/v3/database.Migrate()
/Users/zaosoula/go/pkg/mod/goyave.dev/goyave/[email protected]/database/database.go:122 +0x11e
goyave.dev/goyave/v3.Start(0x46d3ae8, 0xc000143f68, 0x1)
/Users/zaosoula/go/pkg/mod/goyave.dev/goyave/[email protected]/goyave.go:154 +0x11f
main.main()
/Applications/MAMP/htdocs/projet-forum/api/main.go:24 +0x95
exit status 2
2021/06/22 09:29:47 exit status 1
Database models
type User struct {
ID int32 `gorm:"primary_key;AUTO_INCREMENT;column:id;type:integer;" json:"id" auth:"username"`
Email string `gorm:"column:email;type:varchar;" json:"email"`
DisplayName string `gorm:"column:displayName;type:varchar;" json:"displayName"`
UserName string `gorm:"column:userName;type:varchar;size:30;" json:"userName"`
Password string `gorm:"column:password;type:varchar;size:255;" json:"-"`
LastLoginAt int `gorm:"column:lastLoginAt;type:integer;" json:"lastLoginAt"`
RegisteredAt int `gorm:"column:registeredAt;type:integer;" json:"registeredAt"`
RefreshToken string `gorm:"column:refreshToken;type:varchar;size:1000;" json:"-"`
}
type Replies struct {
ID int32 `gorm:"primary_key;AUTO_INCREMENT;column:id;type:integer;" json:"id"`
PostID int `gorm:"column:postId;type:integer;" json:"postId"`
Body string `gorm:"column:body;type:varchar;" json:"body"`
UserID int `gorm:"column:userId;type:integer;" json:"userId"`
User User
CreatedAt int `gorm:"column:createdAt;type:integer;" json:"createdAt"`
}
Expected result:
Be able to add properties to gorm.Config before the connection occurs
The config is set in goyave/database/database.go, line 168
Current implementation automatically Unmarshal request data only in a situation when header Content-Type
equals to application/json
. RFC 7231 describing Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content
specifies that Content-Type
should contain media-type what is defined not only by data format (application/json
) but also by additional metadata about processing (charset
).
I'm not that experienced in Go, but I guess the problem is based on this check.
Some of the heavily used serialization libraries on Android β kotlinx.serialization, Moshi β put charset into Content-Type
by default and it might look similar to this one: Content-Type: application/json; charset=utf-8
To summarize, with this curl request, content of request.Data
is unmarshalled automatically:
curl -X "POST" "http://localhost:8080/v1/login" \
-H 'Content-Type: application/json' \
-d $'{
"email": "[email protected]",
"password": "12345678"
}'
Whereas with this request not:
curl -X "POST" "http://localhost:8080/v1/login" \
-H 'Content-Type: application/json; charset=utf-8' \
-d $'{
"email": "[email protected]",
"password": "12345678"
}'
I'm not sure if it's sufficient just change mentioned check from ==
(equals) into contains()
or it is necessary to take provided charset into account when data are unmarshalled.
With the current implementation of auth.Authenticator
and auth.Middleware
, it is not possible to add any custom behavior if the authentication failed. It is not possible to use status handler neither because the middleware is writing to the response.
Suggested solution: add an interface that authenticators can implement. For example:
type Foo interface{
OnUnauthorized(error)
}
If the authenticator used in auth.Middleware
implements this interface, then call OnUnauthorized()
if Authenticate()
doesn't return nil
.
None
.
Add a "required_if" validation rule that would take another field as first parameter and check if its value is exactly the value of the second parameter (converted to proper type). If that is true, then the field under validation is required.
"credit_card_number": {"required_if:payment_type,cc"}
None
.
Version: v3.10.0
Environment: Ubuntu 20.04, Go 1.16
Reproduces: always
goyave.NativeMiddleware
doesn't work properly with middleware replacing the http.Request
(via request.WithContext()
for example).
Suggested fix: Check if the pointer to the http.Request
is the same as the original one. If that is not the case, simply replace it.
In my case, I want to customize my Http request error handler, for example the default 404 response is 404 page not found
. I need to customize it to a JSON response like
{
"error": true,
"message": "Page not found",
"code": 404
}
Other than your input validator, consider the JSON Schema validator (jsonschema.org). Although similar, it has the advantage of write-once, run anywhere. The same validation schema could run on the browser before bothering the server. There would be no challenge keeping the two in synchronization: just use the same validator file.
Version: v2.7.0
Hello there! I didn't find any events/hooks which i could use for tracking time and other things of request. I know that i can create middleware to do this, but is there a way to track time of the request?
Version: v3.8.0
Environment: CI (Github Actions)
Reproduces: sometimes
"Timeout exceeded in server start/stop test" sometimes occurs in the CI runs, then test time out because it exceeds 10min. This suggests the chan mechanism used in that test is flawed.
See this run: https://github.com/go-goyave/goyave/runs/2466976233?check_suite_focus=true
Version: v2.7.0
Hello, is there a way override basic Gorm settings in the global database connection scope, for example auto_preload
feature?
Version: v2.7.0
Environment: Mac Os, 1.13
Reproduces: always
Hello,
There already was an issue called Failed to Dockerize
which has been solved, but I've run into a different problem with dockerizing the goyave-template. It's important to note that everything works if it's running without Docker.
When I start a server, running inside a container, and I call /hello endpoint I get curl: (52) Empty reply from server
response. When I start server just running by go run goyave-template
, and I call /hello endpoint I get Hi!
response.
I tried put logging inside Start
function and I can see that the server is running. What interesting is that if I put logging inside the SayHi
I got nothing in the terminal. So I suspect that the handler isn't even called. Also, I tried to use a closure. No success.
I haven't tried my Dockerize method with the prev version v2.2.0 in which the original issue was reported.
All files such as config.json, docker-compose and Dockerfile, are copy&paste in this description.
Ghosts-MacBook-Pro-2:goyave-docker ghost$ curl -I localhost:8080/hello
curl: (52) Empty reply from server
Expected result:
Based on the documentation, it should return Hi!
message.
This is my docker-compose.yml file:
version: '3.2'
services:
api:
container_name: goyave_docker_api
build: .
ports:
- 8080:8080
vgo:
container_name: goyave_docker_vgo
image: golang:1.13
volumes:
- .:/app
working_dir: /app
This is my Dockerfile:
FROM golang:1.13-alpine3.11 as builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -mod=vendor -o api
FROM alpine:3.11
WORKDIR /app
RUN apk add --no-cache tzdata
RUN apk add --no-cache ca-certificates
ENV TZ Europe/Prague
COPY --from=builder /app/api ./api
COPY resources /app/resources
COPY config.json ./config.json
EXPOSE 8080
ENTRYPOINT [ "./api" ]
This is my config.json file:
{
"appName": "goyave-docker",
"environment": "localhost",
"domain": "",
"maintenance": false,
"host": "localhost",
"port": 8080,
"httpsPort": 8081,
"protocol": "http",
"tlsCert": "",
"tlsKey": "",
"debug": false,
"timeout": 10,
"maxUploadSize": 10,
"defaultLanguage": "en-US",
"dbConnection": "none",
"dbHost": "127.0.0.1",
"dbPort": 3306,
"dbName": "goyave",
"dbUsername": "root",
"dbPassword": "root",
"dbOptions": "charset=utf8&parseTime=true&loc=Local",
"dbMaxOpenConnections": 20,
"dbMaxIdleConnections": 20,
"dbMaxLifetime": 300,
"dbAutoMigrate": false
}
In the config.json, I changed host
key from 127.0.0.1 to localhost.
Then I run:
docker-compose run --rm vgo go get && go mod vendor
to create the vendor folderdocker-compose up -d --build
to build an image a run a serverDevelop a module able to generate OpenAPI specification for Goyave applications by reading the main route registrer and validation rule sets.
This feature could be included in the CLI Utility ( #39 )
None
.
This issue is a feature proposal and is meant to be discussed.
It is also a good candidate if you want to contribute to the project.
This should probably be developed as a side-project.
Hi,
I am wondering if there is a method like response.JSON()
for template rendering from package text/template
for example like
response.Render(http.StatusOK, "template", &dataStructure)
Thank you.
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.