func serveError(req *web.Request, status int, reason os.Error, header web.Header) { header.Set(web.HeaderContentType, "text/plain; charset=utf-8") w := req.Responder.Respond(status, header) io.WriteString(w, web.StatusText(status)) if reason != nil { io.WriteString(w, "\n") io.WriteString(w, reason.String()) } }
func (t *transaction) Respond(status int, header web.Header) (body io.Writer) { if t.hijacked { log.Println("twister: Respond called on hijacked connection") return &nullResponseBody{err: web.ErrInvalidState} } if t.respondCalled { log.Println("twister: Multiple calls to Respond") return &nullResponseBody{err: web.ErrInvalidState} } t.respondCalled = true t.requestErr = web.ErrInvalidState t.status = status t.header = header if te := header.Get(web.HeaderTransferEncoding); te != "" { log.Println("twister: transfer encoding not allowed") delete(header, web.HeaderTransferEncoding) } if !t.requestConsumed { t.closeAfterResponse = true } if header.Get(web.HeaderConnection) == "close" { t.closeAfterResponse = true } t.chunkedResponse = true contentLength := -1 if status == web.StatusNotModified { delete(header, web.HeaderContentType) delete(header, web.HeaderContentLength) t.chunkedResponse = false } else if s := header.Get(web.HeaderContentLength); s != "" { contentLength, _ = strconv.Atoi(s) t.chunkedResponse = false } else if t.req.ProtocolVersion < web.ProtocolVersion(1, 1) { t.closeAfterResponse = true } if t.closeAfterResponse { header.Set(web.HeaderConnection, "close") t.chunkedResponse = false } if t.req.Method == "HEAD" { t.chunkedResponse = false } if t.chunkedResponse { header.Set(web.HeaderTransferEncoding, "chunked") } proto := "HTTP/1.0" if t.req.ProtocolVersion >= web.ProtocolVersion(1, 1) { proto = "HTTP/1.1" } statusString := strconv.Itoa(status) text := web.StatusText(status) var b bytes.Buffer b.WriteString(proto) b.WriteString(" ") b.WriteString(statusString) b.WriteString(" ") b.WriteString(text) b.WriteString("\r\n") header.WriteHttpHeader(&b) t.headerSize = b.Len() const bufferSize = 4096 switch { case t.req.Method == "HEAD" || status == web.StatusNotModified: t.responseBody, _ = newNullResponseBody(t.conn, b.Bytes()) case t.chunkedResponse: t.responseBody, _ = newChunkedResponseBody(t.conn, b.Bytes(), bufferSize) default: t.responseBody, _ = newIdentityResponseBody(t.conn, b.Bytes(), bufferSize, contentLength) } return t.responseBody }