public static async Task HandleSeekableStreamAsync(this HttpConnection p, Stream stream) { var fileLength = stream.Length; long beginpos = 0; long endpos = fileLength - 1; p.ResponseHeaders["Accept-Ranges"] = "bytes"; if (p.RequestHeaders["Range"] is string ranges) { var match = regexBytes.Match(ranges); beginpos = Convert.ToInt64(match.Groups[1].Value); if (match.Groups[2].Success) { endpos = Convert.ToInt64(match.Groups[2].Value); } p.ResponseStatusCode = "206 Partial Content"; p.ResponseHeaders["Content-Range"] = $"bytes {beginpos}-{endpos}/{fileLength}"; } if (p.Method == "HEAD") { await p.outputStream.SwitchToKnownLengthModeAsync(fileLength); await p.EndResponseAsync(); } else { long realLength = endpos - beginpos + 1; if (p.outputStream.CurrentCompressionType == CompressionType.None) { await p.outputStream.SwitchToKnownLengthModeAsync(realLength); } else { await p.outputStream.SwitchToChunkedModeAsync(); } stream.Position = beginpos; await NaiveUtils.StreamCopyAsync(from : stream, to : p.outputStream, size : realLength, bs : (int)Math.Min(64 * 1024, realLength)); } }
public async Task <WsHandleRequestResult> HandleRequestAsync(bool enterRecvLoop) { List <string> connectionSplits = p.GetReqHeaderSplits("Connection"); if (p.Method == "GET" && p.GetReqHeader("Upgrade") == "websocket" && (connectionSplits.Contains("Upgrade") || connectionSplits.Contains("upgrade"))) { p.Handled = true; if (p.GetReqHeader("Sec-WebSocket-Version") != "13") { p.ResponseStatusCode = "400 Bad Request"; p.setHeader("Sec-WebSocket-Version", "13"); return(new WsHandleRequestResult(WsHandleRequestResult.Results.BadVersion)); } var wskey = p.GetReqHeader("Sec-WebSocket-Key"); if (wskey == null) { p.ResponseStatusCode = "400 Bad Request"; p.keepAlive = false; return(new WsHandleRequestResult(WsHandleRequestResult.Results.BadKey)); } p.ResponseStatusCode = "101 Switching Protocols"; p.setHeader("Upgrade", "websocket"); p.setHeader("Connection", "Upgrade"); p.setHeader("Sec-WebSocket-Accept", GetWebsocketAcceptKey(wskey)); p.keepAlive = false; await p.EndResponseAsync().CAF(); p.SwitchProtocol(); ConnectionState = States.Open; if (enterRecvLoop) { await recvLoopAsync().CAF(); } return(new WsHandleRequestResult(WsHandleRequestResult.Results.Connected)); } return(new WsHandleRequestResult(WsHandleRequestResult.Results.NonWebsocket)); }