protected void FlushResponse(HttpListenerContext context, FileStream stream) { if (stream.Length > 1024 && context.Request.Headers.AllKeys.Contains("Accept-Encoding") && context.Request.Headers["Accept-Encoding"].Contains("gzip")) { using (var ms = new MemoryStream()) { using (var zip = new GZipStream(ms, CompressionMode.Compress, true)) { stream.CopyTo( zip ); } ms.Position = 0; context.Response.AddHeader("Content-Encoding", "gzip"); context.Response.ContentLength64 = ms.Length; ms.WriteTo( context.Response.OutputStream ); } } else { context.Response.ContentLength64 = stream.Length; stream.CopyTo( context.Response.OutputStream ); } context.Response.OutputStream.Close(); context.Response.Close(); }
public ChunkedInputStream(HttpListenerContext context, Stream stream, byte[] buffer, int offset, int length) : base(stream, buffer, offset, length) { this.context = context; WebHeaderCollection coll = (WebHeaderCollection)context.Request.Headers; decoder = new ChunkStream(coll); }
private void InitTask(HttpListenerContext context) { try { var task = this.ProcessRequestAsync(context); task.ContinueWith(x => HandleError(x.Exception, context), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent); //if (task.Status == TaskStatus.Created) //{ // task.RunSynchronously(); //} } catch (Exception ex) { HandleError(ex, context); } }
/// <summary> /// Finds and invokes a route to match this context. Returns true if found, /// false if no route matches. /// </summary> internal bool FindAndInvokeRoute(HttpListenerContext context) { RESTResource resource; MethodInfo route; Match match; if (! FindRoute(context, out resource, out route, out match)) return false; if (route.GetParameters().Length == 2) { route.Invoke(resource, new object[] { context, match }); } else { route.Invoke(resource, new object[] { context }); } return true; }
private Task ProcessRequestAsync(HttpListenerContext context) { var request = context.Request; LogHttpRequest(request); if (request.IsWebSocketRequest) { ProcessWebSocketRequest(context); return Task.FromResult(true); } if (string.IsNullOrEmpty(context.Request.RawUrl)) return ((object)null).AsTaskResult(); var httpReq = GetRequest(context); return RequestHandler(httpReq, request.Url); }
private void QueueRequest(HttpListenerContext context) { lock (this._queue) { if (_queue.Count > MaxPendingRequests) { context.Response.StatusCode = 503; context.Response.OutputStream.Close(); context.Response.Close(); EventLogger.Log( String.Format( "Request queue max size reached: {0}. Connection refused with 503 error.", MaxPendingRequests ) ); return; } this._queue.Enqueue(context); this._ready.Set(); } }
internal void UnregisterContext(HttpListenerContext context) { lock (registry) registry.Remove(context); }
private void ProcessRequest(HttpListenerContext context) { try { if (ServerHeader != null) context.Response.Headers["Server"] = ServerHeader; var notfound = true; if (this._routeCache.FindAndInvokeRoute(context)) { notfound = false; } else if ((context.Request.HttpMethod.ToUpper().Equals("GET")) && (!object.ReferenceEquals(this.WebRoot, null))) { var filename = this.GetFilePath( context.Request.Url.LocalPath ); if (!object.ReferenceEquals(filename, null)) { this.SendFileResponse(context, filename); notfound = false; } } if (notfound) { this.NotFound(context); } } catch (Exception e) { try { EventLogger.Log(e); this.InternalServerError(context, e); } catch (Exception) // We can't even serve an error? { context.Response.StatusCode = 500; // Maybe we can serve the code } } finally { context.Response.OutputStream.Close(); // prevent resource leaks context.Response.Close(); // paranoia } }
/// <summary> /// Respond to a request using text. /// /// Does not set cache-control, so the response may be cached. Useful for serving simple text responses that /// you do not expect to change. /// </summary> protected void SendTextResponse(HttpListenerContext context, string payload, Encoding encoding = null) { encoding = (object.ReferenceEquals(encoding, null)) ? Encoding.UTF8 : encoding; var buffer = encoding.GetBytes(payload); var length = buffer.Length; context.Response.ContentEncoding = encoding; FlushResponse(context, buffer, length); }
private void HandleError(Exception ex, HttpListenerContext context) { var httpReq = GetRequest(context); if (ErrorHandler != null) { ErrorHandler(ex, httpReq); } }
private void ProcessWebSocketRequest(HttpListenerContext ctx) { try { var webSocketContext = ctx.AcceptWebSocket(null); if (WebSocketHandler != null) { WebSocketHandler(new WebSocketConnectEventArgs { WebSocket = new SharpWebSocket(webSocketContext.WebSocket, _logger), Endpoint = ctx.Request.RemoteEndPoint.ToString() }); } } catch (Exception ex) { _logger.ErrorException("AcceptWebSocketAsync error", ex); ctx.Response.StatusCode = 500; ctx.Response.Close(); } }
internal void RegisterContext(HttpListenerContext context) { if (OnContext != null && IsListening) { OnContext(context); } lock (registry) registry[context] = context; }
internal HttpListenerRequest(HttpListenerContext context) { this.context = context; headers = new WebHeaderCollection(); version = HttpVersion.Version10; }
private void SendResponse(HttpListenerContext context, long? positionTicks) { var response = context.Response; var state = GetState(); state.positionTicks = positionTicks ?? state.positionTicks; var bytes = Encoding.UTF8.GetBytes(_json.SerializeToString(state)); response.ContentType = "application/json"; response.ContentLength64 = bytes.Length; response.OutputStream.Write(bytes, 0, bytes.Length); }
// // todo: I don't like multiple out parameters, but I don't like special "result" // data structures either. Hmm. // internal bool FindRoute(HttpListenerContext context, out RESTResource resource, out MethodInfo method, out Match match) { var httpMethod = context.Request.HttpMethod.ToUpper(); string url = HttpUtility.UrlDecode( context.Request.Url.AbsolutePath ); foreach (Entry route in _routes) { if (route.Match(url, httpMethod, out match)) { method = route.MethodInfo; resource = route.RESTResource; return true; } } match = null; // out parameters must be set resource = null; method = null; return false; }
private void ProcessRequestInternal(HttpListenerContext context, string localPath) { var command = localPath.Split('/').LastOrDefault(); long? positionTicks = null; if (string.Equals(command, "config", StringComparison.OrdinalIgnoreCase)) { var response = context.Response; var bytes = Encoding.UTF8.GetBytes(_json.SerializeToString(_player.GetConfiguration())); response.ContentType = "application/json"; response.ContentLength64 = bytes.Length; response.OutputStream.Write(bytes, 0, bytes.Length); return; } if (string.Equals(command, "configsave", StringComparison.OrdinalIgnoreCase)) { var config = _json.DeserializeFromStream<DirectShowPlayerConfiguration>(context.Request.InputStream); _player.UpdateConfiguration(config); var response = context.Response; var bytes = Encoding.UTF8.GetBytes(_json.SerializeToString(_player.GetConfiguration())); response.ContentType = "application/json"; response.ContentLength64 = bytes.Length; response.OutputStream.Write(bytes, 0, bytes.Length); return; } if (string.Equals(command, "play", StringComparison.OrdinalIgnoreCase)) { var playRequest = _json.DeserializeFromStream<PlayRequest>(context.Request.InputStream); Play(playRequest.url, playRequest.startPositionTicks ?? 0, playRequest.isVideo, playRequest.mediaSource, playRequest.item, playRequest.fullscreen); } else if (string.Equals(command, "pause", StringComparison.OrdinalIgnoreCase)) { Pause(); } else if (string.Equals(command, "unpause", StringComparison.OrdinalIgnoreCase)) { UnPause(); } else if (string.Equals(command, "stopfade", StringComparison.OrdinalIgnoreCase)) { positionTicks = GetPositionTicks(); Stop(true); } else if (string.Equals(command, "stop", StringComparison.OrdinalIgnoreCase)) { positionTicks = GetPositionTicks(); Stop(false); } else if (string.Equals(command, "mute", StringComparison.OrdinalIgnoreCase)) { SetMute(true); } else if (string.Equals(command, "unmute", StringComparison.OrdinalIgnoreCase)) { SetMute(false); } else if (string.Equals(command, "volume", StringComparison.OrdinalIgnoreCase)) { float value; if (float.TryParse(context.Request.QueryString["val"], NumberStyles.Any, CultureInfo.InvariantCulture, out value)) { SetVolume(value); } } else if (string.Equals(command, "positionticks", StringComparison.OrdinalIgnoreCase)) { long value; if (long.TryParse(context.Request.QueryString["val"], NumberStyles.Any, CultureInfo.InvariantCulture, out value)) { SetPositionTicks(value); } } else if (string.Equals(command, "setAudioStreamIndex", StringComparison.OrdinalIgnoreCase)) { int value; if (int.TryParse(context.Request.QueryString["index"], NumberStyles.Any, CultureInfo.InvariantCulture, out value)) { _player.SetAudioStreamIndex(value); } } else if (string.Equals(command, "setSubtitleStreamIndex", StringComparison.OrdinalIgnoreCase)) { int value; if (int.TryParse(context.Request.QueryString["index"], NumberStyles.Any, CultureInfo.InvariantCulture, out value)) { _player.SetSubtitleStreamIndex(value); } } ResetStandby(); SendResponse(context, positionTicks); }
public async Task ProcessRequest(HttpListenerContext context, string localPath) { await _requestSemaphore.WaitAsync().ConfigureAwait(false); try { ProcessRequestInternal(context, localPath); } finally { _requestSemaphore.Release(); } }
void Cleanup(bool close_existing) { lock (registry) { if (close_existing) { // Need to copy this since closing will call UnregisterContext ICollection keys = registry.Keys; var all = new HttpListenerContext[keys.Count]; keys.CopyTo(all, 0); registry.Clear(); for (int i = all.Length - 1; i >= 0; i--) all[i].Connection.Close(true); } lock (connections.SyncRoot) { ICollection keys = connections.Keys; var conns = new HttpConnection[keys.Count]; keys.CopyTo(conns, 0); connections.Clear(); for (int i = conns.Length - 1; i >= 0; i--) conns[i].Close(true); } } }
private void ProcessWebSocketRequest(HttpListenerContext ctx) { try { var endpoint = ctx.Request.RemoteEndPoint.ToString(); var url = ctx.Request.RawUrl; var queryString = new NameValueCollection(ctx.Request.QueryString ?? new NameValueCollection()); var connectingArgs = new WebSocketConnectingEventArgs { Url = url, QueryString = queryString, Endpoint = endpoint }; if (WebSocketConnecting != null) { WebSocketConnecting(connectingArgs); } if (connectingArgs.AllowConnection) { _logger.Debug("Web socket connection allowed"); var webSocketContext = ctx.AcceptWebSocket(null); if (WebSocketConnected != null) { WebSocketConnected(new WebSocketConnectEventArgs { Url = url, QueryString = queryString, WebSocket = new SharpWebSocket(webSocketContext.WebSocket, _logger), Endpoint = endpoint }); } } else { _logger.Warn("Web socket connection not allowed"); ctx.Response.StatusCode = 401; ctx.Response.Close(); } } catch (Exception ex) { _logger.ErrorException("AcceptWebSocketAsync error", ex); ctx.Response.StatusCode = 500; ctx.Response.Close(); } }
/// <summary> /// Default response method to an Internal Server Error /// </summary> protected virtual void InternalServerError(HttpListenerContext context, string payload = "<h1>Internal Server Error</h1>", ContentType contentType = ContentType.HTML) { var buffer = Encoding.UTF8.GetBytes(payload); var length = buffer.Length; context.Response.StatusCode = 500; context.Response.StatusDescription = "Internal Server Error"; context.Response.ContentType = contentType.ToValue(); FlushResponse(context, buffer, length); }
private IHttpRequest GetRequest(HttpListenerContext httpContext) { var operationName = httpContext.Request.GetOperationName(); var req = new WebSocketSharpRequest(httpContext, operationName, RequestAttributes.None, _logger); req.RequestAttributes = req.GetAttributes(); return req; }
/// <summary> /// Default response method when a route or file is not found. You can override this to /// customize RESTServer's response. By default, the response may be cached, /// so this is not suitable for use in REST interfaces where a 404 response is not permanent. /// </summary> protected virtual void NotFound(HttpListenerContext context, string payload = "<h1>Not Found</h1>", ContentType contentType = ContentType.HTML) { var buffer = Encoding.UTF8.GetBytes(payload); var length = buffer.Length; context.Response.StatusCode = 404; context.Response.StatusDescription = "Not Found"; context.Response.ContentType = contentType.ToValue(); FlushResponse(context, buffer, length); }
private void ProcessContext(HttpListenerContext context) { Task.Factory.StartNew(() => InitTask(context)); }
/// <summary> /// Respond to a request with the contents of a file /// </summary> protected void SendFileResponse(HttpListenerContext context, string path) { var ext = Path.GetExtension(path).ToUpper().TrimStart('.'); var type = (Enum.IsDefined(typeof(ContentType), ext)) ? (ContentType)Enum.Parse(typeof(ContentType), ext) : ContentType.DEFAULT; var lastWriteTime = File.GetLastWriteTimeUtc(path); var lastModified = lastWriteTime.ToString("R"); var maxAge = (long)((DateTime.UtcNow - lastWriteTime).TotalSeconds + 86400); context.Response.AddHeader("Last-Modified", lastModified); context.Response.AddHeader("max-age", maxAge.ToString()); context.Response.ContentType = type.ToValue(); var ifModified = context.Request.Headers["If-Modified-Since"]; if (null != ifModified && ifModified == lastModified) { context.Response.StatusCode = (int)HttpStatusCode.NotModified; context.Response.Close(); } else { if (type.IsText()) { // Don't get too excited; this only detects UTF-8 and UTF-16. byte [] buffer; using (var reader = new StreamReader(path)) { buffer = Encoding.UTF8.GetBytes(reader.ReadToEnd()); } FlushResponse(context, buffer, buffer.Length); } else { using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read)) { FlushResponse(context, stream); } } } }
/// <summary> /// Default response method to an Internal Server Error /// </summary> protected virtual void InternalServerError(HttpListenerContext context, Exception e) { this.InternalServerError (context, e.ToString()); }
internal AuthenticationSchemes SelectAuthenticationScheme(HttpListenerContext context) { if (AuthenticationSchemeSelectorDelegate != null) return AuthenticationSchemeSelectorDelegate(context.Request); else return auth_schemes; }