GithubHelp home page GithubHelp logo

go-goyave / goyave Goto Github PK

View Code? Open in Web Editor NEW
1.5K 1.5K 64.0 10.28 MB

🍐 The enterprise REST API framework

Home Page: https://goyave.dev

License: MIT License

JavaScript 0.01% Go 100.00% Shell 0.01%
api backend enterprise framework go golang hacktoberfest http rest web-framework

goyave's Issues

A real demo for benchmarks projects and to improve learning

Proposal

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!

Request extra-data or with context value

Proposal

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.

Implementation

The simplest solution would be to add a map[string]interface{} named Extra to the request structure. Initialize it empty to avoid memory usage.

Possible drawbacks

None.

Rate limiting

Proposal

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 ceiling
  • RateLimit-Remaining: the number of requests left
  • RateLimit-Reset: the number of seconds until the quota resets

Note: 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:

  • work with authenticated users and add variable limits depending on a user plan
  • be configured to count rates in relation to a route
  • use an external storage driver instead of the in-memory one explained earlier (support the database for example)
  • check the X-Forwarded-For and X-Real-IP headers if the application is running behind a reverse proxy
  • and more?

Either way, this middleware has to be compliant with previously mentioned IETF spec.

Possible drawbacks

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.

Additional information

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.

CLI Utility

Proposal

Create a CLI Utility called goyave-cli or gyv to make Goyave development easier. The utility would be an interactive, a bit like gh

  • Creation tools:
    • Create a project
      • The utility would ask a series of questions
      • Name of the project, name of the go module
      • Goyave version (latest by default)
      • Database used (changes the config options)
    • Create controllers
      • Resource controllers (full CRUD template, then fill the blanks)
      • Resource controller creation can take a model as reference to automatically create a request and the handlers
    • Create middleware
    • Create request (validation, may be created alongside resource controllers)
    • Create model (+ its resource controller)
  • Database commands:
    • Run seeders
    • Run migrations (may open to a more advanced migration system)
    • Clear / recreate database
  • Miscellaneous:
    • Detailed routes list
    • Run tests (maybe not needed, as it would duplicate go test)
    • Generate OpenAPI specification #42
    • Open documentation page (goyave.dev)

Possible drawbacks

None.

Additional information

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.

Authentication

Is there already an authentication system backed in? I couldn't find anything.

Embedded static resources

Proposal

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.

  • Create a new handler similar to router.Static(), but taking io/fs.FS as a parameter.
  • Add the ability to use an 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)
  • Provide an abstracted version of the helper/filesystem package so it works with io/fs too.
  • Allow Request to use generic file system.

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 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. With v4, I dropped go versions < 1.16.

Possible drawbacks

None.

Additional information

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.

README of generated project to include /echo

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:

  • a simple example:
    curl -G -w '\n' http://localhost:8080/echo -d text=abc123
    abc123
    $
  • an example when space encoding is needed:
    $ curl -G -w '\n' http://localhost:8080/echo --data-urlencode 'text=abc 123'
    abc 123
    $

Placeholders in language lines and pluralization

Proposal

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.

Possible drawbacks

Depending on the implementation, using localization may have a little bit bigger impact on performances.

Additional information

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.

Validation error message for type-dependent rules when field is not in body

Bug report

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.

How to reproduce

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"
        ]
    }
}

Validation rules composition

Proposal

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!

Possible drawbacks

None.

Permission system (guards)

Proposal

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:

  • As function calls, so they can be used anywhere such as in the middle of a controller handler
  • In middleware to protect routes directly without cluttering controller handlers.

This system could support OAuth in some way too.

The implementation is not defined yet, so feel free to discuss and suggest one.

Possible drawbacks

None.

Additional information

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.

Documentation on Gorm migrations incorrect

Description

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.

Inconsistent validation results

Bug report

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

Route parameter converter

Proposal

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.

Possible drawbacks

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.

Additional information

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.

Social Media and Outreach Activities

Description

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.

Possible drawbacks

Reach more Gophers and more contributors

Additional information

I am a beginner in Golang and would love to contribute to this framework by promoting it to gophers.

Websocket

Proposal

Add support for websockets by building an adapter for gorilla's websocket library.

Possible drawbacks

None.

Additional information

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.

Asymmetric JWT signatures support

Proposal

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.

Possible drawbacks

None.

Add request context to validation

Hello, firstly thank you for this project.

Proposal

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.

Possible drawbacks

A changes in the organization of structures to avoid cyclical imports.

Failed to Handle CORS

Description

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!

Can't read json raw request

Description

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!! πŸŽ‰πŸŽ‰πŸŽ‰

Mispelled "Learning" in README.

Information

On the Table of Contents, the first link says Leaning, instead of Learning. It is missing the letter 'r' after the letter 'a'.

Laravel

Is this loosly based on PHP Laravel framework?

