Skip to content

Commit

Permalink
Refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
evg4b committed Nov 12, 2022
1 parent 78369b9 commit 96e41d1
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 62 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.19

require (
github.com/PuerkitoBio/purell v1.2.0
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a
github.com/gojuno/minimock/v3 v3.0.10
github.com/gorilla/mux v1.8.0
github.com/pseidemann/finish v1.2.0
Expand All @@ -18,7 +19,6 @@ require (
atomicgo.dev/keyboard v0.2.8 // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect
github.com/gookit/color v1.5.2 // indirect
github.com/lithammer/fuzzysearch v1.1.5 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
Expand Down
4 changes: 3 additions & 1 deletion internal/contracts/logger.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package contracts

import "net/http"
import (
"net/http"
)

type Logger interface {
Error(a ...interface{})
Expand Down
11 changes: 11 additions & 0 deletions internal/contracts/replacer_factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package contracts

import (
"net/url"

"github.com/evg4b/uncors/internal/urlreplacer"
)

type URLReplacerFactory interface {
Make(requestURL *url.URL) (*urlreplacer.Replacer, *urlreplacer.Replacer, error)
}
13 changes: 13 additions & 0 deletions internal/helpers/asset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package helpers

import "strings"

func AssertIsDefined(value interface{}, message ...string) {
if value == nil {
message := strings.Join(message, " ")
if len(message) == 0 {
message = "Requared variable is not defined"
}
panic(message)
}
}
41 changes: 41 additions & 0 deletions internal/helpers/asset_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package helpers_test

import (
"testing"

"github.com/evg4b/uncors/internal/helpers"
"github.com/stretchr/testify/assert"
)

func TestAssertIsDefined(t *testing.T) {
t.Run("where value is nil", func(t *testing.T) {
tests := []struct {
name string
message []string
expected string
}{
{
name: "shiuld panic with default message where message is not set",
message: []string{},
expected: "Requared variable is not defined",
},
{
name: "shiuld panic with custom message where it is set",
message: []string{"Cusom message"},
expected: "Cusom message",
},
{
name: "shiuld panic with concatanetion of all passed messages",
message: []string{"This", "is", "custom", "message"},
expected: "This is custom message",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.PanicsWithValue(t, tt.expected, func() {
helpers.AssertIsDefined(nil, tt.message...)
})
})
}
})
}
20 changes: 0 additions & 20 deletions internal/proxy/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,3 @@ func copyHeaders(source, dest http.Header, modifications modificationsMap) error

return nil
}

func (handler *Handler) makeOptionsResponse(writer http.ResponseWriter, req *http.Request) error {
header := writer.Header()
for key, values := range req.Header {
lowerKey := strings.ToLower(key)
if strings.Contains(lowerKey, "access-control-request") {
for _, value := range values {
transformedKey := strings.Replace(lowerKey, "request", "allow", 1)
header.Add(transformedKey, value)
}
}
}

handler.logger.PrintResponse(&http.Response{
StatusCode: http.StatusOK,
Request: req,
})

return nil
}
26 changes: 26 additions & 0 deletions internal/proxy/option.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package proxy

import (
"net/http"
"strings"
)

func (handler *Handler) makeOptionsResponse(writer http.ResponseWriter, req *http.Request) error {
header := writer.Header()
for key, values := range req.Header {
lowerKey := strings.ToLower(key)
if strings.Contains(lowerKey, "access-control-request") {
for _, value := range values {
transformedKey := strings.Replace(lowerKey, "request", "allow", 1)
header.Add(transformedKey, value)
}
}
}

handler.logger.PrintResponse(&http.Response{
StatusCode: http.StatusOK,
Request: req,
})

return nil
}
10 changes: 2 additions & 8 deletions internal/proxy/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,15 @@ package proxy

import (
"net/http"
"net/url"

"github.com/evg4b/uncors/internal/contracts"
"github.com/evg4b/uncors/internal/urlreplacer"
)

type URLReplacerFactory interface {
Make(requestURL *url.URL) (*urlreplacer.Replacer, *urlreplacer.Replacer, error)
}

type HandlerOption = func(*Handler)

func WithURLReplacerFactory(replacerFactory URLReplacerFactory) HandlerOption {
func WithURLReplacerFactory(replacerFactory contracts.URLReplacerFactory) HandlerOption {
return func(pm *Handler) {
pm.replacerFactory = replacerFactory
pm.replacers = replacerFactory
}
}

Expand Down
46 changes: 24 additions & 22 deletions internal/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ package proxy

import (
"fmt"
"io"
"net/http"
"strings"

"github.com/evg4b/uncors/internal/contracts"
"github.com/evg4b/uncors/internal/helpers"
"github.com/evg4b/uncors/internal/urlreplacer"
"github.com/pterm/pterm"
)

type Handler struct {
replacerFactory URLReplacerFactory
http *http.Client
logger contracts.Logger
replacers contracts.URLReplacerFactory
http *http.Client
logger contracts.Logger
}

func NewProxyHandler(options ...HandlerOption) *Handler {
Expand All @@ -24,6 +24,10 @@ func NewProxyHandler(options ...HandlerOption) *Handler {
option(handler)
}

helpers.AssertIsDefined(handler.replacers, "ProxyHandler: ReplacerFactory is not configured")
helpers.AssertIsDefined(handler.logger, "ProxyHandler: Logger is not configured")
helpers.AssertIsDefined(handler.http, "ProxyHandler: Http client is not configured")

return handler
}

Expand All @@ -42,33 +46,41 @@ func (handler *Handler) handle(resp http.ResponseWriter, req *http.Request) erro
return handler.makeOptionsResponse(resp, req)
}

targetR, sourceR, err := handler.replacerFactory.Make(req.URL)
targetRreplacer, sourceReplacer, err := handler.replacers.Make(req.URL)
if err != nil {
return fmt.Errorf("failed to transform general url: %w", err)
}

originalReq, err := handler.makeOriginalRequest(req, targetR)
originalRequest, err := handler.makeOriginalRequest(req, targetRreplacer)
if err != nil {
return fmt.Errorf("failed to create reuest to original source: %w", err)
}

originalResp, err := handler.http.Do(originalReq)
originalResponse, err := handler.executeQuery(originalRequest)
if err != nil {
return fmt.Errorf("failed to do reuest: %w", err)
return err
}

defer originalResp.Body.Close()
defer originalResponse.Body.Close()

err = handler.makeUncorsResponse(originalResp, resp, sourceR)
err = handler.makeUncorsResponse(originalResponse, resp, sourceReplacer)
if err != nil {
return fmt.Errorf("failed to make uncors response: %w", err)
}

handler.logger.PrintResponse(originalResp)

return nil
}

