Skip to content

Commit

Permalink
create example usage for http
Browse files Browse the repository at this point in the history
  • Loading branch information
ssengalanto committed Jan 11, 2023
1 parent 6ffdc1b commit e15b783
Show file tree
Hide file tree
Showing 16 changed files with 571 additions and 0 deletions.
29 changes: 29 additions & 0 deletions _examples/http/behaviour/logger_behaviour.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package behaviour

import (
"context"
"log"

"github.com/ssengalanto/midt"
)

type LoggerBehaviour struct{}

func NewLoggerBehaviour() *LoggerBehaviour {
return &LoggerBehaviour{}
}

func (l *LoggerBehaviour) Handle(
ctx context.Context,
request any,
next midt.RequestHandlerFunc,
) (any, error) {
log.Printf("executing %T", request)

res, err := next()
if err != nil {
return nil, err
}

return res, nil
}
15 changes: 15 additions & 0 deletions _examples/http/command/create_person.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package command

type CreatePersonCommand struct {
Email string
FirstName string
LastName string
}

func NewCreatePersonCommand(email, fn, ln string) *CreatePersonCommand {
return &CreatePersonCommand{
Email: email,
FirstName: fn,
LastName: ln,
}
}
42 changes: 42 additions & 0 deletions _examples/http/command/create_person_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package command

import (
"context"
"errors"
"fmt"

"github.com/ssengalanto/midt/_examples/http/dto"
"github.com/ssengalanto/midt/_examples/http/memory"
)

type CreatePersonCommandHandler struct {
personRepository memory.Repository
}

func NewCreatePersonCommandHandler(personRepository memory.Repository) *CreatePersonCommandHandler {
return &CreatePersonCommandHandler{
personRepository: personRepository,
}
}

func (c *CreatePersonCommandHandler) Name() string {
return fmt.Sprintf("%T", &CreatePersonCommand{})
}

func (c *CreatePersonCommandHandler) Handle(ctx context.Context, request any) (any, error) {
cmd, ok := request.(*CreatePersonCommand)
if !ok {
return nil, errors.New("invalid command")
}

id, err := c.personRepository.Save(memory.CreatePersonRequest{
Email: cmd.Email,
FirstName: cmd.FirstName,
LastName: cmd.LastName,
})
if err != nil {
return nil, errors.New("person creation failed")
}

return dto.CreatePersonResponse{ID: id}, nil
}
11 changes: 11 additions & 0 deletions _examples/http/constants/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package constants

import "time"

const (
Port = 8080
IdleTimeout = time.Minute
RequestTimeout = time.Second * 3
ReadTimeout = 10 * time.Second
WriteTimeout = 30 * time.Second
)
11 changes: 11 additions & 0 deletions _examples/http/dto/create_person.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package dto

