protected Task ProduceEnd() { if (_requestRejected || _applicationException != null) { if (HasResponseStarted) { // We can no longer change the response, so we simply close the connection. _requestProcessingStopping = true; return(TaskUtilities.CompletedTask); } if (_requestRejected) { // 400 Bad Request StatusCode = 400; _keepAlive = false; } else { // 500 Internal Server Error StatusCode = 500; } ReasonPhrase = null; var responseHeaders = FrameResponseHeaders; responseHeaders.Reset(); var dateHeaderValues = DateHeaderValueManager.GetDateHeaderValues(); responseHeaders.SetRawDate(dateHeaderValues.String, dateHeaderValues.Bytes); responseHeaders.SetRawContentLength("0", _bytesContentLengthZero); if (ServerOptions.AddServerHeader) { responseHeaders.SetRawServer(Constants.ServerName, _bytesServer); } } if (!HasResponseStarted) { return(ProduceEndAwaited()); } return(WriteSuffix()); }
private void CreateResponseHeader( byte[] statusBytes, bool appCompleted) { var responseHeaders = FrameResponseHeaders; responseHeaders.SetReadOnly(); var hasConnection = responseHeaders.HasConnection; var end = SocketOutput.ProducingStart(); if (_keepAlive && hasConnection) { foreach (var connectionValue in responseHeaders.HeaderConnection) { if (connectionValue.IndexOf("close", StringComparison.OrdinalIgnoreCase) != -1) { _keepAlive = false; break; } } } if (_keepAlive && !responseHeaders.HasTransferEncoding && !responseHeaders.HasContentLength) { if (appCompleted) { // Don't set the Content-Length or Transfer-Encoding headers // automatically for HEAD requests or 101, 204, 205, 304 responses. if (Method != "HEAD" && StatusCanHaveBody(StatusCode)) { // Since the app has completed and we are only now generating // the headers we can safely set the Content-Length to 0. responseHeaders.SetRawContentLength("0", _bytesContentLengthZero); } } else { // Note for future reference: never change this to set _autoChunk to true on HTTP/1.0 // connections, even if we were to infer the client supports it because an HTTP/1.0 request // was received that used chunked encoding. Sending a chunked response to an HTTP/1.0 // client would break compliance with RFC 7230 (section 3.3.1): // // A server MUST NOT send a response containing Transfer-Encoding unless the corresponding // request indicates HTTP/1.1 (or later). if (_httpVersion == HttpVersionType.Http11) { _autoChunk = true; responseHeaders.SetRawTransferEncoding("chunked", _bytesTransferEncodingChunked); } else { _keepAlive = false; } } } if (!_keepAlive && !hasConnection && _httpVersion != HttpVersionType.Http10) { responseHeaders.SetRawConnection("close", _bytesConnectionClose); } else if (_keepAlive && !hasConnection && _httpVersion == HttpVersionType.Http10) { responseHeaders.SetRawConnection("keep-alive", _bytesConnectionKeepAlive); } if (ServerOptions.AddServerHeader && !responseHeaders.HasServer) { responseHeaders.SetRawServer(Constants.ServerName, _bytesServer); } if (!responseHeaders.HasDate) { var dateHeaderValues = DateHeaderValueManager.GetDateHeaderValues(); responseHeaders.SetRawDate(dateHeaderValues.String, dateHeaderValues.Bytes); } end.CopyFrom(_bytesHttpVersion11); end.CopyFrom(statusBytes); responseHeaders.CopyTo(ref end); end.CopyFrom(_bytesEndHeaders, 0, _bytesEndHeaders.Length); SocketOutput.ProducingComplete(end); }