func (handler *Handler) executeQuery(request *http.Request) (*http.Response, error) {
originalResponse, err := handler.http.Do(request)
if err != nil {
return nil, fmt.Errorf("failed to do reuest: %w", err)
}
handler.logger.PrintResponse(originalResponse)

return originalResponse, nil
}

// nolint: unparam
func copyCookiesToSource(target *http.Response, replacer *urlreplacer.Replacer, source http.ResponseWriter) error {
for _, cookie := range target.Cookies() {
Expand All @@ -91,16 +103,6 @@ func copyCookiesToTarget(source *http.Request, replacer *urlreplacer.Replacer, t
return nil
}

func copyResponseData(resp http.ResponseWriter, targetResp *http.Response) error {
resp.WriteHeader(targetResp.StatusCode)

if _, err := io.Copy(resp, targetResp.Body); err != nil {
return fmt.Errorf("failed to copy body to response: %w", err)
}

return nil
}

func updateRequest(request *http.Request) {
request.URL.Host = request.Host

Expand Down
8 changes: 4 additions & 4 deletions internal/proxy/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ func (handler *Handler) makeOriginalRequest(
replacer *urlreplacer.Replacer,
) (*http.Request, error) {
url, _ := replacer.Replace(req.URL.String())
originalReq, err := http.NewRequestWithContext(req.Context(), req.Method, url, req.Body)
originalRequest, err := http.NewRequestWithContext(req.Context(), req.Method, url, req.Body)
if err != nil {
return nil, fmt.Errorf("failed to make requst to original server: %w", err)
}

err = copyHeaders(req.Header, originalReq.Header, modificationsMap{
err = copyHeaders(req.Header, originalRequest.Header, modificationsMap{
headers.Origin: replacer.Replace,
headers.Referer: replacer.Replace,
})
Expand All @@ -27,9 +27,9 @@ func (handler *Handler) makeOriginalRequest(
return nil, err
}

if err = copyCookiesToTarget(req, replacer, originalReq); err != nil {
if err = copyCookiesToTarget(req, replacer, originalRequest); err != nil {
return nil, fmt.Errorf("failed to copy cookies in request: %w", err)
}

return originalReq, nil
return originalRequest, nil
}
23 changes: 17 additions & 6 deletions internal/proxy/responce.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package proxy

import (
"fmt"
"io"
"net/http"

"github.com/evg4b/uncors/internal/infrastructure"
Expand All @@ -10,26 +11,36 @@ import (
)

func (handler *Handler) makeUncorsResponse(
originalResp *http.Response,
resp http.ResponseWriter,
original *http.Response,
target http.ResponseWriter,
replacer *urlreplacer.Replacer,
) error {
if err := copyCookiesToSource(originalResp, replacer, resp); err != nil {
if err := copyCookiesToSource(original, replacer, target); err != nil {
return fmt.Errorf("failed to copy cookies in request: %w", err)
}

err := copyHeaders(originalResp.Header, resp.Header(), modificationsMap{
err := copyHeaders(original.Header, target.Header(), modificationsMap{
headers.Location: replacer.Replace,
})
if err != nil {
return err
}

infrastructure.WriteCorsHeaders(resp.Header())
infrastructure.WriteCorsHeaders(target.Header())

if err = copyResponseData(resp, originalResp); err != nil {
if err = copyResponseData(target, original); err != nil {
return err
}

return nil
}

func copyResponseData(resp http.ResponseWriter, targetResp *http.Response) error {
resp.WriteHeader(targetResp.StatusCode)

if _, err := io.Copy(resp, targetResp.Body); err != nil {
return fmt.Errorf("failed to copy body to response: %w", err)
}

return nil
}

0 comments on commit 96e41d1

Please sign in to comment.