func (c *conn) Respond(status int, header web.StringsMap) (body web.ResponseBody) { if c.hijacked { log.Stderr("twister: Respond called on hijacked connection") return nil } if c.respondCalled { log.Stderr("twister: multiple calls to Respond") return nil } c.respondCalled = true c.requestErr = web.ErrInvalidState if _, found := header.Get(web.HeaderTransferEncoding); found { log.Stderr("twister: transfer encoding not allowed") header[web.HeaderTransferEncoding] = nil, false } if c.requestAvail > 0 { c.closeAfterResponse = true } c.chunked = true c.responseAvail = 0 if status == web.StatusNotModified { header[web.HeaderContentType] = nil, false header[web.HeaderContentLength] = nil, false c.chunked = false } else if s, found := header.Get(web.HeaderContentLength); found { c.responseAvail, _ = strconv.Atoi(s) c.chunked = false } else if c.req.ProtocolVersion < web.ProtocolVersion(1, 1) { c.closeAfterResponse = true } if c.closeAfterResponse { header.Set(web.HeaderConnection, "close") c.chunked = false } if c.chunked { header.Set(web.HeaderTransferEncoding, "chunked") } proto := "HTTP/1.0" if c.req.ProtocolVersion >= web.ProtocolVersion(1, 1) { proto = "HTTP/1.1" } statusString := strconv.Itoa(status) text, found := web.StatusText[status] if !found { text = "status code " + statusString } var b bytes.Buffer b.WriteString(proto) b.WriteString(" ") b.WriteString(statusString) b.WriteString(" ") b.WriteString(text) b.WriteString("\r\n") for key, values := range header { for _, value := range values { b.WriteString(key) b.WriteString(": ") b.WriteString(cleanHeaderValue(value)) b.WriteString("\r\n") } } b.WriteString("\r\n") if c.chunked { c.bw = bufio.NewWriter(chunkedWriter{c}) _, c.responseErr = c.netConn.Write(b.Bytes()) } else { c.bw = bufio.NewWriter(identityWriter{c}) c.bw.Write(b.Bytes()) } return c.bw }