| 
									
										
										
										
											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-02-02 18:01:32 -08:00
										 |  |  | 	"bufio"; | 
					
						
							|  |  |  | 	"fmt"; | 
					
						
							|  |  |  | 	"http"; | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	"io"; | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	"log"; | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	"net"; | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	"os"; | 
					
						
							| 
									
										
										
										
											2009-04-07 00:40:07 -07:00
										 |  |  | 	"path"; | 
					
						
							| 
									
										
										
										
											2008-11-17 12:34:03 -08:00
										 |  |  | 	"strconv"; | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // Errors introduced by the HTTP server. | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	ErrWriteAfterFlush = os.NewError("Conn.Write called after Flush"); | 
					
						
							|  |  |  | 	ErrHijacked = os.NewError("Conn has been hijacked"); | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | type Conn struct | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // Objects implemeting the Handler interface can be | 
					
						
							|  |  |  | // registered to serve a particular path or subtree | 
					
						
							|  |  |  | // in the HTTP server. | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | type Handler interface { | 
					
						
							|  |  |  | 	ServeHTTP(*Conn, *Request); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-02-03 14:16:22 -08:00
										 |  |  | 	RemoteAddr string;	// network address of remote side | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | 	Req *Request;		// current HTTP request | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-08 11:22:57 -07:00
										 |  |  | 	rwc io.ReadWriteCloser;	// i/o connection | 
					
						
							| 
									
										
										
										
											2009-05-08 11:52:39 -07:00
										 |  |  | 	buf *bufio.ReadWriter;	// buffered rwc | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	handler Handler;	// request handler | 
					
						
							|  |  |  | 	hijacked bool;	// connection has been hijacked by handler | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// state for the current reply | 
					
						
							|  |  |  | 	closeAfterReply bool;	// close connection after this reply | 
					
						
							|  |  |  | 	chunking bool;	// using chunked transfer encoding for reply body | 
					
						
							|  |  |  | 	wroteHeader bool;	// reply header has been written | 
					
						
							|  |  |  | 	header map[string] string;	// reply header parameters | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Create new connection from rwc. | 
					
						
							| 
									
										
										
										
											2009-05-08 11:22:57 -07:00
										 |  |  | func newConn(rwc io.ReadWriteCloser, raddr string, handler Handler) (c *Conn, err os.Error) { | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	c = new(Conn); | 
					
						
							|  |  |  | 	c.RemoteAddr = raddr; | 
					
						
							|  |  |  | 	c.handler = handler; | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | 	c.rwc = rwc; | 
					
						
							| 
									
										
										
										
											2009-05-08 11:52:39 -07:00
										 |  |  | 	br := bufio.NewReader(rwc); | 
					
						
							|  |  |  | 	bw := bufio.NewWriter(rwc); | 
					
						
							|  |  |  | 	c.buf = bufio.NewReadWriter(br, bw); | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	return c, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *Conn) SetHeader(hdr, val string) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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 { | 
					
						
							|  |  |  | 		return nil, ErrHijacked | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-05-08 11:52:39 -07:00
										 |  |  | 	if req, err = ReadRequest(c.buf.Reader); err != nil { | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Reset per-request connection state. | 
					
						
							|  |  |  | 	c.header = make(map[string] string); | 
					
						
							|  |  |  | 	c.wroteHeader = false; | 
					
						
							|  |  |  | 	c.Req = req; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Default output is HTML encoded in UTF-8. | 
					
						
							|  |  |  | 	c.SetHeader("Content-Type", "text/html; charset=utf-8"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if req.ProtoAtLeast(1, 1) { | 
					
						
							|  |  |  | 		// HTTP/1.1 or greater: use chunked transfer encoding | 
					
						
							|  |  |  | 		// to avoid closing the connection at EOF. | 
					
						
							|  |  |  | 		c.chunking = true; | 
					
						
							|  |  |  | 		c.SetHeader("Transfer-Encoding", "chunked"); | 
					
						
							|  |  |  | 	} 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-02-03 14:16:22 -08:00
										 |  |  | 		c.closeAfterReply = true; | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 		c.chunking = false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return req, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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-02-02 18:01:32 -08:00
										 |  |  | func (c *Conn) SetHeader(hdr, val string) { | 
					
						
							|  |  |  | 	c.header[CanonicalHeaderKey(hdr)] = val; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							|  |  |  | 		log.Stderr("http: Conn.WriteHeader on hijacked connection"); | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	if c.wroteHeader { | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 		log.Stderr("http: multiple Conn.WriteHeader calls"); | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	c.wroteHeader = true; | 
					
						
							|  |  |  | 	if !c.Req.ProtoAtLeast(1, 0) { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	proto := "HTTP/1.0"; | 
					
						
							|  |  |  | 	if c.Req.ProtoAtLeast(1, 1) { | 
					
						
							|  |  |  | 		proto = "HTTP/1.1"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	codestring := strconv.Itoa(code); | 
					
						
							|  |  |  | 	text, ok := statusText[code]; | 
					
						
							|  |  |  | 	if !ok { | 
					
						
							|  |  |  | 		text = "status code " + codestring; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	io.WriteString(c.buf, proto + " " + codestring + " " + text + "\r\n"); | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	for k,v := range c.header { | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 		io.WriteString(c.buf, k + ": " + v + "\r\n"); | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -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 { | 
					
						
							|  |  |  | 		log.Stderr("http: Conn.Write on hijacked connection"); | 
					
						
							|  |  |  | 		return 0, ErrHijacked | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if !c.wroteHeader { | 
					
						
							|  |  |  | 		c.WriteHeader(StatusOK); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if len(data) == 0 { | 
					
						
							|  |  |  | 		return 0, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 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-02-03 14:16:22 -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-04-27 00:38:04 -07:00
										 |  |  | 	n, err = c.buf.Write(data); | 
					
						
							|  |  |  | 	if err == nil && c.chunking { | 
					
						
							|  |  |  | 		if n != len(data) { | 
					
						
							|  |  |  | 			err = bufio.ShortWrite; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err == nil { | 
					
						
							|  |  |  | 			io.WriteString(c.buf, "\r\n"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return n, err; | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | func (c *Conn) flush() { | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	if !c.wroteHeader { | 
					
						
							|  |  |  | 		c.WriteHeader(StatusOK); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if c.chunking { | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -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-02-03 14:16:22 -08:00
										 |  |  | 		io.WriteString(c.buf, "\r\n"); | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	c.buf.Flush(); | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							|  |  |  | 		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 { | 
					
						
							|  |  |  | 		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-02-02 18:01:32 -08:00
										 |  |  | 		req, err := c.readRequest(); | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											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-02-02 18:01:32 -08:00
										 |  |  | 		c.handler.ServeHTTP(c, req); | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 		if c.hijacked { | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 		c.flush(); | 
					
						
							|  |  |  | 		if c.closeAfterReply { | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	c.close(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							|  |  |  | 		return nil, nil, ErrHijacked; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	c.hijacked = true; | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | 	rwc = c.rwc; | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	buf = c.buf; | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | 	c.rwc = nil; | 
					
						
							| 
									
										
										
										
											2009-02-03 14:16:22 -08:00
										 |  |  | 	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) { | 
					
						
							|  |  |  | 	f(c, req); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Helper handlers | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:31:31 -07:00
										 |  |  | // NotFound replies to the request with an HTTP 404 not found error. | 
					
						
							|  |  |  | func NotFound(c *Conn, req *Request) { | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	c.SetHeader("Content-Type", "text/plain; charset=utf-8"); | 
					
						
							|  |  |  | 	c.WriteHeader(StatusNotFound); | 
					
						
							|  |  |  | 	io.WriteString(c, "404 page not found\n"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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. | 
					
						
							|  |  |  | func NotFoundHandler() Handler { | 
					
						
							| 
									
										
										
										
											2009-04-14 20:31:31 -07:00
										 |  |  | 	return HandlerFunc(NotFound) | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											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. | 
					
						
							|  |  |  | func Redirect(c *Conn, url string) { | 
					
						
							| 
									
										
										
										
											2009-04-15 18:40:55 -07:00
										 |  |  | 	u, err := ParseURL(url); | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		// TODO report internal error instead? | 
					
						
							|  |  |  | 		c.SetHeader("Location", url); | 
					
						
							|  |  |  | 		c.WriteHeader(StatusMovedPermanently); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 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. | 
					
						
							|  |  |  | 	oldpath := c.Req.Url.Path; | 
					
						
							|  |  |  | 	if oldpath == "" {	// should not happen, but avoid a crash if it does | 
					
						
							|  |  |  | 		oldpath = "/" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if u.Scheme == "" { | 
					
						
							|  |  |  | 		// no leading http://server | 
					
						
							|  |  |  | 		if url == "" || url[0] != '/' { | 
					
						
							|  |  |  | 			// make relative path absolute | 
					
						
							|  |  |  | 			olddir, oldfile := path.Split(oldpath); | 
					
						
							|  |  |  | 			url = olddir + url; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// clean up but preserve trailing slash | 
					
						
							|  |  |  | 		trailing := url[len(url) - 1] == '/'; | 
					
						
							|  |  |  | 		url = path.Clean(url); | 
					
						
							|  |  |  | 		if trailing && url[len(url) - 1] != '/' { | 
					
						
							|  |  |  | 			url += "/"; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:31:31 -07:00
										 |  |  | 	c.SetHeader("Location", url); | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	c.WriteHeader(StatusMovedPermanently); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-14 20:31:31 -07:00
										 |  |  | // Redirect to a fixed URL | 
					
						
							|  |  |  | type redirectHandler string | 
					
						
							|  |  |  | func (url redirectHandler) ServeHTTP(c *Conn, req *Request) { | 
					
						
							|  |  |  | 	Redirect(c, url); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // RedirectHandler returns a request handler that redirects | 
					
						
							|  |  |  | // each request it receives to the given url. | 
					
						
							|  |  |  | func RedirectHandler(url string) Handler { | 
					
						
							| 
									
										
										
										
											2009-04-14 20:31:31 -07:00
										 |  |  | 	return redirectHandler(url); | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							|  |  |  | 	m map[string] Handler | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // NewServeMux allocates and returns a new ServeMux. | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | func NewServeMux() *ServeMux { | 
					
						
							| 
									
										
										
										
											2009-03-03 08:39:12 -08:00
										 |  |  | 	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-02-02 18:01:32 -08:00
										 |  |  | var DefaultServeMux = NewServeMux(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Does path match pattern? | 
					
						
							|  |  |  | func pathMatch(pattern, path string) bool { | 
					
						
							|  |  |  | 	if len(pattern) == 0 { | 
					
						
							|  |  |  | 		// should not happen | 
					
						
							|  |  |  | 		return false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	n := len(pattern); | 
					
						
							|  |  |  | 	if pattern[n-1] != '/' { | 
					
						
							|  |  |  | 		return pattern == path | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	return len(path) >= n && path[0:n] == pattern; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-07 00:40:07 -07:00
										 |  |  | // Return the canonical path for p, eliminating . and .. elements. | 
					
						
							|  |  |  | func cleanPath(p string) string { | 
					
						
							|  |  |  | 	if p == "" { | 
					
						
							|  |  |  | 		return "/"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if p[0] != '/' { | 
					
						
							|  |  |  | 		p = "/" + p; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	np := path.Clean(p); | 
					
						
							|  |  |  | 	// path.Clean removes trailing slash except for root; | 
					
						
							|  |  |  | 	// put the trailing slash back if necessary. | 
					
						
							|  |  |  | 	if p[len(p)-1] == '/' && np != "/" { | 
					
						
							|  |  |  | 		np += "/"; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return np; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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. | 
					
						
							|  |  |  | 	if p := cleanPath(req.Url.Path); p != req.Url.Path { | 
					
						
							|  |  |  | 		c.SetHeader("Location", p); | 
					
						
							|  |  |  | 		c.WriteHeader(StatusMovedPermanently); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	// Most-specific (longest) pattern wins. | 
					
						
							|  |  |  | 	var h Handler; | 
					
						
							|  |  |  | 	var n = 0; | 
					
						
							|  |  |  | 	for k, v := range mux.m { | 
					
						
							|  |  |  | 		if !pathMatch(k, req.Url.Path) { | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if h == nil || len(k) > n { | 
					
						
							|  |  |  | 			n = len(k); | 
					
						
							|  |  |  | 			h = v; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if h == nil { | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | 		h = NotFoundHandler(); | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	h.ServeHTTP(c, req); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											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] != '/' { | 
					
						
							|  |  |  | 		panicln("http: invalid pattern", pattern); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mux.m[pattern] = handler; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Helpful behavior: | 
					
						
							|  |  |  | 	// If pattern is /tree/, insert redirect for /tree. | 
					
						
							|  |  |  | 	n := len(pattern); | 
					
						
							|  |  |  | 	if n > 0 && pattern[n-1] == '/' { | 
					
						
							|  |  |  | 		mux.m[pattern[0:n-1]] = RedirectHandler(pattern); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-11 12:51:10 -07:00
										 |  |  | // Handle registers the handler for the given pattern | 
					
						
							|  |  |  | // in the DefaultServeMux. | 
					
						
							|  |  |  | func Handle(pattern string, handler Handler) { | 
					
						
							|  |  |  | 	DefaultServeMux.Handle(pattern, handler); | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 { | 
					
						
							|  |  |  | 		handler = DefaultServeMux; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	for { | 
					
						
							| 
									
										
										
										
											2008-10-08 09:34:50 -07:00
										 |  |  | 		rw, raddr, e := l.Accept(); | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 		if e != nil { | 
					
						
							|  |  |  | 			return e | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 		c, err := newConn(rw, raddr, handler); | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			continue; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		go c.serve(); | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	panic("not reached") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 ( | 
					
						
							|  |  |  | //		"http"; | 
					
						
							|  |  |  | //		"io"; | 
					
						
							|  |  |  | //	) | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //	// hello world, the web server | 
					
						
							|  |  |  | //	func HelloServer(c *http.Conn, req *http.Request) { | 
					
						
							|  |  |  | //		io.WriteString(c, "hello, world!\n"); | 
					
						
							|  |  |  | //	} | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | //	func main() { | 
					
						
							|  |  |  | //		http.Handle("/hello", http.HandlerFunc(HelloServer)); | 
					
						
							|  |  |  | //		err := http.ListenAndServe(":12345", nil); | 
					
						
							|  |  |  | //		if err != nil { | 
					
						
							|  |  |  | //			panic("ListenAndServe: ", err.String()) | 
					
						
							|  |  |  | //		} | 
					
						
							|  |  |  | //	} | 
					
						
							| 
									
										
										
										
											2009-04-17 00:08:24 -07:00
										 |  |  | func ListenAndServe(addr string, handler Handler) os.Error { | 
					
						
							| 
									
										
										
										
											2008-10-08 09:34:50 -07:00
										 |  |  | 	l, e := net.Listen("tcp", addr); | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	if e != nil { | 
					
						
							|  |  |  | 		return e | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 	e = Serve(l, handler); | 
					
						
							| 
									
										
										
										
											2008-10-08 09:34:50 -07:00
										 |  |  | 	l.Close(); | 
					
						
							| 
									
										
										
										
											2008-09-24 15:26:55 -07:00
										 |  |  | 	return e | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-02 18:01:32 -08:00
										 |  |  | 
 |