| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | // Copyright 2009 The Go Authors. All rights reserved. | 
					
						
							|  |  |  | // Use of this source code is governed by a BSD-style | 
					
						
							|  |  |  | // license that can be found in the LICENSE file. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | // HTTP server.  See RFC 2616. | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | // TODO(rsc): | 
					
						
							|  |  |  | //	logging | 
					
						
							|  |  |  | //	cgi support | 
					
						
							|  |  |  | //	post support | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | package http | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	"bufio" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"io" | 
					
						
							|  |  |  | 	"log" | 
					
						
							|  |  |  | 	"net" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"path" | 
					
						
							|  |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // Errors introduced by the HTTP server. | 
					
						
							|  |  |  | var ( | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	ErrWriteAfterFlush = os.NewError("Conn.Write called after Flush") | 
					
						
							| 
									
										
										
										
											2010-06-03 16:09:37 -07:00
										 |  |  | 	ErrBodyNotAllowed  = os.NewError("http: response status code does not allow body") | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	ErrHijacked        = os.NewError("Conn has been hijacked") | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | ) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-15 00:27:40 -07:00
										 |  |  | // Objects implementing the Handler interface can be | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // registered to serve a particular path or subtree | 
					
						
							|  |  |  | // in the HTTP server. | 
					
						
							| 
									
										
										
										
											2010-02-12 14:27:44 -08:00
										 |  |  | // | 
					
						
							|  |  |  | // ServeHTTP should write reply headers and data to the Conn | 
					
						
							|  |  |  | // and then return.  Returning signals that the request is finished | 
					
						
							|  |  |  | // and that the HTTP server can move on to the next request on | 
					
						
							|  |  |  | // the connection. | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | type Handler interface { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	ServeHTTP(*Conn, *Request) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // A Conn represents the server side of a single active HTTP connection. | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | type Conn struct { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	RemoteAddr string   // network address of remote side | 
					
						
							|  |  |  | 	Req        *Request // current HTTP request | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	rwc      io.ReadWriteCloser // i/o connection | 
					
						
							|  |  |  | 	buf      *bufio.ReadWriter  // buffered rwc | 
					
						
							|  |  |  | 	handler  Handler            // request handler | 
					
						
							|  |  |  | 	hijacked bool               // connection has been hijacked by handler | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// state for the current reply | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	closeAfterReply bool              // close connection after this reply | 
					
						
							|  |  |  | 	chunking        bool              // using chunked transfer encoding for reply body | 
					
						
							|  |  |  | 	wroteHeader     bool              // reply header has been written | 
					
						
							| 
									
										
										
										
											2010-06-16 10:15:39 -07:00
										 |  |  | 	wroteContinue   bool              // 100 Continue response was written | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	header          map[string]string // reply header parameters | 
					
						
							|  |  |  | 	written         int64             // number of bytes written in body | 
					
						
							|  |  |  | 	status          int               // status code passed to WriteHeader | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Create new connection from rwc. | 
					
						
							| 
									
										
										
										
											2009-11-02 18:37:30 -08:00
										 |  |  | func newConn(rwc net.Conn, handler Handler) (c *Conn, err os.Error) { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c = new(Conn) | 
					
						
							| 
									
										
										
										
											2009-11-02 18:37:30 -08:00
										 |  |  | 	if a := rwc.RemoteAddr(); a != nil { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		c.RemoteAddr = a.String() | 
					
						
							| 
									
										
										
										
											2009-11-02 18:37:30 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.handler = handler | 
					
						
							|  |  |  | 	c.rwc = rwc | 
					
						
							|  |  |  | 	br := bufio.NewReader(rwc) | 
					
						
							|  |  |  | 	bw := bufio.NewWriter(rwc) | 
					
						
							|  |  |  | 	c.buf = bufio.NewReadWriter(br, bw) | 
					
						
							|  |  |  | 	return c, nil | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-16 10:15:39 -07:00
										 |  |  | // wrapper around io.ReaderCloser which on first read, sends an | 
					
						
							|  |  |  | // HTTP/1.1 100 Continue header | 
					
						
							|  |  |  | type expectContinueReader struct { | 
					
						
							|  |  |  | 	conn       *Conn | 
					
						
							|  |  |  | 	readCloser io.ReadCloser | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (ecr *expectContinueReader) Read(p []byte) (n int, err os.Error) { | 
					
						
							|  |  |  | 	if !ecr.conn.wroteContinue && !ecr.conn.hijacked { | 
					
						
							|  |  |  | 		ecr.conn.wroteContinue = true | 
					
						
							|  |  |  | 		if ecr.conn.Req.ProtoAtLeast(1, 1) { | 
					
						
							|  |  |  | 			io.WriteString(ecr.conn.buf, "HTTP/1.1 100 Continue\r\n\r\n") | 
					
						
							|  |  |  | 			ecr.conn.buf.Flush() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return ecr.readCloser.Read(p) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (ecr *expectContinueReader) Close() os.Error { | 
					
						
							|  |  |  | 	return ecr.readCloser.Close() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | // Read next request from connection. | 
					
						
							| 
									
										
										
										
											2009-04-17 00:08:24 -07:00
										 |  |  | func (c *Conn) readRequest() (req *Request, err os.Error) { | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	if c.hijacked { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		return nil, ErrHijacked | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-05-08 11:52:39 -07:00
										 |  |  | 	if req, err = ReadRequest(c.buf.Reader); err != nil { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Reset per-request connection state. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.header = make(map[string]string) | 
					
						
							|  |  |  | 	c.wroteHeader = false | 
					
						
							| 
									
										
										
										
											2010-06-16 10:15:39 -07:00
										 |  |  | 	c.wroteContinue = false | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.Req = req | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-16 10:15:39 -07:00
										 |  |  | 	// Expect 100 Continue support | 
					
						
							|  |  |  | 	if req.expectsContinue() { | 
					
						
							|  |  |  | 		// Wrap the Body reader with one that replies on the connection | 
					
						
							|  |  |  | 		req.Body = &expectContinueReader{readCloser: req.Body, conn: c} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	// Default output is HTML encoded in UTF-8. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.SetHeader("Content-Type", "text/html; charset=utf-8") | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if req.ProtoAtLeast(1, 1) { | 
					
						
							|  |  |  | 		// HTTP/1.1 or greater: use chunked transfer encoding | 
					
						
							|  |  |  | 		// to avoid closing the connection at EOF. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		c.chunking = true | 
					
						
							|  |  |  | 		c.SetHeader("Transfer-Encoding", "chunked") | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		// HTTP version < 1.1: cannot do chunked transfer | 
					
						
							|  |  |  | 		// encoding, so signal EOF by closing connection. | 
					
						
							|  |  |  | 		// Could avoid closing the connection if there is | 
					
						
							|  |  |  | 		// a Content-Length: header in the response, | 
					
						
							|  |  |  | 		// but everyone who expects persistent connections | 
					
						
							|  |  |  | 		// does HTTP/1.1 now. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		c.closeAfterReply = true | 
					
						
							|  |  |  | 		c.chunking = false | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	return req, nil | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // SetHeader sets a header line in the eventual reply. | 
					
						
							|  |  |  | // For example, SetHeader("Content-Type", "text/html; charset=utf-8") | 
					
						
							|  |  |  | // will result in the header line | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //	Content-Type: text/html; charset=utf-8 | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // being sent.  UTF-8 encoded HTML is the default setting for | 
					
						
							|  |  |  | // Content-Type in this library, so users need not make that | 
					
						
							|  |  |  | // particular call.  Calls to SetHeader after WriteHeader (or Write) | 
					
						
							|  |  |  | // are ignored. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | func (c *Conn) SetHeader(hdr, val string) { c.header[CanonicalHeaderKey(hdr)] = val } | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // WriteHeader sends an HTTP response header with status code. | 
					
						
							|  |  |  | // If WriteHeader is not called explicitly, the first call to Write | 
					
						
							|  |  |  | // will trigger an implicit WriteHeader(http.StatusOK). | 
					
						
							|  |  |  | // Thus explicit calls to WriteHeader are mainly used to | 
					
						
							|  |  |  | // send error codes. | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | func (c *Conn) WriteHeader(code int) { | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	if c.hijacked { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		log.Stderr("http: Conn.WriteHeader on hijacked connection") | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	if c.wroteHeader { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		log.Stderr("http: multiple Conn.WriteHeader calls") | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.wroteHeader = true | 
					
						
							|  |  |  | 	c.status = code | 
					
						
							| 
									
										
										
										
											2010-06-03 16:09:37 -07:00
										 |  |  | 	if code == StatusNotModified { | 
					
						
							|  |  |  | 		// Must not have body. | 
					
						
							|  |  |  | 		c.header["Content-Type"] = "", false | 
					
						
							|  |  |  | 		c.header["Transfer-Encoding"] = "", false | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.written = 0 | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	if !c.Req.ProtoAtLeast(1, 0) { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	proto := "HTTP/1.0" | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	if c.Req.ProtoAtLeast(1, 1) { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		proto = "HTTP/1.1" | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	codestring := strconv.Itoa(code) | 
					
						
							|  |  |  | 	text, ok := statusText[code] | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	if !ok { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		text = "status code " + codestring | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	io.WriteString(c.buf, proto+" "+codestring+" "+text+"\r\n") | 
					
						
							| 
									
										
										
										
											2009-10-06 19:41:51 -07:00
										 |  |  | 	for k, v := range c.header { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		io.WriteString(c.buf, k+": "+v+"\r\n") | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	io.WriteString(c.buf, "\r\n") | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // Write writes the data to the connection as part of an HTTP reply. | 
					
						
							|  |  |  | // If WriteHeader has not yet been called, Write calls WriteHeader(http.StatusOK) | 
					
						
							|  |  |  | // before writing the data. | 
					
						
							| 
									
										
										
										
											2009-04-17 00:08:24 -07:00
										 |  |  | func (c *Conn) Write(data []byte) (n int, err os.Error) { | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	if c.hijacked { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		log.Stderr("http: Conn.Write on hijacked connection") | 
					
						
							|  |  |  | 		return 0, ErrHijacked | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if !c.wroteHeader { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		c.WriteHeader(StatusOK) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if len(data) == 0 { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		return 0, nil | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-03 16:09:37 -07:00
										 |  |  | 	if c.status == StatusNotModified { | 
					
						
							|  |  |  | 		// Must not have body. | 
					
						
							|  |  |  | 		return 0, ErrBodyNotAllowed | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.written += int64(len(data)) // ignoring errors, for errorKludge | 
					
						
							| 
									
										
										
										
											2009-06-08 14:15:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	// TODO(rsc): if chunking happened after the buffering, | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	// then there would be fewer chunk headers. | 
					
						
							|  |  |  | 	// On the other hand, it would make hijacking more difficult. | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	if c.chunking { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		fmt.Fprintf(c.buf, "%x\r\n", len(data)) // TODO(rsc): use strconv not fmt | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	n, err = c.buf.Write(data) | 
					
						
							| 
									
										
										
										
											2009-04-27 00:38:04 -07:00
										 |  |  | 	if err == nil && c.chunking { | 
					
						
							|  |  |  | 		if n != len(data) { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 			err = io.ErrShortWrite | 
					
						
							| 
									
										
										
										
											2009-04-27 00:38:04 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if err == nil { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 			io.WriteString(c.buf, "\r\n") | 
					
						
							| 
									
										
										
										
											2009-04-27 00:38:04 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	return n, err | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-08 14:15:13 -07:00
										 |  |  | // If this is an error reply (4xx or 5xx) | 
					
						
							|  |  |  | // and the handler wrote some data explaining the error, | 
					
						
							|  |  |  | // some browsers (i.e., Chrome, Internet Explorer) | 
					
						
							|  |  |  | // will show their own error instead unless the error is | 
					
						
							|  |  |  | // long enough.  The minimum lengths used in those | 
					
						
							|  |  |  | // browsers are in the 256-512 range. | 
					
						
							|  |  |  | // Pad to 1024 bytes. | 
					
						
							|  |  |  | func errorKludge(c *Conn, req *Request) { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	const min = 1024 | 
					
						
							| 
									
										
										
										
											2009-06-08 14:15:13 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Is this an error? | 
					
						
							| 
									
										
										
										
											2009-10-06 19:41:51 -07:00
										 |  |  | 	if kind := c.status / 100; kind != 4 && kind != 5 { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2009-06-08 14:15:13 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Did the handler supply any info?  Enough? | 
					
						
							|  |  |  | 	if c.written == 0 || c.written >= min { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2009-06-08 14:15:13 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Is it a broken browser? | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	var msg string | 
					
						
							| 
									
										
										
										
											2009-06-08 14:15:13 -07:00
										 |  |  | 	switch agent := req.UserAgent; { | 
					
						
							|  |  |  | 	case strings.Index(agent, "MSIE") >= 0: | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		msg = "Internet Explorer" | 
					
						
							| 
									
										
										
										
											2009-06-08 14:15:13 -07:00
										 |  |  | 	case strings.Index(agent, "Chrome/") >= 0: | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		msg = "Chrome" | 
					
						
							| 
									
										
										
										
											2009-06-08 14:15:13 -07:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		return | 
					
						
							| 
									
										
										
										
											2009-06-08 14:15:13 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	msg += " would ignore this error page if this text weren't here.\n" | 
					
						
							| 
									
										
										
										
											2009-08-24 17:31:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Is it text?  ("Content-Type" is always in the map) | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	baseType := strings.Split(c.header["Content-Type"], ";", 2)[0] | 
					
						
							| 
									
										
										
										
											2009-08-24 17:31:35 -07:00
										 |  |  | 	switch baseType { | 
					
						
							|  |  |  | 	case "text/html": | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		io.WriteString(c, "<!-- ") | 
					
						
							| 
									
										
										
										
											2009-08-24 17:31:35 -07:00
										 |  |  | 		for c.written < min { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 			io.WriteString(c, msg) | 
					
						
							| 
									
										
										
										
											2009-08-24 17:31:35 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		io.WriteString(c, " -->") | 
					
						
							| 
									
										
										
										
											2009-08-24 17:31:35 -07:00
										 |  |  | 	case "text/plain": | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		io.WriteString(c, "\n") | 
					
						
							| 
									
										
										
										
											2009-08-24 17:31:35 -07:00
										 |  |  | 		for c.written < min { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 			io.WriteString(c, msg) | 
					
						
							| 
									
										
										
										
											2009-08-24 17:31:35 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-06-08 14:15:13 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 18:06:47 -08:00
										 |  |  | func (c *Conn) finishRequest() { | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	if !c.wroteHeader { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		c.WriteHeader(StatusOK) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	errorKludge(c, c.Req) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	if c.chunking { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		io.WriteString(c.buf, "0\r\n") | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 		// trailer key/value pairs, followed by blank line | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		io.WriteString(c.buf, "\r\n") | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.buf.Flush() | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 18:06:47 -08:00
										 |  |  | // Flush sends any buffered data to the client. | 
					
						
							|  |  |  | func (c *Conn) Flush() { | 
					
						
							|  |  |  | 	if !c.wroteHeader { | 
					
						
							|  |  |  | 		c.WriteHeader(StatusOK) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.buf.Flush() | 
					
						
							| 
									
										
										
										
											2009-11-13 18:06:47 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | // Close the connection. | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | func (c *Conn) close() { | 
					
						
							|  |  |  | 	if c.buf != nil { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		c.buf.Flush() | 
					
						
							|  |  |  | 		c.buf = nil | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | 	if c.rwc != nil { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		c.rwc.Close() | 
					
						
							|  |  |  | 		c.rwc = nil | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Serve a new connection. | 
					
						
							|  |  |  | func (c *Conn) serve() { | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		req, err := c.readRequest() | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 			break | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 		// HTTP cannot have multiple simultaneous active requests. | 
					
						
							|  |  |  | 		// Until the server replies to this request, it can't read another, | 
					
						
							| 
									
										
										
										
											2009-04-07 00:40:07 -07:00
										 |  |  | 		// so we might as well run the handler in this goroutine. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		c.handler.ServeHTTP(c, req) | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 		if c.hijacked { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 			return | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		c.finishRequest() | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 		if c.closeAfterReply { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 			break | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.close() | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // Hijack lets the caller take over the connection. | 
					
						
							|  |  |  | // After a call to c.Hijack(), the HTTP server library | 
					
						
							|  |  |  | // will not do anything else with the connection. | 
					
						
							|  |  |  | // It becomes the caller's responsibility to manage | 
					
						
							|  |  |  | // and close the connection. | 
					
						
							| 
									
										
										
										
											2009-05-08 11:52:39 -07:00
										 |  |  | func (c *Conn) Hijack() (rwc io.ReadWriteCloser, buf *bufio.ReadWriter, err os.Error) { | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	if c.hijacked { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		return nil, nil, ErrHijacked | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.hijacked = true | 
					
						
							|  |  |  | 	rwc = c.rwc | 
					
						
							|  |  |  | 	buf = c.buf | 
					
						
							|  |  |  | 	c.rwc = nil | 
					
						
							|  |  |  | 	c.buf = nil | 
					
						
							|  |  |  | 	return | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // The HandlerFunc type is an adapter to allow the use of | 
					
						
							|  |  |  | // ordinary functions as HTTP handlers.  If f is a function | 
					
						
							|  |  |  | // with the appropriate signature, HandlerFunc(f) is a | 
					
						
							|  |  |  | // Handler object that calls f. | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | type HandlerFunc func(*Conn, *Request) | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | // ServeHTTP calls f(c, req). | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 	f(c, req) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Helper handlers | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-20 10:22:09 +11:00
										 |  |  | // Error replies to the request with the specified error message and HTTP code. | 
					
						
							|  |  |  | func Error(c *Conn, error string, code int) { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.SetHeader("Content-Type", "text/plain; charset=utf-8") | 
					
						
							| 
									
										
										
										
											2010-03-20 10:22:09 +11:00
										 |  |  | 	c.WriteHeader(code) | 
					
						
							|  |  |  | 	fmt.Fprintln(c, error) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-20 10:22:09 +11:00
										 |  |  | // NotFound replies to the request with an HTTP 404 not found error. | 
					
						
							|  |  |  | func NotFound(c *Conn, req *Request) { Error(c, "404 page not found", StatusNotFound) } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // NotFoundHandler returns a simple request handler | 
					
						
							|  |  |  | // that replies to each request with a ``404 page not found'' reply. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | func NotFoundHandler() Handler { return HandlerFunc(NotFound) } | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:31:31 -07:00
										 |  |  | // Redirect replies to the request with a redirect to url, | 
					
						
							|  |  |  | // which may be a path relative to the request path. | 
					
						
							| 
									
										
										
										
											2009-05-12 15:41:19 -07:00
										 |  |  | func Redirect(c *Conn, url string, code int) { | 
					
						
							|  |  |  | 	// RFC2616 recommends that a short note "SHOULD" be included in the | 
					
						
							|  |  |  | 	// response because older user agents may not understand 301/307. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	note := "<a href=\"%v\">" + statusText[code] + "</a>.\n" | 
					
						
							| 
									
										
										
										
											2009-05-12 15:41:19 -07:00
										 |  |  | 	if c.Req.Method == "POST" { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		note = "" | 
					
						
							| 
									
										
										
										
											2009-05-12 15:41:19 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	u, err := ParseURL(url) | 
					
						
							| 
									
										
										
										
											2009-04-15 18:40:55 -07:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		goto finish | 
					
						
							| 
									
										
										
										
											2009-04-15 18:40:55 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// If url was relative, make absolute by | 
					
						
							|  |  |  | 	// combining with request path. | 
					
						
							|  |  |  | 	// The browser would probably do this for us, | 
					
						
							|  |  |  | 	// but doing it ourselves is more reliable. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// NOTE(rsc): RFC 2616 says that the Location | 
					
						
							|  |  |  | 	// line must be an absolute URI, like | 
					
						
							|  |  |  | 	// "http://www.google.com/redirect/", | 
					
						
							|  |  |  | 	// not a path like "/redirect/". | 
					
						
							|  |  |  | 	// Unfortunately, we don't know what to | 
					
						
							|  |  |  | 	// put in the host name section to get the | 
					
						
							|  |  |  | 	// client to connect to us again, so we can't | 
					
						
							|  |  |  | 	// know the right absolute URI to send back. | 
					
						
							|  |  |  | 	// Because of this problem, no one pays attention | 
					
						
							|  |  |  | 	// to the RFC; they all send back just a new path. | 
					
						
							|  |  |  | 	// So do we. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	oldpath := c.Req.URL.Path | 
					
						
							|  |  |  | 	if oldpath == "" { // should not happen, but avoid a crash if it does | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		oldpath = "/" | 
					
						
							| 
									
										
										
										
											2009-04-15 18:40:55 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if u.Scheme == "" { | 
					
						
							|  |  |  | 		// no leading http://server | 
					
						
							|  |  |  | 		if url == "" || url[0] != '/' { | 
					
						
							|  |  |  | 			// make relative path absolute | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 			olddir, _ := path.Split(oldpath) | 
					
						
							|  |  |  | 			url = olddir + url | 
					
						
							| 
									
										
										
										
											2009-04-15 18:40:55 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// clean up but preserve trailing slash | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		trailing := url[len(url)-1] == '/' | 
					
						
							|  |  |  | 		url = path.Clean(url) | 
					
						
							| 
									
										
										
										
											2009-10-06 19:41:51 -07:00
										 |  |  | 		if trailing && url[len(url)-1] != '/' { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 			url += "/" | 
					
						
							| 
									
										
										
										
											2009-04-15 18:40:55 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-12 15:41:19 -07:00
										 |  |  | finish: | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	c.SetHeader("Location", url) | 
					
						
							|  |  |  | 	c.WriteHeader(code) | 
					
						
							|  |  |  | 	fmt.Fprintf(c, note, url) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:31:31 -07:00
										 |  |  | // Redirect to a fixed URL | 
					
						
							| 
									
										
										
										
											2009-05-12 15:41:19 -07:00
										 |  |  | type redirectHandler struct { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	url  string | 
					
						
							|  |  |  | 	code int | 
					
						
							| 
									
										
										
										
											2009-05-12 15:41:19 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-06 19:41:51 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-12 15:41:19 -07:00
										 |  |  | func (rh *redirectHandler) ServeHTTP(c *Conn, req *Request) { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 	Redirect(c, rh.url, rh.code) | 
					
						
							| 
									
										
										
										
											2009-04-14 20:31:31 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // RedirectHandler returns a request handler that redirects | 
					
						
							| 
									
										
										
										
											2009-05-12 15:41:19 -07:00
										 |  |  | // each request it receives to the given url using the given | 
					
						
							|  |  |  | // status code. | 
					
						
							|  |  |  | func RedirectHandler(url string, code int) Handler { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 	return &redirectHandler{url, code} | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // ServeMux is an HTTP request multiplexer. | 
					
						
							|  |  |  | // It matches the URL of each incoming request against a list of registered | 
					
						
							|  |  |  | // patterns and calls the handler for the pattern that | 
					
						
							|  |  |  | // most closely matches the URL. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // Patterns named fixed paths, like "/favicon.ico", | 
					
						
							|  |  |  | // or subtrees, like "/images/" (note the trailing slash). | 
					
						
							|  |  |  | // Patterns must begin with /. | 
					
						
							|  |  |  | // Longer patterns take precedence over shorter ones, so that | 
					
						
							|  |  |  | // if there are handlers registered for both "/images/" | 
					
						
							|  |  |  | // and "/images/thumbnails/", the latter handler will be | 
					
						
							|  |  |  | // called for paths beginning "/images/thumbnails/" and the | 
					
						
							|  |  |  | // former will receiver requests for any other paths in the | 
					
						
							|  |  |  | // "/images/" subtree. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // In the future, the pattern syntax may be relaxed to allow | 
					
						
							|  |  |  | // an optional host-name at the beginning of the pattern, | 
					
						
							|  |  |  | // so that a handler might register for the two patterns | 
					
						
							|  |  |  | // "/codesearch" and "codesearch.google.com/" | 
					
						
							|  |  |  | // without taking over requests for http://www.google.com/. | 
					
						
							| 
									
										
										
										
											2009-04-07 00:40:07 -07:00
										 |  |  | // | 
					
						
							|  |  |  | // ServeMux also takes care of sanitizing the URL request path, | 
					
						
							|  |  |  | // redirecting any request containing . or .. elements to an | 
					
						
							|  |  |  | // equivalent .- and ..-free URL. | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | type ServeMux struct { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	m map[string]Handler | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // NewServeMux allocates and returns a new ServeMux. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | func NewServeMux() *ServeMux { return &ServeMux{make(map[string]Handler)} } | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // DefaultServeMux is the default ServeMux used by Serve. | 
					
						
							| 
									
										
										
										
											2009-10-06 19:41:51 -07:00
										 |  |  | var DefaultServeMux = NewServeMux() | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Does path match pattern? | 
					
						
							|  |  |  | func pathMatch(pattern, path string) bool { | 
					
						
							|  |  |  | 	if len(pattern) == 0 { | 
					
						
							|  |  |  | 		// should not happen | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		return false | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	n := len(pattern) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	if pattern[n-1] != '/' { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		return pattern == path | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	return len(path) >= n && path[0:n] == pattern | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-07 00:40:07 -07:00
										 |  |  | // Return the canonical path for p, eliminating . and .. elements. | 
					
						
							|  |  |  | func cleanPath(p string) string { | 
					
						
							|  |  |  | 	if p == "" { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		return "/" | 
					
						
							| 
									
										
										
										
											2009-04-07 00:40:07 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if p[0] != '/' { | 
					
						
							| 
									
										
										
										
											2009-11-09 21:23:52 -08:00
										 |  |  | 		p = "/" + p | 
					
						
							| 
									
										
										
										
											2009-04-07 00:40:07 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	np := path.Clean(p) | 
					
						
							| 
									
										
										
										
											2009-04-07 00:40:07 -07:00
										 |  |  | 	// path.Clean removes trailing slash except for root; | 
					
						
							|  |  |  | 	// put the trailing slash back if necessary. | 
					
						
							|  |  |  | 	if p[len(p)-1] == '/' && np != "/" { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		np += "/" | 
					
						
							| 
									
										
										
										
											2009-04-07 00:40:07 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	return np | 
					
						
							| 
									
										
										
										
											2009-04-07 00:40:07 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // ServeHTTP dispatches the request to the handler whose | 
					
						
							|  |  |  | // pattern most closely matches the request URL. | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | func (mux *ServeMux) ServeHTTP(c *Conn, req *Request) { | 
					
						
							| 
									
										
										
										
											2009-04-07 00:40:07 -07:00
										 |  |  | 	// Clean path to canonical form and redirect. | 
					
						
							| 
									
										
										
										
											2009-11-08 21:46:20 -08:00
										 |  |  | 	if p := cleanPath(req.URL.Path); p != req.URL.Path { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		c.SetHeader("Location", p) | 
					
						
							|  |  |  | 		c.WriteHeader(StatusMovedPermanently) | 
					
						
							|  |  |  | 		return | 
					
						
							| 
									
										
										
										
											2009-04-07 00:40:07 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	// Most-specific (longest) pattern wins. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	var h Handler | 
					
						
							|  |  |  | 	var n = 0 | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	for k, v := range mux.m { | 
					
						
							| 
									
										
										
										
											2009-11-08 21:46:20 -08:00
										 |  |  | 		if !pathMatch(k, req.URL.Path) { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if h == nil || len(k) > n { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 			n = len(k) | 
					
						
							|  |  |  | 			h = v | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if h == nil { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		h = NotFoundHandler() | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	h.ServeHTTP(c, req) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // Handle registers the handler for the given pattern. | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | func (mux *ServeMux) Handle(pattern string, handler Handler) { | 
					
						
							|  |  |  | 	if pattern == "" || pattern[0] != '/' { | 
					
						
							| 
									
										
										
										
											2010-03-24 16:46:53 -07:00
										 |  |  | 		panic("http: invalid pattern " + pattern) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	mux.m[pattern] = handler | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Helpful behavior: | 
					
						
							| 
									
										
										
										
											2009-05-12 15:41:19 -07:00
										 |  |  | 	// If pattern is /tree/, insert permanent redirect for /tree. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	n := len(pattern) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	if n > 0 && pattern[n-1] == '/' { | 
					
						
							| 
									
										
										
										
											2009-11-09 21:23:52 -08:00
										 |  |  | 		mux.m[pattern[0:n-1]] = RedirectHandler(pattern, StatusMovedPermanently) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-29 10:02:37 +11:00
										 |  |  | // HandleFunc registers the handler function for the given pattern. | 
					
						
							|  |  |  | func (mux *ServeMux) HandleFunc(pattern string, handler func(*Conn, *Request)) { | 
					
						
							|  |  |  | 	mux.Handle(pattern, HandlerFunc(handler)) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // Handle registers the handler for the given pattern | 
					
						
							|  |  |  | // in the DefaultServeMux. | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) } | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-03-29 10:02:37 +11:00
										 |  |  | // HandleFunc registers the handler function for the given pattern | 
					
						
							|  |  |  | // in the DefaultServeMux. | 
					
						
							|  |  |  | func HandleFunc(pattern string, handler func(*Conn, *Request)) { | 
					
						
							|  |  |  | 	DefaultServeMux.HandleFunc(pattern, handler) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // Serve accepts incoming HTTP connections on the listener l, | 
					
						
							|  |  |  | // creating a new service thread for each.  The service threads | 
					
						
							|  |  |  | // read requests and then call handler to reply to them. | 
					
						
							|  |  |  | // Handler is typically nil, in which case the DefaultServeMux is used. | 
					
						
							| 
									
										
										
										
											2009-04-17 00:08:24 -07:00
										 |  |  | func Serve(l net.Listener, handler Handler) os.Error { | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	if handler == nil { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		handler = DefaultServeMux | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		rw, e := l.Accept() | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 		if e != nil { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 			return e | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		c, err := newConn(rw, handler) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 			continue | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 		go c.serve() | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	panic("not reached") | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // ListenAndServe listens on the TCP network address addr | 
					
						
							|  |  |  | // and then calls Serve with handler to handle requests | 
					
						
							|  |  |  | // on incoming connections.  Handler is typically nil, | 
					
						
							|  |  |  | // in which case the DefaultServeMux is used. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // A trivial example server is: | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //	package main | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //	import ( | 
					
						
							| 
									
										
										
										
											2010-04-05 22:55:05 -07:00
										 |  |  | //		"http" | 
					
						
							|  |  |  | //		"io" | 
					
						
							|  |  |  | //		"log" | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | //	) | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //	// hello world, the web server | 
					
						
							|  |  |  | //	func HelloServer(c *http.Conn, req *http.Request) { | 
					
						
							| 
									
										
										
										
											2010-04-05 22:55:05 -07:00
										 |  |  | //		io.WriteString(c, "hello, world!\n") | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | //	} | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //	func main() { | 
					
						
							| 
									
										
										
										
											2010-04-05 22:55:05 -07:00
										 |  |  | //		http.HandleFunc("/hello", HelloServer) | 
					
						
							|  |  |  | //		err := http.ListenAndServe(":12345", nil) | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | //		if err != nil { | 
					
						
							| 
									
										
										
										
											2010-04-05 22:55:05 -07:00
										 |  |  | //			log.Exit("ListenAndServe: ", err.String()) | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | //		} | 
					
						
							|  |  |  | //	} | 
					
						
							| 
									
										
										
										
											2009-04-17 00:08:24 -07:00
										 |  |  | func ListenAndServe(addr string, handler Handler) os.Error { | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	l, e := net.Listen("tcp", addr) | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	if e != nil { | 
					
						
							| 
									
										
										
										
											2009-11-09 12:07:39 -08:00
										 |  |  | 		return e | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-15 15:35:38 -08:00
										 |  |  | 	e = Serve(l, handler) | 
					
						
							|  |  |  | 	l.Close() | 
					
						
							|  |  |  | 	return e | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | } |