I get what you're saying.  I did something similar, but modifying all those 
structures places you at risk of changing the entire default specified 
behaviour of the ListenAndServeTLS because you now not only introduced the 
limitConnections integer, but you in fact brought in other 
variables/functions that should have never been changed re-introduced in 
the first place.

I want to thank you for providing what you did.  It is still very useful.

That said I was hoping for something more deeply integrated within the 
current golang compiler itself like the following:
git diff
diff --git a/src/net/http/server.go b/src/net/http/server.go
index 89574a8..f135b57 100644
--- a/src/net/http/server.go
+++ b/src/net/http/server.go
@@ -29,6 +29,7 @@ import (
        "time"
 
        "golang_org/x/net/lex/httplex"
+       "golang_org/x/net/netutil"
 )
 
 // Errors used by the HTTP server.
@@ -2747,3 +2748,40 @@ func strSliceContains(ss []string, s string) bool {
        }
        return false
 }
+
+func (srv *Server) LimitListenAndServeTLS(certFile string, keyFile string, 
maxListeners int) error  {
+       addr := srv.Addr
+       if addr == "" {
+               addr = ":https"
+       }
+
+       // Setup HTTP/2 before srv.Serve, to initialize srv.TLSConfig
+       // before we clone it and create the TLS Listener.
+       if err := srv.setupHTTP2_ListenAndServeTLS(); err != nil {
+               return err
+       }
+
+       config := cloneTLSConfig(srv.TLSConfig)
+       if !strSliceContains(config.NextProtos, "http/1.1") {
+               config.NextProtos = append(config.NextProtos, "http/1.1")
+       }
+
+       configHasCert := len(config.Certificates) > 0 || 
config.GetCertificate != nil
+       if !configHasCert || certFile != "" || keyFile != "" {
+               var err error
+               config.Certificates = make([]tls.Certificate, 1)
+               config.Certificates[0], err = tls.LoadX509KeyPair(certFile, 
keyFile)
+               if err != nil {
+                       return err
+               }
+       }
+
+       ln, err := net.Listen("tcp", addr)
+       if err != nil {
+               return err
+       }
+
+       tlsListener := 
tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config)
+       tlsListener = netutil.LimitListener(tlsListener, maxListeners)
+       return srv.Serve(tlsListener)
+}


On Thursday, August 4, 2016 at 10:45:54 AM UTC-4, Nathan Kerr wrote:
>
> I managed to expand ListenAndServeTLS and then apply LimitedListener.
>
> My code and process are posted at 
> https://pocketgophers.com/limit-https-listener/
>
> tcpKeepAliveListener ended up being the only code that was copied but not 
> specialized. It would have been nice if it were exported from the http 
> package.
>
> On Thursday, August 4, 2016 at 12:27:18 AM UTC+2, David Marceau wrote:
>>
>> I tried just what you mentioned.  Unfortunately even my interim solution 
>> when it is outside of the net.http package and within mine, there are many 
>> services that are not exported meaning I can't use them at all and the 
>> variables themselves are inaccessible.
>> I tried copying pasting some functions and tweaking them and I ended up 
>> going down a rabbit hole never to get out of.  The only way to achieve what 
>> I want would be to tweak the original golang sources for 
>> net.http.ListenAndServeTLS and stuff surrounding it.
>>
>>
>> On Wednesday, August 3, 2016 at 9:19:40 AM UTC-4, Nathan Kerr wrote:
>>>
>>> Your research revealed the essential lines from ListenAndServeTLS that 
>>> basically say: 
>>>
>>> 1. create a tls listener 
>>> 2. have the server serve using that listener 
>>>
>>> The LimitListener example follows this same pattern, just with 
>>> net.Listener instead of a tls.Listener. A careful reading reveals that 
>>> ListenAndServeTLS does not do anything to http.Server that you cannot do 
>>> from outside the http package. This means that you can implement it in your 
>>> own code; changing it to fit your needs. Your code will probably flow 
>>> something like: 
>>>
>>> 1. get a listener 
>>> 2. limit that listener 
>>> 3. create a tls.Config 
>>> 4. tlslistener on LimitedListener with config 
>>> 5. Server.Serve(tlsListener) 
>>>
>>> I am not sure if it would be better to limit before or after the tls 
>>> listener. 
>>>
>>> I call this trick expanding convenience functions and explain it in 
>>> regards to another problem at 
>>> http://pocketgophers.com/expanding-convenience-functions/ (
>>> http://pocketgophers.com/expanding-convenience-functions/). 
>>>
>>> To answer your other questions: 
>>>
>>> I think that tlsListener is not part of the Server structure (so that 
>>> you could easily fetch it and limit it) is for two reasons. First, it keeps 
>>> the server and the listener separate. There is no fundamental reason that a 
>>> single server could not serve on multiple listeners. 
>>>
>>> Second, Serve is basically an infinite loop waiting on Listener.Accept. 
>>> What would it mean to change the server's listener while it is blocked 
>>> accepting a new connection? The old listener would be blocking. If a 
>>> connection was never made to it, the new listener would never accept any 
>>> connections. 
>>>
>>> The API does give the control you need, just not in the way you looked 
>>> for it. 
>>>
>>> For that last question, controlling connections is usually done as a way 
>>> to control the use of some other resource such as cpu, memory, database 
>>> access, etc. Managing resources must be done at both the OS and server 
>>> level. What needs to be done depends on what the server needs to do, what 
>>> hardware it is running on, service level agreements, etc. Sometimes 
>>> limiting, sometimes expanding limits, sometime increasing performance. 
>>>
>>> Hope this helps.
>>
>>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to