Use more buffered I/O
This commit is contained in:
		
							parent
							
								
									3980cfd28f
								
							
						
					
					
						commit
						4b27a736ac
					
				| @ -25,7 +25,7 @@ func main() { | |||||||
| 	config.Certificates = append(config.Certificates, cert) | 	config.Certificates = append(config.Certificates, cert) | ||||||
| 	config.ClientAuth = tls.RequestClientCert | 	config.ClientAuth = tls.RequestClientCert | ||||||
| 
 | 
 | ||||||
| 	mux := &gemini.Mux{} | 	mux := &gemini.ServeMux{} | ||||||
| 	mux.HandleFunc("/", func(rw gemini.ResponseWriter, req *gemini.Request) { | 	mux.HandleFunc("/", func(rw gemini.ResponseWriter, req *gemini.Request) { | ||||||
| 		log.Printf("Request from %s for %s with certificates %v", req.RemoteAddr.String(), req.URL.String(), req.TLS.PeerCertificates) | 		log.Printf("Request from %s for %s with certificates %v", req.RemoteAddr.String(), req.URL.String(), req.TLS.PeerCertificates) | ||||||
| 		rw.WriteHeader(gemini.StatusSuccess, "text/gemini") | 		rw.WriteHeader(gemini.StatusSuccess, "text/gemini") | ||||||
|  | |||||||
							
								
								
									
										70
									
								
								gemini.go
									
									
									
									
									
								
							
							
						
						
									
										70
									
								
								gemini.go
									
									
									
									
									
								
							| @ -5,7 +5,6 @@ import ( | |||||||
| 	"bufio" | 	"bufio" | ||||||
| 	"crypto/tls" | 	"crypto/tls" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"io" |  | ||||||
| 	"io/ioutil" | 	"io/ioutil" | ||||||
| 	"log" | 	"log" | ||||||
| 	"net" | 	"net" | ||||||
| @ -159,12 +158,10 @@ type Response struct { | |||||||
| 	Meta string | 	Meta string | ||||||
| 
 | 
 | ||||||
| 	// Body contains the response body. | 	// Body contains the response body. | ||||||
| 	// Body is only used by the server for successful responses. |  | ||||||
| 	Body []byte | 	Body []byte | ||||||
| 
 | 
 | ||||||
| 	// TLS contains information about the TLS connection on which the response | 	// TLS contains information about the TLS connection on which the response | ||||||
| 	// was received. | 	// was received. | ||||||
| 	// This field is ignored by the server. |  | ||||||
| 	TLS tls.ConnectionState | 	TLS tls.ConnectionState | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -194,8 +191,8 @@ func Get(url string) (*Response, error) { | |||||||
| 	return Do(req) | 	return Do(req) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ProxyRequest requests the provided URL from the provided host. | // ProxyGet requests the provided URL from the provided host. | ||||||
| func ProxyRequest(host, url string) (*Response, error) { | func ProxyGet(host, url string) (*Response, error) { | ||||||
| 	req, err := NewProxyRequest(host, url) | 	req, err := NewProxyRequest(host, url) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| @ -254,7 +251,7 @@ func Do(req *Request) (*Response, error) { | |||||||
| 	// Trim carriage return | 	// Trim carriage return | ||||||
| 	meta = meta[:len(meta)-1] | 	meta = meta[:len(meta)-1] | ||||||
| 
 | 
 | ||||||
| 	// Ensure meta is less than 1024 bytes | 	// Ensure meta is less than or equal to 1024 bytes | ||||||
| 	if len(meta) > 1024 { | 	if len(meta) > 1024 { | ||||||
| 		return nil, ErrProtocol | 		return nil, ErrProtocol | ||||||
| 	} | 	} | ||||||
| @ -371,26 +368,39 @@ func (r *response) Write(b []byte) (int, error) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // respond responds to a connection. | // respond responds to a connection. | ||||||
| func (s *Server) respond(rw net.Conn) { | func (s *Server) respond(conn net.Conn) { | ||||||
| 	resp := newResponse(rw) | 	r := bufio.NewReader(conn) | ||||||
| 	if rawurl, err := readLine(rw); err != nil { | 	rw := newResponse(conn) | ||||||
| 		resp.WriteHeader(StatusBadRequest, "Bad request") | 	// Read requested URL | ||||||
| 	} else if len(rawurl) > 1024 { | 	rawurl, err := r.ReadString('\r') | ||||||
| 		resp.WriteHeader(StatusBadRequest, "Requested URL exceeds 1024 bytes") | 	if err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	// Trim carriage return | ||||||
|  | 	rawurl = rawurl[:len(rawurl)-1] | ||||||
|  | 	// Read terminating line feed | ||||||
|  | 	if b, err := r.ReadByte(); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} else if b != '\n' { | ||||||
|  | 		rw.WriteHeader(StatusBadRequest, "Bad request") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if len(rawurl) > 1024 { | ||||||
|  | 		rw.WriteHeader(StatusBadRequest, "Requested URL exceeds 1024 bytes") | ||||||
| 	} else if url, err := url.Parse(rawurl); err != nil || url.User != nil { | 	} else if url, err := url.Parse(rawurl); err != nil || url.User != nil { | ||||||
| 		// Note that we return an error if User is specified in the URL. | 		// Note that we return an error status if User is specified in the URL | ||||||
| 		resp.WriteHeader(StatusBadRequest, "Requested URL is invalid") | 		rw.WriteHeader(StatusBadRequest, "Requested URL is invalid") | ||||||
| 	} else { | 	} else { | ||||||
| 		// Gather information about the request | 		// Gather information about the request | ||||||
| 		req := &Request{ | 		req := &Request{ | ||||||
| 			URL:        url, | 			URL:        url, | ||||||
| 			RemoteAddr: rw.RemoteAddr(), | 			RemoteAddr: conn.RemoteAddr(), | ||||||
| 			TLS:        rw.(*tls.Conn).ConnectionState(), | 			TLS:        conn.(*tls.Conn).ConnectionState(), | ||||||
| 		} | 		} | ||||||
| 		s.Handler.Serve(resp, req) | 		s.Handler.Serve(rw, req) | ||||||
| 	} | 	} | ||||||
| 	resp.w.Flush() | 	rw.w.Flush() | ||||||
| 	rw.Close() | 	conn.Close() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // A Handler responds to a Gemini request. | // A Handler responds to a Gemini request. | ||||||
| @ -399,11 +409,11 @@ type Handler interface { | |||||||
| 	Serve(ResponseWriter, *Request) | 	Serve(ResponseWriter, *Request) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Mux is a Gemini request multiplexer. | // ServeMux is a Gemini request multiplexer. | ||||||
| // It matches the URL of each incoming request against a list of registered | // It matches the URL of each incoming request against a list of registered | ||||||
| // patterns and calls the handler for the pattern that most closesly matches | // patterns and calls the handler for the pattern that most closesly matches | ||||||
| // the URL. | // the URL. | ||||||
| type Mux struct { | type ServeMux struct { | ||||||
| 	entries []muxEntry | 	entries []muxEntry | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -414,7 +424,7 @@ type muxEntry struct { | |||||||
| 	handler Handler | 	handler Handler | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *Mux) match(url *url.URL) Handler { | func (m *ServeMux) match(url *url.URL) Handler { | ||||||
| 	for _, e := range m.entries { | 	for _, e := range m.entries { | ||||||
| 		if (e.scheme == "" || url.Scheme == e.scheme) && | 		if (e.scheme == "" || url.Scheme == e.scheme) && | ||||||
| 			(e.host == "" || url.Host == e.host) && | 			(e.host == "" || url.Host == e.host) && | ||||||
| @ -426,7 +436,7 @@ func (m *Mux) match(url *url.URL) Handler { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Handle registers a Handler for the given pattern. | // Handle registers a Handler for the given pattern. | ||||||
| func (m *Mux) Handle(pattern string, handler Handler) { | func (m *ServeMux) Handle(pattern string, handler Handler) { | ||||||
| 	url, err := url.Parse(pattern) | 	url, err := url.Parse(pattern) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		panic(err) | 		panic(err) | ||||||
| @ -440,13 +450,13 @@ func (m *Mux) Handle(pattern string, handler Handler) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // HandleFunc registers a HandlerFunc for the given pattern. | // HandleFunc registers a HandlerFunc for the given pattern. | ||||||
| func (m *Mux) HandleFunc(pattern string, handlerFunc func(ResponseWriter, *Request)) { | func (m *ServeMux) HandleFunc(pattern string, handlerFunc func(ResponseWriter, *Request)) { | ||||||
| 	handler := HandlerFunc(handlerFunc) | 	handler := HandlerFunc(handlerFunc) | ||||||
| 	m.Handle(pattern, handler) | 	m.Handle(pattern, handler) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // Serve responds to the request with the appropriate handler. | // Serve responds to the request with the appropriate handler. | ||||||
| func (m *Mux) Serve(rw ResponseWriter, req *Request) { | func (m *ServeMux) Serve(rw ResponseWriter, req *Request) { | ||||||
| 	h := m.match(req.URL) | 	h := m.match(req.URL) | ||||||
| 	if h == nil { | 	if h == nil { | ||||||
| 		rw.WriteHeader(StatusNotFound, "Not found") | 		rw.WriteHeader(StatusNotFound, "Not found") | ||||||
| @ -461,13 +471,3 @@ type HandlerFunc func(ResponseWriter, *Request) | |||||||
| func (f HandlerFunc) Serve(rw ResponseWriter, req *Request) { | func (f HandlerFunc) Serve(rw ResponseWriter, req *Request) { | ||||||
| 	f(rw, req) | 	f(rw, req) | ||||||
| } | } | ||||||
| 
 |  | ||||||
| // readLine reads a line. |  | ||||||
| func readLine(r io.Reader) (string, error) { |  | ||||||
| 	scanner := bufio.NewScanner(r) |  | ||||||
| 	scanner.Scan() |  | ||||||
| 	if err := scanner.Err(); err != nil { |  | ||||||
| 		return "", err |  | ||||||
| 	} |  | ||||||
| 	return scanner.Text(), nil |  | ||||||
| } |  | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user