Skip to content

Commit 62747af

Browse files
committed
The big commit, modified server to breakout server engine and added an interface layer to future proof design.
Breaking changes - Anything that hit *http.Request which was bound inside revel.Request, must now use the interface stored in revel.Request.In Websockets are also changed to user revel.ServerWebsocket.
1 parent b57bb94 commit 62747af

26 files changed

+984
-380
lines changed

compress.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ type WriteFlusher interface {
4040
}
4141

4242
type CompressResponseWriter struct {
43-
http.ResponseWriter
43+
ServerResponse
4444
compressWriter WriteFlusher
4545
compressionType string
4646
headersWritten bool
@@ -102,14 +102,14 @@ func (c *CompressResponseWriter) prepareHeaders() {
102102
func (c *CompressResponseWriter) WriteHeader(status int) {
103103
c.headersWritten = true
104104
c.prepareHeaders()
105-
c.ResponseWriter.WriteHeader(status)
105+
c.ServerResponse.Header().SetStatus(status)
106106
}
107107

108108
func (c *CompressResponseWriter) Close() error {
109109
if c.compressionType != "" {
110110
_ = c.compressWriter.Close()
111111
}
112-
if w, ok := c.ResponseWriter.(io.Closer); ok {
112+
if w, ok := c.ServerResponse.GetWriter().(io.Closer); ok {
113113
_ = w.Close()
114114
}
115115
// Non-blocking write to the closenotifier, if we for some reason should
@@ -144,14 +144,14 @@ func (c *CompressResponseWriter) Write(b []byte) (int, error) {
144144
return c.compressWriter.Write(b)
145145
}
146146

147-
return c.ResponseWriter.Write(b)
147+
return c.ServerResponse.GetWriter().Write(b)
148148
}
149149

150150
// DetectCompressionType method detects the comperssion type
151151
// from header "Accept-Encoding"
152152
func (c *CompressResponseWriter) DetectCompressionType(req *Request, resp *Response) {
153153
if Config.BoolDefault("results.compressed", false) {
154-
acceptedEncodings := strings.Split(req.Request.Header.Get("Accept-Encoding"), ",")
154+
acceptedEncodings := strings.Split(req.In.GetHeader().Get("Accept-Encoding"), ",")
155155

156156
largestQ := 0.0
157157
chosenEncoding := len(compressionTypes)
@@ -220,9 +220,9 @@ func (c *CompressResponseWriter) DetectCompressionType(req *Request, resp *Respo
220220

221221
switch c.compressionType {
222222
case "gzip":
223-
c.compressWriter = gzip.NewWriter(resp.Out)
223+
c.compressWriter = gzip.NewWriter(resp.Out.GetWriter())
224224
case "deflate":
225-
c.compressWriter = zlib.NewWriter(resp.Out)
225+
c.compressWriter = zlib.NewWriter(resp.Out.GetWriter())
226226
}
227227
}
228228
}

controller.go

Lines changed: 106 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ type Controller struct {
2424
Type *ControllerType // A description of the controller type.
2525
MethodName string // The method name, e.g. "Index"
2626
MethodType *MethodType // A description of the invoked action type.
27-
AppController interface{} // The controller that was instantiated.
27+
AppController interface{} // The controller that was instantiated. extends from revel.Controller
2828
Action string // The fully qualified action name, e.g. "App.Index"
2929
ClientIP string // holds IP address of request came from
3030

@@ -39,8 +39,14 @@ type Controller struct {
3939
ViewArgs map[string]interface{} // Variables passed to the template.
4040
Validation *Validation // Data validation helpers
4141
}
42+
type BaseController struct {
43+
SetAppController (interface{})
44+
}
4245

4346
// NewController returns new controller instance for Request and Response
47+
func NewControllerEmpty() *Controller {
48+
return &Controller{}
49+
}
4450
func NewController(req *Request, resp *Response) *Controller {
4551
return &Controller{
4652
Request: req,
@@ -53,6 +59,52 @@ func NewController(req *Request, resp *Response) *Controller {
5359
},
5460
}
5561
}
62+
func (c *Controller) SetController(req *Request, resp *Response) {
63+
64+
c.Request = req
65+
c.Response = resp
66+
c.Params = new(Params)
67+
c.Args = map[string]interface{}{}
68+
c.ViewArgs = map[string]interface{}{
69+
"RunMode": RunMode,
70+
"DevMode": DevMode,
71+
}
72+
73+
}
74+
func (c *Controller) Destroy() {
75+
// When the instantiated controller gets injected
76+
// It inherits this method, so we need to
77+
// check to see if the controller is nil before performing
78+
// any actions
79+
if c == nil {
80+
return
81+
}
82+
if c.AppController != nil {
83+
c.resetAppControllerFields()
84+
// Return this instance to the pool
85+
appController := c.AppController
86+
c.AppController = nil
87+
cachedControllerMap[c.Name].Push(appController)
88+
c.AppController = nil
89+
}
90+
c.Request = nil
91+
c.Response = nil
92+
c.Params = nil
93+
c.Args = nil
94+
c.ViewArgs = nil
95+
c.Name = ""
96+
c.Type = nil
97+
c.MethodName = ""
98+
c.MethodType = nil
99+
c.Action = ""
100+
c.ClientIP = ""
101+
c.Result = nil
102+
c.Flash = Flash{}
103+
c.Session = Session{}
104+
c.Params = nil
105+
c.Validation = nil
106+
107+
}
56108

57109
// FlashParams serializes the contents of Controller.Params to the Flash
58110
// cookie.
@@ -63,7 +115,8 @@ func (c *Controller) FlashParams() {
63115
}
64116

65117
func (c *Controller) SetCookie(cookie *http.Cookie) {
66-
http.SetCookie(c.Response.Out, cookie)
118+
c.Response.Out.Header().SetCookie(cookie.String())
119+
67120
}
68121

69122
func (c *Controller) RenderError(err error) Result {
@@ -130,7 +183,7 @@ func (c *Controller) RenderTemplate(templatePath string) Result {
130183
}
131184

132185
return &RenderTemplateResult{
133-
Template: template,
186+
Template: template,
134187
ViewArgs: c.ViewArgs,
135188
}
136189
}
@@ -263,11 +316,23 @@ func (c *Controller) Redirect(val interface{}, args ...interface{}) Result {
263316
return &RedirectToActionResult{val}
264317
}
265318

319+
// This stats returns some interesting stats based on what is cached in memory
320+
// and what is available directly
321+
func (c *Controller) Stats() map[string]interface{} {
322+
result := CurrentEngine.Stats()
323+
result["revel-controllers"] = controllerStack.String()
324+
result["revel-requests"] = requestStack.String()
325+
result["revel-response"] = responseStack.String()
326+
for key,appStack := range cachedControllerMap {
327+
result["app-" + key] = appStack.String()
328+
}
329+
return result
330+
}
266331
// Message performs a lookup for the given message name using the given
267332
// arguments using the current language defined for this controller.
268333
//
269334
// The current language is set by the i18n plugin.
270-
func (c *Controller) Message(message string, args ...interface{}) (value string) {
335+
func (c *Controller) Message(message string, args ...interface{}) string {
271336
return MessageFunc(c.Request.Locale, message, args...)
272337
}
273338

@@ -286,27 +351,51 @@ func (c *Controller) SetAction(controllerName, methodName string) error {
286351

287352
c.Name, c.MethodName = c.Type.Type.Name(), c.MethodType.Name
288353
c.Action = c.Name + "." + c.MethodName
289-
354+
if _, ok := cachedControllerMap[c.Name]; !ok {
355+
// Create a new stack for this controller
356+
localType := c.Type.Type
357+
cachedControllerMap[c.Name] = NewStackLock(cachedControllerStackSize, func() interface{} {
358+
return reflect.New(localType).Interface()
359+
})
360+
}
290361
// Instantiate the controller.
291-
c.AppController = initNewAppController(c.Type, c).Interface()
362+
c.AppController = cachedControllerMap[c.Name].Pop()
363+
c.setAppControllerFields()
364+
365+
// TODO Old method, remove c.AppController = initNewAppController(c.Type, c).Interface()
292366

293367
return nil
294368
}
369+
func (c *Controller) setAppControllerFields() {
370+
appController := reflect.ValueOf(c.AppController).Elem() //.(reflect.Value).Elem()
371+
cValue := reflect.ValueOf(c)
372+
for _, index := range c.Type.ControllerIndexes {
373+
appController.FieldByIndex(index).Set(cValue)
374+
}
375+
}
376+
func (c *Controller) resetAppControllerFields() {
377+
appController := reflect.ValueOf(c.AppController).Elem()
378+
// Zero out controller
379+
for _, index := range c.Type.ControllerIndexes {
380+
appController.FieldByIndex(index).Set(reflect.Zero(reflect.TypeOf(c.AppController).Elem().FieldByIndex(index).Type))
381+
}
382+
}
295383

296384
// This is a helper that initializes (zeros) a new app controller value.
297385
// Specifically, it sets all *revel.Controller embedded types to the provided controller.
298386
// Returns a value representing a pointer to the new app controller.
299-
func initNewAppController(appControllerType *ControllerType, c *Controller) reflect.Value {
300-
var (
301-
appControllerPtr = reflect.New(appControllerType.Type)
302-
appController = appControllerPtr.Elem()
303-
cValue = reflect.ValueOf(c)
304-
)
305-
for _, index := range appControllerType.ControllerIndexes {
306-
appController.FieldByIndex(index).Set(cValue)
307-
}
308-
return appControllerPtr
309-
}
387+
// TODO Unneeded method
388+
//func initNewAppController(appControllerType *ControllerType, c *Controller) reflect.Value {
389+
// var (
390+
// appControllerPtr = reflect.New(appControllerType.Type)
391+
// appController = appControllerPtr.Elem()
392+
// cValue = reflect.ValueOf(c)
393+
// )
394+
// for _, index := range appControllerType.ControllerIndexes {
395+
// appController.FieldByIndex(index).Set(cValue)
396+
// }
397+
// return appControllerPtr
398+
//}
310399

311400
func findControllers(appControllerType reflect.Type) (indexes [][]int) {
312401
// It might be a multi-level embedding. To find the controllers, we follow

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy