public async Task <Task> SendStream(Stream s) { header.Add("$response_code", response_code.ToString()); header.Add("$response_text", response_text); await proxy.WriteHeader(header); return(await proxy.BodyWriteStream(s)); }
/// <summary> /// The function responsible for handling each request. This function can be implemented by subclassing /// of this class and using override. The function is provided with the request header, request body, and /// the response encoder which allows setting of headers and data if any. /// </summary> /// <param name="header"></param> /// <param name="body"></param> /// <param name="encoder"></param> /// <returns></returns> public virtual async Task <Task> HandleRequest(Dictionary <String, String> header, Stream body, IProxyHTTPEncoder encoder) { var outheader = new Dictionary <String, String>(); outheader.Add("$response_code", "200"); outheader.Add("$response_text", "OK"); await encoder.WriteHeader(outheader); MemoryStream ms = new MemoryStream(); byte[] something = Encoding.UTF8.GetBytes("hello world\n"); ms.Write(something, 0, something.Length); ms.Write(something, 0, something.Length); ms.Write(something, 0, something.Length); ms.Write(something, 0, something.Length); ms.Write(something, 0, something.Length); ms.Position = 0; //await encoder.BodyWriteSingleChunk("response test body"); await encoder.BodyWriteStream(ms); return(Task.CompletedTask); }
/// <summary> /// Performs higher-level interpretation of application layer data and provides that in a higher level form /// for consumption by the upper layers. /// </summary> /// <param name="header"></param> /// <param name="body"></param> /// <param name="encoder"></param> /// <returns></returns> /// <remarks>This implementation needs cleaning on variable names for query string processing.</remarks> public override async Task <Task> HandleRequest(Dictionary <String, String> header, Stream body, IProxyHTTPEncoder encoder) { var outheader = new Dictionary <String, String>(); // Ensure the URL parameter actually exists instead of crashing. if (!header.ContainsKey("$url")) { outheader.Add("$response_code", "500"); outheader.Add("$response_text", "ERROR"); await encoder.WriteHeader(outheader); await encoder.BodyWriteSingleChunk("The request did not specify a URL."); return(Task.CompletedTask); } var url = header["$url"]; var url_absolute = url; var query_string = new Dictionary <String, String>(); String query_as_string = null; // Break down any query string into its key and value parts. if (url.IndexOf("?") > -1) { var qsndx = url.IndexOf("?"); query_as_string = url.Substring(qsndx + 1); var qstring_parts = query_as_string.Split('&'); foreach (var part in qstring_parts) { var eqndx = part.IndexOf("="); if (eqndx < 0) { query_string.Add(part, part); } else { query_string.Add(part.Substring(0, eqndx), part.Substring(eqndx + 1)); } } url_absolute = url.Substring(0, qsndx); } HTTPRequest request; switch (header["$method"].ToLower()) { case "get": request.method = HTTPRequestMethod.GET; break; case "post": request.method = HTTPRequestMethod.POST; break; default: request.method = HTTPRequestMethod.UNKNOWN; break; } // Package everything up nice. Hide away the messy implementation details. request.internal_headers = header; request.query = query_string; request.url = url; request.url_absolute = url_absolute; request.query_string = query_as_string; return(await HandleRequest2(request, body, encoder)); }
static public async Task <Task> Action(ServerHandler shandler, HTTPRequest request, Stream body, IProxyHTTPEncoder encoder) { // This URL route was never implemented with user security. The security ID itself is the security, but that // could be revised. //var auth = await ReadMessageFromStreamAndAuthenticate(1024 * 16, body); //if (!auth.success) //{ // throw new UnauthorizedException(); //} String download_sid; if (request.query_string.Length > 0) { download_sid = request.query_string; } else { //req = JsonConvert.DeserializeObject<HandleDownloadRequest>(auth.payload); //download_sid = req.security_id; throw new InvalidArgumentException(); } Item item; lock (shandler.items) { if (!shandler.items.ContainsKey(download_sid)) { throw new InvalidArgumentException(); } item = shandler.items[download_sid]; } var item_data_path = Path.Combine(shandler.data_path, item.node); var fd = File.OpenRead(item_data_path); ulong offset_start = 0; // How can a stream be negative? Could this stream ever be negative? What purpose does it suit? ulong offset_size = (ulong)fd.Length; ulong total_size = (ulong)fd.Length; String response_code = "200"; if (request.internal_headers.ContainsKey("range")) { var range_str = request.internal_headers["range"]; var eqndx = range_str.IndexOf("="); if (eqndx > -1) { var range_sub_str = range_str.Substring(eqndx + 1).Trim(); var range_nums_strs = range_sub_str.Split("-"); if (range_nums_strs.Length > 1) { offset_start = ulong.Parse(range_nums_strs[0]); if (range_nums_strs[1].Equals("")) { offset_size = (ulong)fd.Length - offset_start; } else { offset_size = ulong.Parse(range_nums_strs[1]) - offset_start + 1; } response_code = "206"; } } } checked { fd.Seek((long)offset_start, SeekOrigin.Begin); } fd.Seek((long)offset_start, SeekOrigin.Begin); String mime_type = null; switch (item.datatype) { case "mp4": mime_type = "video/mp4"; break; case "jpg": mime_type = "image/jpeg"; break; } using (var de_stream = new LimitedStream(fd, offset_size)) { var header = new Dictionary <String, String>(); header.Add("$response_code", response_code); header.Add("$response_text", "Partial Content"); header.Add("content-disposition", String.Format("inline; filename=\"{0}_{1}_{2}_{3}.{4}\"", item.datestr, item.userstr, item.devicestr, item.timestr, item.datatype ) ); header.Add("accept-ranges", "bytes"); header.Add("content-range", String.Format("bytes {0}-{1}/{2}", offset_start, offset_size + offset_start - 1, total_size ) ); if (mime_type != null) { header.Add("content-type", mime_type); } await encoder.WriteHeader(header); await encoder.BodyWriteStream(de_stream); return(Task.CompletedTask); } }