Passed
Push — master ( 7fc31c...e5d363 )
by Igor
04:51 queued 02:47
created

di.*Factory.CreateSpecificationLoader   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
package di
2
3
import (
4
	"fmt"
5
	"io/ioutil"
6
	"log"
7
	"net/http"
8
	"os"
9
10
	"github.com/getkin/kin-openapi/openapi3"
11
	"github.com/getkin/kin-openapi/openapi3filter"
12
	"github.com/gorilla/handlers"
13
	"github.com/muonsoft/openapi-mock/internal/application/config"
14
	responseGenerator "github.com/muonsoft/openapi-mock/internal/openapi/generator"
15
	"github.com/muonsoft/openapi-mock/internal/openapi/generator/data"
16
	"github.com/muonsoft/openapi-mock/internal/openapi/handler"
17
	"github.com/muonsoft/openapi-mock/internal/openapi/loader"
18
	"github.com/muonsoft/openapi-mock/internal/openapi/responder"
19
	"github.com/muonsoft/openapi-mock/internal/server"
20
	"github.com/muonsoft/openapi-mock/internal/server/middleware"
21
	"github.com/sirupsen/logrus"
22
	"github.com/unrolled/secure"
23
)
24
25
type Factory struct {
26
	configuration *config.Configuration
27
	logger        logrus.FieldLogger
28
}
29
30
func NewFactory(configuration *config.Configuration) *Factory {
31
	logger := createLogger(configuration)
32
33
	return &Factory{
34
		configuration: configuration,
35
		logger:        logger,
36
	}
37
}
38
39
func init() {
40
	openapi3.DefineStringFormat("uuid", openapi3.FormatOfStringForUUIDOfRFC4122)
41
	openapi3.DefineStringFormat("html", "<[^>]+>|&[^;]+;")
42
}
43
44
func (factory *Factory) GetLogger() logrus.FieldLogger {
45
	return factory.logger
46
}
47
48
func (factory *Factory) CreateSpecificationLoader() loader.SpecificationLoader {
49
	return loader.New()
50
}
51
52
func (factory *Factory) CreateHTTPHandler(router *openapi3filter.Router) http.Handler {
53
	generatorOptions := data.Options{
54
		UseExamples:     factory.configuration.UseExamples,
55
		NullProbability: factory.configuration.NullProbability,
56
		DefaultMinInt:   factory.configuration.DefaultMinInt,
57
		DefaultMaxInt:   factory.configuration.DefaultMaxInt,
58
		DefaultMinFloat: factory.configuration.DefaultMinFloat,
59
		DefaultMaxFloat: factory.configuration.DefaultMaxFloat,
60
		SuppressErrors:  factory.configuration.SuppressErrors,
61
	}
62
63
	dataGeneratorInstance := data.New(generatorOptions)
64
	responseGeneratorInstance := responseGenerator.New(dataGeneratorInstance)
65
	apiResponder := responder.New()
66
67
	var httpHandler http.Handler
68
	httpHandler = handler.NewResponseGeneratorHandler(router, responseGeneratorInstance, apiResponder)
69
	if factory.configuration.CORSEnabled {
70
		httpHandler = middleware.CORSHandler(httpHandler)
71
	}
72
73
	secureMiddleware := secure.New(secure.Options{
74
		FrameDeny:             true,
75
		ContentTypeNosniff:    true,
76
		BrowserXssFilter:      true,
77
		ContentSecurityPolicy: "default-src 'self'",
78
	})
79
80
	httpHandler = secureMiddleware.Handler(httpHandler)
81
	httpHandler = middleware.ContextLoggerHandler(factory.logger, httpHandler)
82
	httpHandler = middleware.TracingHandler(httpHandler)
83
	httpHandler = handlers.CombinedLoggingHandler(os.Stdout, httpHandler)
84
	httpHandler = handlers.RecoveryHandler(
85
		handlers.RecoveryLogger(factory.logger),
86
		handlers.PrintRecoveryStack(true),
87
	)(httpHandler)
88
	httpHandler = http.TimeoutHandler(httpHandler, factory.configuration.ResponseTimeout, "")
89
90
	return httpHandler
91
}
92
93
func (factory *Factory) CreateHTTPServer() (server.Server, error) {
94
	logger := factory.GetLogger()
95
	loggerWriter := logger.(*logrus.Logger).Writer()
96
97
	specificationLoader := factory.CreateSpecificationLoader()
98
	specification, err := specificationLoader.LoadFromURI(factory.configuration.SpecificationURL)
99
	if err != nil {
100
		return nil, fmt.Errorf("failed to load OpenAPI specification from '%s': %w", factory.configuration.SpecificationURL, err)
101
	}
102
103
	logger.Infof("OpenAPI specification was successfully loaded from '%s'", factory.configuration.SpecificationURL)
104
105
	router := openapi3filter.NewRouter().WithSwagger(specification)
106
	httpHandler := factory.CreateHTTPHandler(router)
107
108
	serverLogger := log.New(loggerWriter, "[HTTP]: ", log.LstdFlags)
109
	httpServer := server.New(factory.configuration.Port, httpHandler, serverLogger)
110
111
	logger.WithFields(factory.configuration.Dump()).Info("OpenAPI mock server was created")
112
113
	return httpServer, nil
114
}
115
116
func createLogger(configuration *config.Configuration) *logrus.Logger {
117
	logger := logrus.New()
118
	if configuration.DryRun {
119
		logger.Out = ioutil.Discard
120
		return logger
121
	}
122
123
	logger.SetLevel(configuration.LogLevel)
124
125
	if configuration.LogFormat == "json" {
126
		logger.SetFormatter(&logrus.JSONFormatter{})
127
	} else {
128
		logger.SetFormatter(&logrus.TextFormatter{})
129
	}
130
131
	return logger
132
}
133