Skip to content

Commit

Permalink
general maintenance
Browse files Browse the repository at this point in the history
  • Loading branch information
steviebps committed Dec 22, 2023
1 parent 326b6df commit bd45e20
Show file tree
Hide file tree
Showing 13 changed files with 400 additions and 159 deletions.
2 changes: 1 addition & 1 deletion api/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type HTTPResponse struct {
Data json.RawMessage `json:"data"`
}

type HTTPErrorAndDataRespone struct {
type HTTPErrorAndDataResponse struct {
Data json.RawMessage `json:"data,omitempty"`
Errors []string `json:"errors,omitempty"`
}
18 changes: 11 additions & 7 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,24 @@ import (
"net/http"
"net/url"
"strings"
"time"

"github.com/hashicorp/go-hclog"
"github.com/steviebps/realm/utils"
)

const DefaultClientTimeout = 15 * time.Second

type ClientConfig struct {
Logger hclog.Logger
Address string
Timeout time.Duration
}

type Client struct {
underlying *http.Client
logger hclog.Logger
address *url.URL
config *ClientConfig
underlying *http.Client
}

func NewClient(c *ClientConfig) (*Client, error) {
Expand All @@ -37,13 +40,14 @@ func NewClient(c *ClientConfig) (*Client, error) {
if logger == nil {
logger = hclog.Default().Named("client")
}
if c.Timeout == 0 {
c.Timeout = DefaultClientTimeout
}

return &Client{
address: u,
config: c,
logger: logger,
// TODO: add internal client options
underlying: &http.Client{},
underlying: &http.Client{Timeout: c.Timeout},
address: u,
logger: logger,
}, nil
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/client_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ var clientDelete = &cobra.Command{
}
defer res.Body.Close()

var httpRes api.HTTPErrorAndDataRespone
var httpRes api.HTTPErrorAndDataResponse
if err := utils.ReadInterfaceWith(res.Body, &httpRes); err != nil {
logger.Error(fmt.Sprintf("could not read response for deleting: %q", args[0]), "error", err.Error())
os.Exit(1)
Expand Down
2 changes: 1 addition & 1 deletion cmd/client_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ var clientGet = &cobra.Command{
}
defer res.Body.Close()

var httpRes api.HTTPErrorAndDataRespone
var httpRes api.HTTPErrorAndDataResponse
if err := utils.ReadInterfaceWith(res.Body, &httpRes); err != nil {
logger.Error(fmt.Sprintf("could not read response for getting: %q", args[0]), "error", err.Error())
os.Exit(1)
Expand Down
2 changes: 1 addition & 1 deletion cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ var serverCmd = &cobra.Command{
}
}

handler, err := realmhttp.NewHandler(realmhttp.HandlerConfig{Storage: stg, Logger: logger, RequestTimeout: 5 * time.Second})
handler, err := realmhttp.NewHandler(realmhttp.HandlerConfig{Storage: stg, Logger: logger})
if err != nil {
logger.Error(err.Error())
os.Exit(1)
Expand Down
14 changes: 9 additions & 5 deletions examples/go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import (
"fmt"
"log"
"net/http"
"time"

"github.com/steviebps/realm/client"
realmhttp "github.com/steviebps/realm/http"
realm "github.com/steviebps/realm/pkg"
)

Expand All @@ -18,11 +20,11 @@ type CustomStruct struct {
func main() {
var err error

client, err := client.NewClient(&client.ClientConfig{Address: "http://localhost"})
client, err := client.NewClient(&client.ClientConfig{Address: "http://localhost:8080"})
if err != nil {
log.Fatal(err)
}
rlm, err := realm.NewRealm(realm.RealmOptions{Client: client, ApplicationVersion: "v1.0.0", Path: "root"})
rlm, err := realm.NewRealm(realm.RealmOptions{Client: client, ApplicationVersion: "v1.0.0", Path: "root", RefreshInterval: 1 * time.Minute})
if err != nil {
log.Fatal(err)
}
Expand All @@ -36,13 +38,13 @@ func main() {

mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
message, _ := rlm.String(rlm.NewContext(r.Context()), "message", "DEFAULT")
message, _ := rlm.String(r.Context(), "message", "DEFAULT")
w.Write([]byte(message))
})

mux.HandleFunc("/custom", func(w http.ResponseWriter, r *http.Request) {
var custom *CustomStruct
if err := rlm.CustomValue(rlm.NewContext(r.Context()), "custom", &custom); err != nil {
if err := rlm.CustomValue(r.Context(), "custom", &custom); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
Expand All @@ -51,8 +53,10 @@ func main() {
json.NewEncoder(w).Encode(custom)
})

rlmHandler := realmhttp.RealmHandler(rlm, mux)

log.Println("Listening on :", port)
err = http.ListenAndServe(fmt.Sprintf(":%d", int(port)), mux)
err = http.ListenAndServe(fmt.Sprintf(":%d", int(port)), rlmHandler)
if err != nil {
log.Fatal(err)
}
Expand Down
57 changes: 36 additions & 21 deletions http/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,31 @@ import (
"github.com/steviebps/realm/utils"
)

const DefaultHandlerTimeout = 10 * time.Second

type HandlerConfig struct {
Logger hclog.Logger
Storage storage.Storage
RequestTimeout time.Duration
}

func RealmHandler(rlm *realm.Realm, h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
req := r.WithContext(rlm.NewContext(r.Context()))
h.ServeHTTP(w, req)
})
}

func NewHandler(config HandlerConfig) (http.Handler, error) {
if config.Storage == nil {
return nil, fmt.Errorf("storage cannot be nil")
}
if config.Logger == nil {
config.Logger = hclog.Default().Named("realm")
}
if config.RequestTimeout == 0 {
config.RequestTimeout = DefaultHandlerTimeout
}
return handle(config), nil
}

Expand All @@ -48,6 +60,7 @@ func handle(hc HandlerConfig) http.Handler {

func wrapWithTimeout(h http.Handler, t time.Duration) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("timeout")
ctx := r.Context()
var cancelFunc context.CancelFunc
ctx, cancelFunc = context.WithTimeout(ctx, t)
Expand All @@ -59,6 +72,7 @@ func wrapWithTimeout(h http.Handler, t time.Duration) http.Handler {
func wrapCommonHandler(h http.Handler) http.Handler {
hostname, _ := os.Hostname()
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Println("common")
w.Header().Set("Cache-Control", "no-store")

if hostname != "" {
Expand All @@ -67,11 +81,15 @@ func wrapCommonHandler(h http.Handler) http.Handler {
h.ServeHTTP(w, r)
})
}
func createResponse(data json.RawMessage) *api.HTTPResponse {
response := &api.HTTPResponse{}

func createResponseWithErrors(data json.RawMessage, errors []string) api.HTTPErrorAndDataResponse {
response := api.HTTPErrorAndDataResponse{}
if data != nil {
response.Data = data
}
if len(errors) > 0 {
response.Errors = errors
}

return response
}
Expand All @@ -86,18 +104,14 @@ func handleOk(w http.ResponseWriter, body interface{}) {
}
}

func handleOkWithStatus(w http.ResponseWriter, status int, body interface{}) {
func handleWithStatus(w http.ResponseWriter, status int, body interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
utils.WriteInterfaceWith(w, body, true)
}

func handleError(w http.ResponseWriter, status int, err error) {
func handleError(w http.ResponseWriter, status int, resp api.HTTPErrorAndDataResponse) {
w.Header().Set("Content-Type", "application/json")
resp := &api.HTTPErrorResponse{Errors: make([]string, 0, 1)}
if err != nil {
resp.Errors = append(resp.Errors, err.Error())
}
w.WriteHeader(status)
utils.WriteInterfaceWith(w, resp, true)
}
Expand All @@ -121,11 +135,11 @@ func handleChambers(strg storage.Storage, logger hclog.Logger) http.Handler {
err = nfError
}

handleError(w, http.StatusNotFound, err)
handleError(w, http.StatusNotFound, createResponseWithErrors(nil, []string{err.Error()}))
return
}

handleOk(w, createResponse(entry.Value))
handleOk(w, createResponseWithErrors(entry.Value, nil))
return

case PutOperation:
Expand All @@ -139,26 +153,27 @@ func handleChambers(strg storage.Storage, logger hclog.Logger) http.Handler {
} else {
err = errors.New(http.StatusText(http.StatusBadRequest))
}
handleError(w, http.StatusBadRequest, err)
handleError(w, http.StatusBadRequest, createResponseWithErrors(nil, []string{err.Error()}))
return
}

b, err := json.Marshal(&c)
if err != nil {
requestLogger.Error(err.Error())
err = errors.New(http.StatusText(http.StatusInternalServerError))
handleError(w, http.StatusInternalServerError, err)
handleError(w, http.StatusInternalServerError, createResponseWithErrors(nil, []string{err.Error()}))
return
}

// store the entry if the format is correct
entry := storage.StorageEntry{Key: req.Path, Value: b}
if err := strg.Put(loggerCtx, entry); err != nil {
requestLogger.Error(err.Error())
handleError(w, http.StatusInternalServerError, err)
handleError(w, http.StatusInternalServerError, createResponseWithErrors(nil, []string{err.Error()}))
return
}

handleOkWithStatus(w, http.StatusCreated, nil)
handleWithStatus(w, http.StatusCreated, nil)
return

case DeleteOperation:
Expand All @@ -167,11 +182,11 @@ func handleChambers(strg storage.Storage, logger hclog.Logger) http.Handler {

var nfError *storage.NotFoundError
if errors.As(err, &nfError) {
handleError(w, http.StatusNotFound, nfError)
handleError(w, http.StatusNotFound, createResponseWithErrors(nil, []string{nfError.Error()}))
return
}

handleError(w, http.StatusInternalServerError, err)
handleError(w, http.StatusInternalServerError, createResponseWithErrors(nil, []string{err.Error()}))
return
}
handleOk(w, nil)
Expand All @@ -182,23 +197,23 @@ func handleChambers(strg storage.Storage, logger hclog.Logger) http.Handler {
if err != nil {
requestLogger.Error(err.Error())
if errors.Is(err, os.ErrNotExist) {
handleError(w, http.StatusNotFound, errors.New(http.StatusText(http.StatusNotFound)))
handleError(w, http.StatusNotFound, createResponseWithErrors(nil, []string{http.StatusText(http.StatusNotFound)}))
return
}
handleError(w, http.StatusInternalServerError, err)
handleError(w, http.StatusInternalServerError, createResponseWithErrors(nil, []string{err.Error()}))
return
}
raw, err := json.Marshal(names)
if err != nil {
handleError(w, http.StatusInternalServerError, err)
handleError(w, http.StatusInternalServerError, createResponseWithErrors(nil, []string{err.Error()}))
return
}

handleOk(w, createResponse(raw))
handleOk(w, createResponseWithErrors(raw, nil))
return

default:
handleError(w, http.StatusMethodNotAllowed, errors.New(http.StatusText(http.StatusMethodNotAllowed)))
handleError(w, http.StatusMethodNotAllowed, createResponseWithErrors(nil, []string{http.StatusText(http.StatusMethodNotAllowed)}))
}
})

Expand Down
Loading

0 comments on commit bd45e20

Please sign in to comment.