Skip to content

Instantly share code, notes, and snippets.

@dewey4iv
Created March 23, 2017 18:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dewey4iv/ce080e02b505b297bc788dbc21136129 to your computer and use it in GitHub Desktop.
Save dewey4iv/ce080e02b505b297bc788dbc21136129 to your computer and use it in GitHub Desktop.
package articles
// New retunrs a new instance of the Article Service
func New() (*Service, error) {
var s Service
return &s, nil
}
// Service defines the articles service
type Service struct {
store Store
}
// All fetches all articles
func (s *Service) All() ([]*Article, error) {
return s.All()
}
// Search takes a term and list of tags and returns matching articles
func (s *Service) Search(term string, tags ...string) ([]*Article, error) {
return nil, nil
}
// ByID returns the article by the ID
func (s *Service) ByID(articleID string) (*Article, error) {
return s.ByID(articleID)
}
// BySlug returns the article by the slug
func (s *Service) BySlug(articleID string) (*Article, error) {
return s.BySlug(articleID)
}
// Create takes an article and returns the saved article
func (s *Service) Create(article *Article) (*Article, error) {
return s.Create(article)
}
// Update takes the article and returns the result of the update
func (s *Service) Update(article *Article) (*Article, error) {
return s.Update(article)
}
// Delete removes the article with the same id
func (s *Service) Delete(articleID string) error {
return s.Delete(articleID)
}
// Store defines a set of stores
type Store interface {
Articles() ArticleStore
}
// ArticleStore returns methods for interacting with Articles
type ArticleStore interface {
All() ([]*Article, error)
ByTags(tags ...string) ([]*Article, error)
ByID(articleID string) (*Article, error)
BySlug(slug string) (*Article, error)
Create(article *Article) (*Article, error)
Update(article *Article) (*Article, error)
Delete(articleID string) error
}
package http
import (
"fmt"
"net/http"
pkg "git.dewey4.com/d4apps/gazette/articles"
"git.dewey4.com/dewey4com/gop/router"
)
// ArticleService defines the service used by the http server
type ArticleService interface {
All() ([]*pkg.Article, error)
Search(term string, tags ...string) ([]*pkg.Article, error)
ByID(articleID string) (*pkg.Article, error)
Create(articles *pkg.Article) (*pkg.Article, error)
Update(articles *pkg.Article) (*pkg.Article, error)
Delete(articleID string) error
}
func listArticles(m Methods, service ArticleService) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
articles, err := service.All()
if err != nil {
m.HandleErr(w, err)
return
}
if articles == nil {
articles = make([]*pkg.Article, 0)
}
m.MarshalBody(w, articles)
}
}
func showArticle(m Methods, service ArticleService) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
articleID := router.ParamFromCtx(r, "articleID")
if articleID == "" {
m.HandleErr(w, fmt.Errorf("no article id provided"))
return
}
article, err := service.ByID(articleID)
if err != nil {
m.HandleErr(w, err)
return
}
m.MarshalBody(w, article)
}
}
func searchArticles(m Methods, service ArticleService) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
tags := router.ParamFromCtx(r, "tags")
term := router.ParamFromCtx(r, "q")
articles, err := service.Search(term, tags)
if err != nil {
m.HandleErr(w, err)
return
}
if articles == nil {
articles = make([]*pkg.Article, 0)
}
m.MarshalBody(w, articles)
}
}
func createArticle(m Methods, service ArticleService) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var req pkg.Article
if err := m.UnmarshalBody(r, &req); err != nil {
m.HandleErr(w, err)
return
}
article, err := service.Create(&req)
if err != nil {
m.HandleErr(w, err)
return
}
m.MarshalBody(w, article)
}
}
func updateArticle(m Methods, service ArticleService) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
var req pkg.Article
if err := m.UnmarshalBody(r, &req); err != nil {
m.HandleErr(w, err)
return
}
article, err := service.Update(&req)
if err != nil {
m.HandleErr(w, err)
return
}
m.MarshalBody(w, article)
}
}
func deleteArticle(m Methods, service ArticleService) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
articleID := router.ParamFromCtx(r, "articleID")
if articleID == "" {
m.HandleErr(w, fmt.Errorf("no article id provided"))
return
}
if err := service.Delete(articleID); err != nil {
m.HandleErr(w, err)
return
}
}
}
package http
import (
"net/http"
"git.dewey4.com/dewey4com/gop/middleware"
"git.dewey4.com/dewey4com/gop/router"
)
// New returns a new server
func New(opts ...Option) (*Server, error) {
var s Server
for _, opt := range opts {
if err := opt.Apply(&s); err != nil {
return nil, err
}
}
return &s, nil
}
// Server is a basic HTTP Server
type Server struct {
service ArticleService
handler http.Handler
methods Methods
}
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.handler.ServeHTTP(w, r)
}
func (s *Server) setup() error {
middl := []router.Middleware{
middleware.AccessOriginAll,
middleware.AccessControlHeaders("X-API-Key", "X-Session-ID", "Content-Type"),
middleware.AccessMethods,
}
var routes = []router.Route{
// Articles
{
Method: "GET",
Path: "/articles",
Handler: listArticles(s.methods, s.service),
Middlewares: middl,
},
{
Method: "GET",
Path: "/articles/:articleID",
Handler: showArticle(s.methods, s.service),
Middlewares: middl,
},
{
Method: "POST",
Path: "/articles_search",
Handler: searchArticles(s.methods, s.service),
Middlewares: middl,
},
{
Method: "POST",
Path: "/articles",
Handler: createArticle(s.methods, s.service),
Middlewares: middl,
},
{
Method: "PUT",
Path: "/articles",
Handler: updateArticle(s.methods, s.service),
Middlewares: middl,
},
{
Method: "DELETE",
Path: "/articles/:articleID",
Handler: deleteArticle(s.methods, s.service),
Middlewares: middl,
},
}
s.handler = router.NewWithRoutes(routes)
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment