// 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.

// HTTP server.  See RFC 2616.

// TODO(rsc):
//	logging
//	cgi support
//	post support

package http

import (
	"bufio";
	"fmt";
	"io";
	"log";
	"net";
	"os";
	"path";
	"strconv";
	"strings";
)

// Errors introduced by the HTTP server.
var (
	ErrWriteAfterFlush	= os.NewError("Conn.Write called after Flush");
	ErrHijacked		= os.NewError("Conn has been hijacked");
)

// Objects implementing the Handler interface can be
// registered to serve a particular path or subtree
// in the HTTP server.
type Handler interface {
	ServeHTTP(*Conn, *Request);
}

// A Conn represents the server side of a single active HTTP connection.
type Conn struct {
	RemoteAddr	string;		// network address of remote side
	Req		*Request;	// current HTTP request

	rwc		io.ReadWriteCloser;	// i/o connection
	buf		*bufio.ReadWriter;	// buffered rwc
	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
	written		int64;			// number of bytes written in body
	status		int;			// status code passed to WriteHeader
}

// Create new connection from rwc.
func newConn(rwc net.Conn, handler Handler) (c *Conn, err os.Error) {
	c = new(Conn);
	if a := rwc.RemoteAddr(); a != nil {
		c.RemoteAddr = a.String()
	}
	c.handler = handler;
	c.rwc = rwc;
	br := bufio.NewReader(rwc);
	bw := bufio.NewWriter(rwc);
	c.buf = bufio.NewReadWriter(br, bw);
	return c, nil;
}

// Read next request from connection.
func (c *Conn) readRequest() (req *Request, err os.Error) {
	if c.hijacked {
		return nil, ErrHijacked
	}
	if req, err = ReadRequest(c.buf.Reader); err != nil {
		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.
		c.closeAfterReply = true;
		c.chunking = false;
	}

	return req, nil;
}

// 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.
func (c *Conn) SetHeader(hdr, val string)	{ c.header[CanonicalHeaderKey(hdr)] = val }

// 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.
func (c *Conn) WriteHeader(code int) {
	if c.hijacked {
		log.Stderr("http: Conn.WriteHeader on hijacked connection");
		return;
	}
	if c.wroteHeader {
		log.Stderr("http: multiple Conn.WriteHeader calls");
		return;
	}
	c.wroteHeader = true;
	c.status = code;
	c.written = 0;
	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
	}
	io.WriteString(c.buf, proto+" "+codestring+" "+text+"\r\n");
	for k, v := range c.header {
		io.WriteString(c.buf, k+": "+v+"\r\n")
	}
	io.WriteString(c.buf, "\r\n");
}

// 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.
func (c *Conn) Write(data []byte) (n int, err os.Error) {
	if c.hijacked {
		log.Stderr("http: Conn.Write on hijacked connection");
		return 0, ErrHijacked;
	}
	if !c.wroteHeader {
		c.WriteHeader(StatusOK)
	}
	if len(data) == 0 {
		return 0, nil
	}

	c.written += int64(len(data));	// ignoring errors, for errorKludge

	// TODO(rsc): if chunking happened after the buffering,
	// then there would be fewer chunk headers.
	// On the other hand, it would make hijacking more difficult.
	if c.chunking {
		fmt.Fprintf(c.buf, "%x\r\n", len(data))	// TODO(rsc): use strconv not fmt
	}
	n, err = c.buf.Write(data);
	if err == nil && c.chunking {
		if n != len(data) {
			err = io.ErrShortWrite
		}
		if err == nil {
			io.WriteString(c.buf, "\r\n")
		}
	}

	return n, err;
}

// 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) {
	const min = 1024;

	// Is this an error?
	if kind := c.status / 100; kind != 4 && kind != 5 {
		return
	}

	// Did the handler supply any info?  Enough?
	if c.written == 0 || c.written >= min {
		return
	}

	// Is it a broken browser?
	var msg string;
	switch agent := req.UserAgent; {
	case strings.Index(agent, "MSIE") >= 0:
		msg = "Internet Explorer"
	case strings.Index(agent, "Chrome/") >= 0:
		msg = "Chrome"
	default:
		return
	}
	msg += " would ignore this error page if this text weren't here.\n";

	// Is it text?  ("Content-Type" is always in the map)
	baseType := strings.Split(c.header["Content-Type"], ";", 2)[0];
	switch baseType {
	case "text/html":
		io.WriteString(c, "<!-- ");
		for c.written < min {
			io.WriteString(c, msg)
		}
		io.WriteString(c, " -->");
	case "text/plain":
		io.WriteString(c, "\n");
		for c.written < min {
			io.WriteString(c, msg)
		}
	}
}

