11package http
22
33import (
4+ "crypto/tls"
5+ "crypto/x509"
6+ ioutil2 "io/ioutil"
47 "log"
58 "net"
69 "net/http"
@@ -82,13 +85,70 @@ func (s *luaServer) serve(L *lua.LState) {
8285
8386// http.server(bind, handler) returns (user data, error)
8487func New (L * lua.LState ) int {
85- bind := L .CheckAny (1 ).String ()
88+ var tlsConfig * tls.Config
89+ bind := "127.0.0.1:0"
90+ switch bindOrTable := L .CheckAny (1 ).(type ) {
91+ case lua.LString :
92+ bind = string (bindOrTable )
93+ case * lua.LTable :
94+ if addr , ok := L .GetField (bindOrTable , "addr" ).(lua.LString ); ok {
95+ bind = string (addr )
96+ }
97+ serverPublicCertPEMFile := L .GetField (bindOrTable , `server_public_cert_pem_file` )
98+ serverPrivateKeyPemFile := L .GetField (bindOrTable , `server_private_key_pem_file` )
99+ if serverPublicCertPEMFile != lua .LNil && serverPrivateKeyPemFile != lua .LNil {
100+ serverCert , err := tls .LoadX509KeyPair (serverPublicCertPEMFile .String (), serverPrivateKeyPemFile .String ())
101+ if err != nil {
102+ L .RaiseError ("error loading server cert: %v" , err )
103+ }
104+ tlsConfig = & tls.Config {
105+ Certificates : []tls.Certificate {serverCert },
106+ }
107+
108+ clientAuth := L .GetField (bindOrTable , "client_auth" )
109+ if clientAuth != lua .LNil {
110+ if _ , ok := clientAuth .(lua.LString ); ! ok {
111+ L .ArgError (1 , "client_auth should be a string" )
112+ }
113+ switch clientAuth .String () {
114+ case "NoClientCert" :
115+ tlsConfig .ClientAuth = tls .NoClientCert
116+ case "RequestClientCert" :
117+ tlsConfig .ClientAuth = tls .RequestClientCert
118+ case "RequireAnyClientCert" :
119+ tlsConfig .ClientAuth = tls .RequireAnyClientCert
120+ case "VerifyClientCertIfGiven" :
121+ tlsConfig .ClientAuth = tls .VerifyClientCertIfGiven
122+ case "RequireAndVerifyClientCert" :
123+ tlsConfig .ClientAuth = tls .RequireAndVerifyClientCert
124+ }
125+ }
126+
127+ clientCAs := L .GetField (bindOrTable , "client_cas_pem_file" )
128+ if clientCAs != lua .LNil {
129+ if _ , ok := clientCAs .(lua.LString ); ! ok {
130+ L .ArgError (1 , "client_cas_pem_file must be a string" )
131+ }
132+ data , err := ioutil2 .ReadFile (clientCAs .String ())
133+ if err != nil {
134+ L .RaiseError ("error reading %s: %v" , clientCAs , err )
135+ }
136+ tlsConfig .ClientCAs = x509 .NewCertPool ()
137+ if ! tlsConfig .ClientCAs .AppendCertsFromPEM (data ) {
138+ L .RaiseError ("no certs loaded from %s" , clientCAs )
139+ }
140+ }
141+ }
142+ }
86143 l , err := net .Listen (`tcp` , bind )
87144 if err != nil {
88145 L .Push (lua .LNil )
89146 L .Push (lua .LString (err .Error ()))
90147 return 2
91148 }
149+ if tlsConfig != nil {
150+ l = tls .NewListener (l , tlsConfig )
151+ }
92152 server := & luaServer {
93153 Listener : l ,
94154 serveData : make (chan * serveData , 1 ),
@@ -112,6 +172,13 @@ func Accept(L *lua.LState) int {
112172 }
113173}
114174
175+ // Addr returns the address if, for instance, one listens on :0
176+ func Addr (L * lua.LState ) int {
177+ s := checkServer (L , 1 )
178+ L .Push (lua .LString (s .Listener .Addr ().String ()))
179+ return 1
180+ }
181+
115182func newHandlerState (data * serveData ) * lua.LState {
116183 state := lua .NewState ()
117184
@@ -185,16 +252,18 @@ func HandleFile(L *lua.LState) int {
185252func HandleString (L * lua.LState ) int {
186253 s := checkServer (L , 1 )
187254 body := L .CheckString (2 )
188- select {
189- case data := <- s .serveData :
190- go func (sData * serveData , content string ) {
191- state := newHandlerState (sData )
192- if err := state .DoString (content ); err != nil {
193- log .Printf ("[ERROR] handle: %s\n " , err .Error ())
194- data .done <- true
195- log .Printf ("[ERROR] closed connection\n " )
196- }
197- }(data , body )
255+ for {
256+ select {
257+ case data := <- s .serveData :
258+ go func (sData * serveData , content string ) {
259+ state := newHandlerState (sData )
260+ if err := state .DoString (content ); err != nil {
261+ log .Printf ("[ERROR] handle: %s\n " , err .Error ())
262+ data .done <- true
263+ log .Printf ("[ERROR] closed connection\n " )
264+ }
265+ }(data , body )
266+ }
198267 }
199268 return 0
200269}
0 commit comments