Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d240869

Browse filesBrowse files
committed
An initial http engine for the revel framework
1 parent f594750 commit d240869
Copy full SHA for d240869

File tree

6 files changed

+158
-63
lines changed
Filter options

6 files changed

+158
-63
lines changed

‎fakeapp_test.go

Copy file name to clipboardExpand all lines: fakeapp_test.go
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,6 @@ func startFakeBookingApp() {
106106
RenderArgNames: map[int][]string{},
107107
},
108108
})
109-
109+
InitServerEngine(9000, GO_NATIVE_SERVER_ENGINE)
110110
runStartupHooks()
111111
}

‎server-engine.go

Copy file name to clipboard
+116Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
// Copyright (c) 2012-2016 The Revel Framework Authors, All rights reserved.
2+
// Revel Framework source code and usage is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package revel
6+
7+
import (
8+
"fmt"
9+
"net"
10+
"net/http"
11+
"time"
12+
13+
"golang.org/x/net/websocket"
14+
)
15+
16+
17+
type ServerEngine interface {
18+
// Initialize the server (non blocking)
19+
Init(init *EngineInit)
20+
// Starts the server. This will block until server is stopped
21+
Start()
22+
// Fires a new event to the server
23+
Event(event string, args interface{})
24+
// Returns the engine instance for specific calls
25+
Engine() interface{}
26+
// Returns the engine Name
27+
Name() string
28+
// Handle the request an response
29+
Handle(w http.ResponseWriter, r *http.Request)
30+
}
31+
type EngineInit struct {
32+
Address,
33+
Network string
34+
Port int
35+
Callback func(http.ResponseWriter, *http.Request, *websocket.Conn)
36+
}
37+
38+
// Register the GOHttpServer engine
39+
func init() {
40+
RegisterServerEngine(&GOHttpServer{})
41+
}
42+
type GOHttpServer struct {
43+
Server *http.Server
44+
ServerInit *EngineInit
45+
}
46+
47+
func (g *GOHttpServer) Init(init *EngineInit) {
48+
g.ServerInit = init
49+
g.Server = &http.Server{
50+
Addr: init.Address,
51+
Handler: http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request){
52+
g.Handle(writer,request)
53+
}),
54+
ReadTimeout: time.Duration(Config.IntDefault("http.timeout.read", 0)) * time.Second,
55+
WriteTimeout: time.Duration(Config.IntDefault("http.timeout.write", 0)) * time.Second,
56+
}
57+
// Server already initialized
58+
59+
60+
}
61+
func (g *GOHttpServer) Start() {
62+
go func() {
63+
time.Sleep(100 * time.Millisecond)
64+
fmt.Printf("Listening on %s...\n", g.Server.Addr)
65+
}()
66+
if HTTPSsl {
67+
if g.ServerInit.Network != "tcp" {
68+
// This limitation is just to reduce complexity, since it is standard
69+
// to terminate SSL upstream when using unix domain sockets.
70+
ERROR.Fatalln("SSL is only supported for TCP sockets. Specify a port to listen on.")
71+
}
72+
ERROR.Fatalln("Failed to listen:",
73+
g.Server.ListenAndServeTLS(HTTPSslCert, HTTPSslKey))
74+
} else {
75+
listener, err := net.Listen(g.ServerInit.Network, g.Server.Addr)
76+
if err != nil {
77+
ERROR.Fatalln("Failed to listen:", err)
78+
}
79+
ERROR.Fatalln("Failed to serve:", g.Server.Serve(listener))
80+
}
81+
82+
}
83+
84+
func (g *GOHttpServer) Handle(w http.ResponseWriter, r *http.Request) {
85+
if maxRequestSize := int64(Config.IntDefault("http.maxrequestsize", 0)); maxRequestSize > 0 {
86+
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
87+
}
88+
89+
upgrade := r.Header.Get("Upgrade")
90+
if upgrade == "websocket" || upgrade == "Websocket" {
91+
websocket.Handler(func(ws *websocket.Conn) {
92+
//Override default Read/Write timeout with sane value for a web socket request
93+
if err := ws.SetDeadline(time.Now().Add(time.Hour * 24)); err != nil {
94+
ERROR.Println("SetDeadLine failed:", err)
95+
}
96+
r.Method = "WS"
97+
g.ServerInit.Callback(w, r, ws)
98+
}).ServeHTTP(w, r)
99+
} else {
100+
g.ServerInit.Callback(w, r, nil)
101+
}
102+
}
103+
104+
const GO_NATIVE_SERVER_ENGINE = "go"
105+
106+
func (g *GOHttpServer) Name() string {
107+
return GO_NATIVE_SERVER_ENGINE
108+
}
109+
110+
func (g *GOHttpServer) Engine() interface{} {
111+
return g.Server
112+
}
113+
114+
func (g *GOHttpServer) Event(event string, args interface{}) {
115+
116+
}

