1
9
10 package config
11
12 import (
13 "encoding/json"
14 "io"
15 "net/http"
16 "strconv"
17
18 "github.com/gin-gonic/gin"
19 "gitlab.hexacode.org/go-libs/hctypes"
20 "gitlab.hexacode.org/go-libs/microservice/validate"
21 )
22
23 type ConfigContext struct {
24 Method string `json:"method,omitempty"`
25 Url string `json:"url,omitempty"`
26 Config *Config `json:"config,omitempty"`
27 ConfigApi *ConfigAPI `json:"config_api,omitempty"`
28 URLParams hctypes.Dict `json:"url_params,omitempty"`
29 Params hctypes.Dict `json:"params,omitempty"`
30 Headers hctypes.Dict `json:"headers,omitempty"`
31 Request *http.Request `json:"-"`
32 Writer http.ResponseWriter `json:"-"`
33 }
34
35 type ConfigAPI struct {
36 Name string `json:"name,omitempty"`
37 Path string `json:"path,omitempty"`
38 Method string `json:"method,omitempty"`
39 ContentType string `json:"content_type,omitempty"`
40 ResponseType string `json:"response_type,omitempty"`
41 Timeout string `json:"timeout,omitempty"`
42 Callback *ConfigCallback `json:"callback,omitempty"`
43 Params []*validate.Options `json:"params,omitempty"`
44 URLParams []*validate.Options `json:"url_params,omitempty"`
45 ExtraConfig hctypes.Dict `json:"extra_config,omitempty"`
46 config *Config `json:"-"`
47 }
48
49 type ReturnHTTPError struct {
50 StatusCode int `json:"status"`
51 Result hctypes.Dict `json:"result,omitempty"`
52 Errors []*ReturnError `json:"errors,omitempty"`
53 }
54
55 func (config_api *ConfigAPI) ForPublic() *ConfigAPI {
56 return &ConfigAPI{
57 Name: config_api.Name,
58 Path: config_api.Path,
59 Method: config_api.Method,
60 ContentType: config_api.ContentType,
61 ResponseType: config_api.ResponseType,
62 Params: config_api.Params,
63 URLParams: config_api.URLParams,
64 }
65 }
66
67 func (config_api *ConfigAPI) ValidParams(data hctypes.Dict) *ReturnError {
68 params_opt := config_api.Params
69
70 errs := validate.Validate(params_opt, data)
71 if len(errs) > 0 {
72 return &ReturnError{
73 Name: "params",
74 Errors: errs,
75 }
76 }
77
78 return nil
79 }
80
81 func (config_api *ConfigAPI) ValidURLParams(data hctypes.Dict) *ReturnError {
82 params_opt := config_api.URLParams
83
84 errs := validate.Validate(params_opt, data)
85 if len(errs) > 0 {
86 return &ReturnError{
87 Name: "url_params",
88 Errors: errs,
89 }
90 }
91
92 return nil
93 }
94
95 func (config_api *ConfigAPI) HTTPHandlerConfig(ctx *gin.Context) {
96 render(ctx, config_api.ForPublic())
97 }
98
99 func render(ctx *gin.Context, data interface{}) {
100 buff, err := json.Marshal(data)
101 if err != nil {
102 return
103 }
104
105 ctx.Writer.WriteHeader(http.StatusOK)
106 ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
107 ctx.Writer.Header().Set("Access-Control-Allow-Methods", "POST, HEAD, PATCH, OPTIONS, GET, PUT, TRACE")
108 ctx.Writer.Header().Set("Access-Control-Allow-Headers", "*")
109 ctx.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
110 ctx.Writer.Header().Set("Content-Type", "application/json")
111 ctx.Writer.Header().Set("Content-Length", strconv.Itoa(len(buff)))
112 ctx.Writer.WriteHeaderNow()
113 ctx.Writer.Write(buff)
114 }
115
116 func options_handler(ctx *gin.Context) {
117 ctx.Writer.WriteHeader(http.StatusOK)
118 ctx.Writer.Header().Set("Access-Control-Allow-Origin", "*")
119 ctx.Writer.Header().Set("Access-Control-Allow-Methods", "POST, HEAD, PATCH, OPTIONS, GET, PUT, TRACE")
120 ctx.Writer.Header().Set("Access-Control-Allow-Headers", "*")
121 ctx.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
122 ctx.Writer.Header().Set("Content-Length", "0")
123 ctx.Writer.WriteHeaderNow()
124 }
125
126 func (config_api *ConfigAPI) HTTPHandler(ctx *gin.Context) {
127 url_params := hctypes.Dict{}
128 params := hctypes.Dict{}
129 headers := hctypes.Dict{}
130
131 raw_headers := ctx.Request.Header.Clone()
132
133 for k, v := range raw_headers {
134 headers[k] = hctypes.String(v[0])
135 }
136
137 for _, param := range ctx.Params {
138 url_params[param.Key] = hctypes.String(param.Value)
139 }
140
141 ret_err := []*ReturnError{}
142
143 url_params_err := config_api.ValidURLParams(url_params)
144 if url_params_err != nil {
145 ret_err = append(ret_err, url_params_err)
146 }
147
148 if config_api.Params != nil {
149 if len(config_api.Params) > 0 {
150 if bytes, err := io.ReadAll(ctx.Request.Body); err == nil {
151 params = hctypes.NewDictFromJson(hctypes.Buffer(bytes))
152 } else {
153 params = hctypes.Dict{}
154 }
155 }
156 }
157
158 params_err := config_api.ValidParams(params)
159 if params_err != nil {
160 ret_err = append(ret_err, params_err)
161 }
162
163 if len(ret_err) > 0 {
164 render(ctx, &ReturnHTTPError{
165 StatusCode: 400,
166 Errors: ret_err,
167 Result: hctypes.Dict{},
168 })
169 return
170 }
171
172 code, ret, err := config_api.Callback.function(&ConfigContext{
173 Method: ctx.Request.Method,
174 Url: ctx.Request.URL.Path,
175 Config: config_api.config,
176 ConfigApi: config_api,
177 Params: params,
178 URLParams: url_params,
179 Headers: headers,
180 Request: ctx.Request,
181 Writer: ctx.Writer,
182 })
183
184 if err != nil {
185 render(ctx, &err)
186 return
187 }
188
189 if ret != nil {
190 render(ctx, &ReturnHTTPError{
191 StatusCode: code,
192 Errors: []*ReturnError{},
193 Result: ret,
194 })
195 }
196 }
197
198 func (ctx *ConfigContext) Error(status int, message string) (int, hctypes.Dict, *ReturnHTTPError) {
199 return status, nil, &ReturnHTTPError{
200 StatusCode: status,
201 Result: hctypes.Dict{},
202 Errors: []*ReturnError{
203 &ReturnError{
204 Name: ctx.Config.Namespace,
205 Errors: []*validate.ValidateError{
206 &validate.ValidateError{
207 Name: ctx.ConfigApi.Name,
208 Message: message,
209 },
210 },
211 },
212 },
213 }
214 }
215
216 func (config_api *ConfigAPI) ToDict() hctypes.Dict {
217 bytes, _ := json.Marshal(config_api)
218 return hctypes.NewDictFromJson(hctypes.Buffer(bytes))
219 }
220
View as plain text