type CreatePersonRequest struct {
Email string `json:"email"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}

type CreatePersonResponse struct {
ID string `json:"id"`
}
12 changes: 12 additions & 0 deletions _examples/http/dto/get_person.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package dto

type GetPersonRequest struct {
ID string `json:"id"`
}

type GetPersonResponse struct {
ID string `json:"id"`
Email string `json:"email"`
FirstName string `json:"firstName"`
LastName string `json:"lastName"`
}
17 changes: 17 additions & 0 deletions _examples/http/event/person_created.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package event

type PersonCreatedEvent struct {
ID string
Email string
FirstName string
LastName string
}

func NewPersonCreatedEvent(id, email, fn, ln string) *PersonCreatedEvent {
return &PersonCreatedEvent{
ID: id,
Email: email,
FirstName: fn,
LastName: ln,
}
}
25 changes: 25 additions & 0 deletions _examples/http/event/person_created_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package event

import (
"context"
"fmt"
"log"
)

type PersonCreatedEventHandler struct{}

func NewPersonCreatedEventHandler() *PersonCreatedEventHandler {
return &PersonCreatedEventHandler{}
}

func (p *PersonCreatedEventHandler) Name() string {
return fmt.Sprintf("%T", &PersonCreatedEvent{})
}

func (p *PersonCreatedEventHandler) Handle(ctx context.Context, notification any) error {
evt := notification.(*PersonCreatedEvent)

log.Printf("person created %+v", evt)

return nil
}
73 changes: 73 additions & 0 deletions _examples/http/http/handlers/create_person_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package handlers

import (
"context"
"encoding/json"
"log"
"net/http"

"github.com/ssengalanto/midt"
"github.com/ssengalanto/midt/_examples/http/command"
"github.com/ssengalanto/midt/_examples/http/constants"
"github.com/ssengalanto/midt/_examples/http/dto"
"github.com/ssengalanto/midt/_examples/http/event"
"github.com/ssengalanto/midt/_examples/http/http/response"
"github.com/ssengalanto/midt/_examples/http/query"
)

type CreatePersonHandler struct {
m *midt.Midt
}

func NewCreatePersonHandler(m *midt.Midt) *CreatePersonHandler {
return &CreatePersonHandler{m: m}
}

func (c *CreatePersonHandler) Handle(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(context.Background(), constants.RequestTimeout)
defer cancel()

if r.Method != http.MethodPost {
log.Println("invalid http method")
response.Error(w, http.StatusMethodNotAllowed)
return
}

var req dto.CreatePersonRequest

err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
log.Println("invalid request body")
response.Error(w, http.StatusBadRequest)
return
}

// Executing CreatePersonCommand
cmd := command.NewCreatePersonCommand(req.Email, req.FirstName, req.LastName)
cmdres, err := c.m.Send(ctx, cmd)
if err != nil {
log.Printf("%T execution failed: %+v\n", cmd, err)
response.Error(w, http.StatusInternalServerError)
return
}

// Executing GetPersonQuery
id := cmdres.(dto.CreatePersonResponse).ID
q := query.NewGetPersonQuery(id)
qres, err := c.m.Send(ctx, q)
if err != nil {
log.Printf("%T execution failed: %+v\n", q, err)
response.Error(w, http.StatusInternalServerError)
return
}

// Executing PersonCreatedEvent
pers := qres.(dto.GetPersonResponse)
evt := event.NewPersonCreatedEvent(pers.ID, pers.Email, pers.FirstName, pers.LastName)
err = c.m.Publish(ctx, evt)
if err != nil {
log.Printf("%T execution failed: %+v\n", evt, err)
}

response.Success(w, http.StatusCreated, pers)
}
46 changes: 46 additions & 0 deletions _examples/http/http/handlers/get_person_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package handlers

import (
"context"
"log"
"net/http"
"strings"

"github.com/ssengalanto/midt"
"github.com/ssengalanto/midt/_examples/http/constants"
"github.com/ssengalanto/midt/_examples/http/dto"
"github.com/ssengalanto/midt/_examples/http/http/response"
"github.com/ssengalanto/midt/_examples/http/query"
)

type GetPersonHandler struct {
m *midt.Midt
}

func NewGetPersonHandler(m *midt.Midt) *GetPersonHandler {
return &GetPersonHandler{m: m}
}

func (g *GetPersonHandler) Handle(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(context.Background(), constants.RequestTimeout)
defer cancel()

if r.Method != http.MethodGet {
log.Println("invalid http method")
response.Error(w, http.StatusMethodNotAllowed)
return
}

id := strings.TrimPrefix(r.URL.Path, "/person/")

req := dto.GetPersonRequest{ID: id}

q := query.NewGetPersonQuery(req.ID)
res, err := g.m.Send(ctx, q)
if err != nil {
response.Error(w, http.StatusInternalServerError)
return
}

response.Success(w, http.StatusCreated, res)
}
51 changes: 51 additions & 0 deletions _examples/http/http/response/response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package response

import (
"encoding/json"
"net/http"
)

type HTTPError struct {
Error Err `json:"error"`
}

type Err struct {
Code int `json:"code"`
Message string `json:"message"`
}

func Success(w http.ResponseWriter, statusCode int, payload any) error {
res, err := json.Marshal(payload)
if err != nil {
return err
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(statusCode)
w.Write(res)

return nil
}

func Error(w http.ResponseWriter, statusCode int) error {
statusText := http.StatusText(statusCode)
if statusText == "" {
panic("invalid status code")
}

httpError := HTTPError{Error: Err{
Code: statusCode,
Message: statusText,
}}

res, err := json.Marshal(httpError)
if err != nil {
return err
}

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(statusCode)
w.Write(res)

return nil
}
Loading

0 comments on commit e15b783

Please sign in to comment.