‎server.go

Copy file name to clipboardExpand all lines: server.go
+27-54Lines changed: 27 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@
55
package revel
66

77
import (
8-
"fmt"
98
"io"
10-
"net"
119
"net/http"
1210
"sort"
1311
"strconv"
@@ -22,29 +20,14 @@ var (
2220
MainRouter *Router
2321
MainTemplateLoader *TemplateLoader
2422
MainWatcher *Watcher
25-
Server *http.Server
23+
//Server *http.Server
24+
serverEngineMap = map[string]ServerEngine{}
25+
CurrentEngine ServerEngine
26+
ServerEngineInit *EngineInit
2627
)
2728

28-
// This method handles all requests. It dispatches to handleInternal after
29-
// handling / adapting websocket connections.
30-
func handle(w http.ResponseWriter, r *http.Request) {
31-
if maxRequestSize := int64(Config.IntDefault("http.maxrequestsize", 0)); maxRequestSize > 0 {
32-
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
33-
}
34-
35-
upgrade := r.Header.Get("Upgrade")
36-
if upgrade == "websocket" || upgrade == "Websocket" {
37-
websocket.Handler(func(ws *websocket.Conn) {
38-
//Override default Read/Write timeout with sane value for a web socket request
39-
if err := ws.SetDeadline(time.Now().Add(time.Hour * 24)); err != nil {
40-
ERROR.Println("SetDeadLine failed:", err)
41-
}
42-
r.Method = "WS"
43-
handleInternal(w, r, ws)
44-
}).ServeHTTP(w, r)
45-
} else {
46-
handleInternal(w, r, nil)
47-
}
29+
func RegisterServerEngine(newEngine ServerEngine) {
30+
serverEngineMap[newEngine.Name()]=newEngine
4831
}
4932

5033
func handleInternal(w http.ResponseWriter, r *http.Request, ws *websocket.Conn) {
@@ -90,7 +73,7 @@ func handleInternal(w http.ResponseWriter, r *http.Request, ws *websocket.Conn)
9073
// It can be used as an alternative entry-point if one needs the http handler
9174
// to be exposed. E.g. to run on multiple addresses and ports or to set custom
9275
// TLS options.
93-
func InitServer() http.HandlerFunc {
76+
func InitServer() {
9477
runStartupHooks()
9578

9679
// Load templates
@@ -117,13 +100,20 @@ func InitServer() http.HandlerFunc {
117100
MainWatcher.Listen(MainTemplateLoader, MainTemplateLoader.paths...)
118101
}
119102

120-
return http.HandlerFunc(handle)
103+
// return http.HandlerFunc(handle)
121104
}
122105

123106
// Run the server.
124107
// This is called from the generated main file.
125108
// If port is non-zero, use that. Else, read the port from app.conf.
126109
func Run(port int) {
110+
111+
InitServerEngine(port, Config.StringDefault("server.engine",GO_NATIVE_SERVER_ENGINE))
112+
InitServer()
113+
CurrentEngine.Start()
114+
}
115+
116+
func InitServerEngine(port int, serverEngine string) {
127117
address := HTTPAddr
128118
if port == 0 {
129119
port = HTTPPort
@@ -143,35 +133,18 @@ func Run(port int) {
143133
localAddress = address + ":" + strconv.Itoa(port)
144134
}
145135

146-
Server = &http.Server{
147-
Addr: localAddress,
148-
Handler: http.HandlerFunc(handle),
149-
ReadTimeout: time.Duration(Config.IntDefault("http.timeout.read", 0)) * time.Second,
150-
WriteTimeout: time.Duration(Config.IntDefault("http.timeout.write", 0)) * time.Second,
151-
}
152-
153-
InitServer()
154-
155-
go func() {
156-
time.Sleep(100 * time.Millisecond)
157-
fmt.Printf("Listening on %s...\n", Server.Addr)
158-
}()
159-
160-
if HTTPSsl {
161-
if network != "tcp" {
162-
// This limitation is just to reduce complexity, since it is standard
163-
// to terminate SSL upstream when using unix domain sockets.
164-
ERROR.Fatalln("SSL is only supported for TCP sockets. Specify a port to listen on.")
165-
}
166-
ERROR.Fatalln("Failed to listen:",
167-
Server.ListenAndServeTLS(HTTPSslCert, HTTPSslKey))
168-
} else {
169-
listener, err := net.Listen(network, Server.Addr)
170-
if err != nil {
171-
ERROR.Fatalln("Failed to listen:", err)
172-
}
173-
ERROR.Fatalln("Failed to serve:", Server.Serve(listener))
174-
}
136+
var ok bool
137+
if CurrentEngine,ok = serverEngineMap[serverEngine];!ok {
138+
panic("Server Engine " + serverEngine +" Not found")
139+
} else {
140+
ServerEngineInit = &EngineInit{
141+
Address:localAddress,
142+
Network:network,
143+
Port:port,
144+
Callback:handleInternal,
145+
}
146+
CurrentEngine.Init(ServerEngineInit)
147+
}
175148
}
176149

177150
func runStartupHooks() {

‎server_test.go

Copy file name to clipboardExpand all lines: server_test.go
+5-5Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func benchmarkRequest(b *testing.B, req *http.Request) {
4848
b.ResetTimer()
4949
resp := httptest.NewRecorder()
5050
for i := 0; i < b.N; i++ {
51-
handle(resp, req)
51+
CurrentEngine.Handle(resp, req)
5252
}
5353
}
5454

@@ -59,29 +59,29 @@ func TestFakeServer(t *testing.T) {
5959
resp := httptest.NewRecorder()
6060

6161
// First, test that the expected responses are actually generated
62-
handle(resp, showRequest)
62+
CurrentEngine.Handle(resp, showRequest)
6363
if !strings.Contains(resp.Body.String(), "300 Main St.") {
6464
t.Errorf("Failed to find hotel address in action response:\n%s", resp.Body)
6565
t.FailNow()
6666
}
6767
resp.Body.Reset()
6868

69-
handle(resp, staticRequest)
69+
CurrentEngine.Handle(resp, staticRequest)
7070
sessvarsSize := getFileSize(t, filepath.Join(BasePath, "public", "js", "sessvars.js"))
7171
if int64(resp.Body.Len()) != sessvarsSize {
7272
t.Errorf("Expected sessvars.js to have %d bytes, got %d:\n%s", sessvarsSize, resp.Body.Len(), resp.Body)
7373
t.FailNow()
7474
}
7575
resp.Body.Reset()
7676

77-
handle(resp, jsonRequest)
77+
CurrentEngine.Handle(resp, jsonRequest)
7878
if !strings.Contains(resp.Body.String(), `"Address":"300 Main St."`) {
7979
t.Errorf("Failed to find hotel address in JSON response:\n%s", resp.Body)
8080
t.FailNow()
8181
}
8282
resp.Body.Reset()
8383

84-
handle(resp, plaintextRequest)
84+
CurrentEngine.Handle(resp, plaintextRequest)
8585
if resp.Body.String() != "Hello, World!" {
8686
t.Errorf("Failed to find greeting in plaintext response:\n%s", resp.Body)
8787
t.FailNow()

‎template.go

Copy file name to clipboardExpand all lines: template.go
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,15 @@ type TemplateWatcher interface {
4444
}
4545

4646
type Template interface {
47+
// #Name: The name of the template.
4748
Name() string // Name of template
49+
// #Content: The content of the template as a string (Used in error handling).
4850
Content() []string // Content
51+
// #Render: Called by the server to render the template out the io.Writer, args contains the arguements to be passed to the template.
52+
// arg: wr io.Writer
53+
// arg: arg interface{}
4954
Render(wr io.Writer, arg interface{}) error
55+
// #Location: The full path to the file on the disk.
5056
Location() string // Disk location
5157
}
5258

‎testing/testsuite.go

Copy file name to clipboardExpand all lines: testing/testsuite.go
+3-3Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,10 +69,10 @@ func (t *TestSuite) NewTestRequest(req *http.Request) *TestRequest {
6969

7070
// Host returns the address and port of the server, e.g. "127.0.0.1:8557"
7171
func (t *TestSuite) Host() string {
72-
if revel.Server.Addr[0] == ':' {
73-
return "127.0.0.1" + revel.Server.Addr
72+
if revel.ServerEngineInit.Address[0] == ':' {
73+
return "127.0.0.1" + revel.ServerEngineInit.Address
7474
}
75-
return revel.Server.Addr
75+
return revel.ServerEngineInit.Address
7676
}
7777

7878
// BaseUrl returns the base http/https URL of the server, e.g. "http://127.0.0.1:8557".

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.