v3 Discussion

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:

  • Revamped configuration.
    • Maybe using another configuration format such as toml instead of json
    • Improving the way configuration is organized, by letting the possibility of grouping items together (for example grouping all database config into a single category) instead of accumulating a lot of entries at the root-level.
    • Ease plugin development by adding a possibility to add entries to the default config in an init() function
    • Make configuration checked at compile-time by using structures instead of maps.
  • Validation
    • Improve performance by parsing rule sets at startup time instead of during each request.
    • Add the ability to define validation in a more complex way, which will be more verbose, but more flexible and checked at compile-time. This would solve the comma escaping problem in rules parameters.
  • Route parameter converters ( #93 ) may require a breaking change.
  • Remove native handlers. I understand that it would make it harder to plug well known go http modules to Goyave and isolate it a bit from the rest of the environment, but this change would be beneficial in many ways:
    • Performance improvements: no need to duplicate the request body
    • Consistency: plugged modules may not work well with Goyave and there is no way to guarantee it. They probably don't follow the same design choices and principles, which can make programs inconsistent and sometimes unreliable.
  • Convention changes
    • Remove the request 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.
  • More flexibility for databases. For example, the ability to add another dialect will be added.

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.

"exists" validation rule

Proposal

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.

Possible drawbacks

None.

Error "pq: SSL is not enabled on the server" when using Postgres

Description

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

How it occurred

Every querying data

How to reproduce

Every querying data

Failed to Dockerize

Description

Version: v2.2.0
Commit: bc72e19

Description

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! 😁

Logging not working when no route matched

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.

How it occurred

  1. Register the logging middleware
  2. Request a non-existing URL or an existing one with the wrong HTTP method
  3. Notice nothing is logged

Expected result:
Logging should probably log all requests, including 404 and 405.

How to reproduce

router.Middleware(log.CombinedLogMiddleware())

response.Render status code

Bug report

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.

Root route ("/") always return 404

Bug report

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

How it occurred

Setting a route in route.go:

router.Get("/", page.Index)

Expected result:
Describe the expected result and how it differs from the actual result.

How to reproduce

Point any route to "/" and start the server, then open browser and point to http://127.0.0.1:8080/

Logging

Proposal

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:

  • logging of incoming requests
  • logging of responses
  • logging of debug, info, errors on-demand in handlers and middleware
  • custom logging behavior in case of unexpected error
  • set output (stdout, stderr, files, other)

The implementation is not defined yet, so feel free to discuss and suggest one.

Possible drawbacks

None.

Additional information

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.

JSON body request example

Support

Version: v2.10.0

Can you please provide an example of a JSON body request controller with validation?

CORS options not working on subrouters

Bug report

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.

Support JWT custom claims

Proposal

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).

Possible drawbacks

By default - none, if someone uses too many fields then the token will be heavy, but that's up to user of the framework.

Additional information

I think I can handle this contribution if you agree.

Value null after ToStruct and validation ruleset

Bug report

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
}

How it occurred

  1. Validation
"pos_x":     {"required", "numeric"},
"pos_y":     {"required", "numeric"},
"pos_z":     {"required", "numeric"},
  1. On a POST request
pos_x: -970.4351,
pos_y: -664.2330,
pos_z: 44.2087,
  1. ToStruct
random := model.MyStruct{}
if err := request.ToStruct(&random); err != nil {
        panic(err)
}
  1. Values
fmt.Print(random.PosX)
// 0.000000

Expected result:

fmt.Print(random.PosX)
// -970.4351

Additional information

Problem from ToStruct() ?
Naming convention in POST request : pos_x -> PosX ?

Validating arrays of objects

Proposal

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"}
            ],
        }
    ]
}

Possible drawbacks

Slightly slower startup time.

Unable to set DisableForeignKeyConstraintWhenMigrating

Bug report

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"`
}

How it occurred

  1. Create an association (in this case a User in a Replies)
  2. Gorm throw an error asking to set DisableForeignKeyConstraintWhenMigrating to true (which seems not possible with Goyave

Expected result:
Be able to add properties to gorm.Config before the connection occurs

Additional information

The config is set in goyave/database/database.go, line 168

Content-Type with charset

Proposal

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"
}'

Possible drawbacks

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.

Authenticator: Ability to define a function executed if auth failed

Proposal

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.

Possible drawbacks

None.

Validation "Required if"

Proposal

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"}

Possible drawbacks

None.

Native middleware don't use replaced http.Request

Bug report

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.

Custom HTTP request error handler such as 404 handler etc

Description

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
}

JSON Schema Validator

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.

Request time tracking

Support

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?

Gorm settings

Support

Version: v2.7.0

Hello, is there a way override basic Gorm settings in the global database connection scope, for example auto_preload feature?

Failed to Dockerize

Description

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.

How it occurred

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.

How to reproduce

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:

  1. docker-compose run --rm vgo go get && go mod vendor to create the vendor folder
  2. docker-compose up -d --build to build an image a run a server

OpenAPI generator

Proposal

Develop 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 )

Possible drawbacks

None.

Additional information

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.

Template rendering

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.