func (c *Conn) flush() {
	if !c.wroteHeader {
		c.WriteHeader(StatusOK)
	}
	errorKludge(c, c.Req);
	if c.chunking {
		io.WriteString(c.buf, "0\r\n");
		// trailer key/value pairs, followed by blank line
		io.WriteString(c.buf, "\r\n");
	}
	c.buf.Flush();
}

// Close the connection.
func (c *Conn) close() {
	if c.buf != nil {
		c.buf.Flush();
		c.buf = nil;
	}
	if c.rwc != nil {
		c.rwc.Close();
		c.rwc = nil;
	}
}

// Serve a new connection.
func (c *Conn) serve() {
	for {
		req, err := c.readRequest();
		if err != nil {
			break
		}
		// HTTP cannot have multiple simultaneous active requests.
		// Until the server replies to this request, it can't read another,
		// so we might as well run the handler in this goroutine.
		c.handler.ServeHTTP(c, req);
		if c.hijacked {
			return
		}
		c.flush();
		if c.closeAfterReply {
			break
		}
	}
	c.close();
}

// 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.
func (c *Conn) Hijack() (rwc io.ReadWriteCloser, buf *bufio.ReadWriter, err os.Error) {
	if c.hijacked {
		return nil, nil, ErrHijacked
	}
	c.hijacked = true;
	rwc = c.rwc;
	buf = c.buf;
	c.rwc = nil;
	c.buf = nil;
	return;
}

// 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.
type HandlerFunc func(*Conn, *Request)

// ServeHTTP calls f(c, req).
func (f HandlerFunc) ServeHTTP(c *Conn, req *Request) {
	f(c, req)
}

// Helper handlers

// NotFound replies to the request with an HTTP 404 not found error.
func NotFound(c *Conn, req *Request) {
	c.SetHeader("Content-Type", "text/plain; charset=utf-8");
	c.WriteHeader(StatusNotFound);
	io.WriteString(c, "404 page not found\n");
}

// NotFoundHandler returns a simple request handler
// that replies to each request with a ``404 page not found'' reply.
func NotFoundHandler() Handler	{ return HandlerFunc(NotFound) }

// 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, code int) {
	// RFC2616 recommends that a short note "SHOULD" be included in the
	// response because older user agents may not understand 301/307.
	note := "<a href=\"%v\">" + statusText[code] + "</a>.\n";
	if c.Req.Method == "POST" {
		note = ""
	}

	u, err := ParseURL(url);
	if err != nil {
		goto finish
	}

	// 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, _ := 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 += "/"
		}
	}

finish:
	c.SetHeader("Location", url);
	c.WriteHeader(code);
	fmt.Fprintf(c, note, url);
}

// Redirect to a fixed URL
type redirectHandler struct {
	url	string;
	code	int;
}

func (rh *redirectHandler) ServeHTTP(c *Conn, req *Request) {
	Redirect(c, rh.url, rh.code)
}

// RedirectHandler returns a request handler that redirects
// each request it receives to the given url using the given
// status code.
func RedirectHandler(url string, code int) Handler {
	return &redirectHandler{url, code}
}

// 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/.
//
// ServeMux also takes care of sanitizing the URL request path,
// redirecting any request containing . or .. elements to an
// equivalent .- and ..-free URL.
type ServeMux struct {
	m map[string]Handler;
}

// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux	{ return &ServeMux{make(map[string]Handler)} }

// DefaultServeMux is the default ServeMux used by Serve.
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
	}
	return len(path) >= n && path[0:n] == pattern;
}

// 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;
}

// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(c *Conn, req *Request) {
	// 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;
	}

	// 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 {
		h = NotFoundHandler()
	}
	h.ServeHTTP(c, req);
}

// Handle registers the handler for the given pattern.
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 permanent redirect for /tree.
	n := len(pattern);
	if n > 0 && pattern[n-1] == '/' {
		mux.m[pattern[0:n-1]] = RedirectHandler(pattern, StatusMovedPermanently)
	}
}

// Handle registers the handler for the given pattern
// in the DefaultServeMux.
func Handle(pattern string, handler Handler)	{ DefaultServeMux.Handle(pattern, handler) }

// 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.
func Serve(l net.Listener, handler Handler) os.Error {
	if handler == nil {
		handler = DefaultServeMux
	}
	for {
		rw, e := l.Accept();
		if e != nil {
			return e
		}
		c, err := newConn(rw, handler);
		if err != nil {
			continue
		}
		go c.serve();
	}
	panic("not reached");
}

// 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())
//		}
//	}
func ListenAndServe(addr string, handler Handler) os.Error {
	l, e := net.Listen("tcp", addr);
	if e != nil {
		return e
	}
	e = Serve(l, handler);
	l.Close();
	return e;
}
