Reputation: 2041
After reading the official guide on how to structure projects and going through various (1, 2, 3 to name a few) examples and projects I can't help wondering whether my approach of structuring my REST-API server app is structured properly.
/auth/sign-in
Accepts a username
and password
and issues a JWT (JSON Web Token).
/auth/sign-out
Adds the JWT to a blacklist to invalidate the auth session.
/resources
Retrieves a list of all resources.
/resources
(requires valid JWT authentication)Accepts a JSON body, creates a new resource and sends out an email and notification to everyone about the new resource.
Currently I'm not creating any libraries. Everything is sitting in the main package, the overarching server setup with routes etc. all done in main.go
. I didn't go for the MVC pattern found à la Rails or Django to avoid overcomplicating things just for the sake of it. Also my impression was it doesn't really comply with the recommended structure for commands and libraries as described in the guide already mentioned above.
auth.go # generates, validates JWT, etc
auth-handler.go # Handles sign-in/out requests; includes middleware for required authentication
mailer.go # Provides methods to send out transactional email, loads correct template etc.
main.go # set up routes, runs server; inits mailer and notification instance for the request context
models.go # struct definition for User, Resource
notifications.go # Provides methods to publish push notifications
resource-handler.go # Handles request for resources, uses mailer and notifications instances for the POST request
Should routes be separated? What about middleware? And how do you deal with interfaces to 3rd party code – imagine mailer.go
in the outlined sample app talking to Mandrill and notifications.go
to Amazon AWS SNS?
Upvotes: 0
Views: 1109
Reputation: 49275
I can share a bit from my own experience.
In application code:
as opposed to library code, separating into packages and sub-packages is less important - as long as you don't have too much complexity in your code. I mostly design apps as integrating self contained libraries, so the app code itself is usually rather small. In general, try to avoid package separation if you don't really need it. But don't just slap tons of code in one package - that's also bad.
but don't have general packages like "util", they soon start to accumulate baggage and suck. I have a separate repo for generic utils reusable across projects, and under it each utility API is a sub package. e.g. github.com/me/myutils/countrycodes
, github.com/me/myutils/set
, github.com/me/myutils/whatevs
.
Regardless of the package structure, the most important thing is to separate internal APIs from handler code. The handlers code should be a very thin layer that handles input, and calls an internal, self contained API, that can be tested without handlers, or tied to other handlers. Looks like you're doing this. Then you can separate your internal API into another package or not, it doesn't really matter.
When you're deciding what parts of the code should be separated into libraries, think in terms of code reuse. If this code will be used only by your app, there's no point in that.
I like to wrap integration with third party APIs in an interface that is defined in a secondary package. For example if you have something like sending emails with AWS SES, I'd create a pakcage called github.com/my_org/mailer
, with an abstract interface, and under it an github.com/my_org/mailer/ses
package that implements the SES integration. The application code imports the mailer
package and its interface, and only in main
do I somehow inject the usage of SES and integrate things together.
re middleware - I usually keep it in the same package as the API itself.
Upvotes: 3