Skip to content

Commit

Permalink
Merge pull request #12 from subomi/subomi/feat/improve-migration-inte…
Browse files Browse the repository at this point in the history
…rface

feat: improved core api
  • Loading branch information
subomi authored Oct 10, 2023
2 parents 8e5c299 + 104f9cd commit 8212aad
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 100 deletions.
2 changes: 1 addition & 1 deletion example/basic/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.18

require (
github.com/gorilla/mux v1.8.0
github.com/prometheus/client_golang v1.16.0
github.com/subomi/requestmigrations v0.1.0
)

Expand All @@ -13,7 +14,6 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
Expand Down
4 changes: 4 additions & 0 deletions example/basic/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
Expand All @@ -15,6 +16,7 @@ github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
Expand All @@ -23,6 +25,7 @@ github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI
github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc=
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand All @@ -31,3 +34,4 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
2 changes: 1 addition & 1 deletion example/basic/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ type API struct {

func (a *API) ListUser(w http.ResponseWriter, r *http.Request) {
// Generate a random Int type number between 1 and 10
randNum := rand.Intn(3-1+1) + 1
randNum := rand.Intn(2-1+1) + 1
time.Sleep(time.Duration(randNum) * time.Second)

users, err := a.store.GetAll()
Expand Down
92 changes: 35 additions & 57 deletions example/basic/requestmigrations.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,32 @@
package main

import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
)

// Migrations
type combineNamesForUserMigration struct{}

func (c *combineNamesForUserMigration) ShouldMigrateRequest(r *http.Request) bool {
return false
}

func (c *combineNamesForUserMigration) MigrateRequest(r *http.Request) error {
fmt.Println("migrating request...")

return nil
}
func (c *combineNamesForUserMigration) ShouldMigrateConstraint(
url *url.URL,
method string,
data []byte,
isReq bool) bool {

func (c *combineNamesForUserMigration) ShouldMigrateResponse(
req *http.Request,
res *http.Response) bool {
isUserPath := url.Path == "/users"
isGetMethod := method == http.MethodGet
isValidType := isReq == false

isUserPath := req.URL.Path == "/users"
isGetMethod := req.Method == http.MethodGet

return isUserPath && isGetMethod
return isUserPath && isGetMethod && isValidType
}

func (c *combineNamesForUserMigration) MigrateResponse(r *http.Response) error {
func (c *combineNamesForUserMigration) Migrate(
body []byte,
h http.Header) ([]byte, http.Header, error) {
type oldUser struct {
UID string `json:"uid"`
Email string `json:"email"`
Expand All @@ -43,21 +36,16 @@ func (c *combineNamesForUserMigration) MigrateResponse(r *http.Response) error {
UpdatedAt time.Time `json:"updated_at"`
}

body, err := io.ReadAll(r.Body)
if err != nil {
return err
}

var res ServerResponse
err = json.Unmarshal(body, &res)
err := json.Unmarshal(body, &res)
if err != nil {
return err
return nil, nil, err
}

var users []*oldUser20230501
err = json.Unmarshal(res.Data, &users)
if err != nil {
return err
return nil, nil, err
}

var newUsers []*oldUser
Expand All @@ -74,11 +62,10 @@ func (c *combineNamesForUserMigration) MigrateResponse(r *http.Response) error {

body, err = generateSuccessResponse(&newUsers, "users retrieved successfully")
if err != nil {
return err
return nil, nil, err
}

r.Body = io.NopCloser(bytes.NewReader(body))
return nil
return body, h, nil
}

type oldUser20230501 struct {
Expand All @@ -93,40 +80,32 @@ type oldUser20230501 struct {

type expandProfileForUserMigration struct{}

func (e *expandProfileForUserMigration) ShouldMigrateRequest(r *http.Request) bool {
return false
}

func (e *expandProfileForUserMigration) MigrateRequest(r *http.Request) error {
return nil
}

func (e *expandProfileForUserMigration) ShouldMigrateResponse(
req *http.Request,
res *http.Response) bool {
func (e *expandProfileForUserMigration) ShouldMigrateConstraint(
url *url.URL,
method string,
body []byte,
isReq bool) bool {

isUserPath := req.URL.Path == "/users"
isGetMethod := req.Method == http.MethodGet
isUserPath := url.Path == "/users"
isGetMethod := method == http.MethodGet
isValidType := isReq == false

return isUserPath && isGetMethod
return isUserPath && isGetMethod && isValidType
}

func (e *expandProfileForUserMigration) MigrateResponse(r *http.Response) error {
body, err := io.ReadAll(r.Body)
if err != nil {
return err
}

func (e *expandProfileForUserMigration) Migrate(
body []byte,
h http.Header) ([]byte, http.Header, error) {
var res ServerResponse
err = json.Unmarshal(body, &res)
err := json.Unmarshal(body, &res)
if err != nil {
return err
return nil, nil, err
}

var users []*User
err = json.Unmarshal(res.Data, &users)
if err != nil {
return err
return nil, nil, err
}

var newUsers []*oldUser20230501
Expand All @@ -144,9 +123,8 @@ func (e *expandProfileForUserMigration) MigrateResponse(r *http.Response) error

body, err = generateSuccessResponse(&newUsers, "users retrieved successfully")
if err != nil {
return err
return nil, nil, err
}

r.Body = io.NopCloser(bytes.NewReader(body))
return nil
return body, h, nil
}
49 changes: 31 additions & 18 deletions requestmigrations.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package requestmigrations

import (
"bytes"
"errors"
"io"
"net/http"
"net/http/httptest"
"net/url"
"sort"
"sync"
"time"
Expand Down Expand Up @@ -38,11 +40,8 @@ type Migrations map[string][]Migration
// needs to implement. It includes two predicate functions and two
// transformation functions.
type Migration interface {
ShouldMigrateRequest(req *http.Request) bool
MigrateRequest(req *http.Request) error

ShouldMigrateResponse(req *http.Request, res *http.Response) bool
MigrateResponse(res *http.Response) error
Migrate(data []byte, header http.Header) ([]byte, http.Header, error)
ShouldMigrateConstraint(url *url.URL, method string, data []byte, isReq bool) bool
}

type GetUserVersionFunc func(req *http.Request) (string, error)
Expand Down Expand Up @@ -271,6 +270,13 @@ func (m *migrator) applyRequestMigrations(req *http.Request) error {
return nil
}

data, err := io.ReadAll(req.Body)
if err != nil {
return err
}

header := req.Header.Clone()

for _, version := range m.versions {
migrations, ok := m.migrations[version.String()]
if !ok {
Expand All @@ -283,17 +289,22 @@ func (m *migrator) applyRequestMigrations(req *http.Request) error {
}

for _, migration := range migrations {
if !migration.ShouldMigrateRequest(req) {
if !migration.ShouldMigrateConstraint(req.URL, req.Method, data, true) {
continue
}

err := migration.MigrateRequest(req)
data, header, err = migration.Migrate(data, header)
if err != nil {
return err
}
}
}

req.Header = header

// set the body back for the rest of the middleware.
req.Body = io.NopCloser(bytes.NewReader(data))

return nil
}

Expand All @@ -302,6 +313,13 @@ func (m *migrator) applyResponseMigrations(
rr *httptest.ResponseRecorder, w http.ResponseWriter) error {
res := rr.Result()

data, err := io.ReadAll(res.Body)
if err != nil {
return err
}

header := res.Header.Clone()

for i := len(m.versions); i > 0; i-- {
version := m.versions[i-1]
migrations, ok := m.migrations[version.String()]
Expand All @@ -315,18 +333,18 @@ func (m *migrator) applyResponseMigrations(
}

for _, migration := range migrations {
if !migration.ShouldMigrateResponse(req, res) {
if !migration.ShouldMigrateConstraint(req.URL, req.Method, data, false) {
continue
}

err := migration.MigrateResponse(res)
data, header, err = migration.Migrate(data, header)
if err != nil {
return ErrServerError
}
}
}

err := m.finalResponder(w, res)
err = m.finalResponder(w, data, header)
if err != nil {
// log error.
return ErrServerError
Expand All @@ -335,17 +353,12 @@ func (m *migrator) applyResponseMigrations(
return nil
}

func (m *migrator) finalResponder(w http.ResponseWriter, res *http.Response) error {
body, err := io.ReadAll(res.Body)
if err != nil {
return err
}

for k, v := range res.Header {
func (m *migrator) finalResponder(w http.ResponseWriter, body []byte, h http.Header) error {
for k, v := range h {
w.Header()[k] = v
}

_, err = w.Write(body)
_, err := w.Write(body)
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit 8212aad

Please sign in to comment.