/// <summary> /// Resolve and return the HTTP handler for the HTTP context of request/response /// </summary> /// <param name="httpContext">HTTP context of request/response</param> /// <returns>HTTP handler for processing the request</returns> private IHttpHandler ResolveHandler(HttpContext httpContext) { IHttpHandler handler = null; // check if it is a request for the file system if (this.fileSystemHandler.CanProcessRequest(httpContext)) { handler = this.fileSystemHandler; } else { // if there are handlers if (this.handlers.Count > 0) { // check URL for handler if (this.handlers.Contains(httpContext.Request.URL)) handler = (IHttpHandler)this.handlers[httpContext.Request.URL]; else { // no handler for URL, try to use CGI handler if (this.cgiHandler.CanProcessRequest(httpContext)) handler = this.cgiHandler; } } else { // no handlers registered, try to use CGI handler if (this.cgiHandler.CanProcessRequest(httpContext)) handler = this.cgiHandler; } } return handler; }
/// <summary> /// Process a request from the corrisponding socket /// </summary> /// <param name="requestSocket">Socket bind to request</param> private void ProcessRequest(Socket requestSocket) { HttpRequest httpRequest = null; bool badRequest = false; try { // parse incoming request httpRequest = HttpRequest.Parse(requestSocket); } catch { // error parsing incoming request (bad request) httpRequest = new HttpRequest(); badRequest = true; } // create an HTTP context for the current request HttpContext httpContext = new HttpContext(httpRequest, new HttpServerUtility(this.config)); if (badRequest) { httpContext.Response.StatusCode = HttpStatusCode.BadRequest; httpContext.Response.Body = null; } else { try { // resolve handler to manage request IHttpHandler handler = this.ResolveHandler(httpContext); // no handler found if (handler == null) { httpContext.Response.StatusCode = HttpStatusCode.NotFound; } else { // process request by handler handler.ProcessRequest(httpContext); } } catch { httpContext.Response.StatusCode = HttpStatusCode.InternalServerError; httpContext.Response.Body = null; } } // TODO : evaluate initial capacity // build the status line StringBuilder responseBuilder = new StringBuilder("HTTP/1.1 "); responseBuilder.Append(httpContext.Response.StatusCode); responseBuilder.Append(" "); responseBuilder.AppendLine(this.MapStatusCodeToReason(httpContext.Response.StatusCode)); // build header section httpContext.Response.Headers["Content-Type"] = httpContext.Response.ContentType; int bodyLength = ((httpContext.Response.Body != null) && (httpContext.Response.Body != String.Empty)) ? httpContext.Response.Body.Length : 0; if (bodyLength > 0) httpContext.Response.Headers["Content-Length"] = bodyLength.ToString(); httpContext.Response.Headers["Connection"] = "close"; foreach (string responseHeaderKey in httpContext.Response.Headers.Keys) { responseBuilder.Append(responseHeaderKey); responseBuilder.Append(": "); responseBuilder.AppendLine(httpContext.Response.Headers[responseHeaderKey]); } // line blank seperation header-body responseBuilder.AppendLine(); // start sending status line and headers byte[] buffer = Encoding.UTF8.GetBytes(responseBuilder.ToString()); requestSocket.Send(buffer); // send body, if it exists if (bodyLength > 0) { buffer = Encoding.UTF8.GetBytes(httpContext.Response.Body); requestSocket.Send(buffer); } // no body, streamed response else { if (httpContext.Response.Stream != null) { byte[] sendBuffer = new byte[512]; int sendBytes = 0; while ((sendBytes = httpContext.Response.Stream.Read(sendBuffer, 0, sendBuffer.Length)) > 0) { requestSocket.Send(sendBuffer, sendBytes, SocketFlags.None); } httpContext.Response.CloseStream(); } } }
/// <summary> /// Return if handler can process the request /// </summary> /// <param name="httpContext">HTTP context of request/response</param> /// <returns>Handler can process or not the request</returns> public bool CanProcessRequest(HttpContext httpContext) { return (this.CgiCallback != null); }
public void ProcessRequest(HttpContext httpContext) { // if defined, calls the callback if (this.CgiCallback != null) this.CgiCallback(httpContext); }
public void CgiCallback(HttpContext httpContext) { // POST request if (httpContext.Request.HttpMethod == "POST") { // date & time configuration if (httpContext.Request.URL == "config/datetime") { // check that the body request (form parameters) contains date and time // (date=YYYYMMDD&time=HHmmss) if (!httpContext.Request.Form.ContainsKey("date") || !httpContext.Request.Form.ContainsKey("time")) httpContext.Response.StatusCode = HttpStatusCode.BadRequest; else { // extract date information string date = httpContext.Request.Form["date"]; int year = Convert.ToInt32(date.Substring(0, 4)); int month = Convert.ToInt32(date.Substring(4, 2)); int day = Convert.ToInt32(date.Substring(6, 2)); // extract time information string time = httpContext.Request.Form["time"]; int hour = Convert.ToInt32(time.Substring(0, 2)); int minute = Convert.ToInt32(time.Substring(2, 2)); int second = Convert.ToInt32(time.Substring(4, 2)); DateTime dateTime = new DateTime(year, month, day, hour, minute, second); // set datetime on RTC and into the system this.rtc.SetDateTime(dateTime); } } // configuration settings else if (httpContext.Request.URL == "config/settings") { // check that the body request (form parameters) contains settings // (ipAddress=...&subnetMask=...&gatewayAddress=....&isDhcpEnabled=...") if (!httpContext.Request.Form.ContainsKey("ipAddress") || !httpContext.Request.Form.ContainsKey("subnetMask") || !httpContext.Request.Form.ContainsKey("gatewayAddress") || !httpContext.Request.Form.ContainsKey("isDhcpEnabled") || !httpContext.Request.Form.ContainsKey("isDataLogEnabled")) httpContext.Response.StatusCode = HttpStatusCode.BadRequest; else { this.config.IPAddress = IPAddress.Parse(httpContext.Request.Form["ipAddress"]); this.config.SubnetMask = IPAddress.Parse(httpContext.Request.Form["subnetMask"]); this.config.GatewayAddress = IPAddress.Parse(httpContext.Request.Form["gatewayAddress"]); this.config.IsDhcpEnabled = (httpContext.Request.Form["isDhcpEnabled"] == "true"); this.config.IsDataLogEnabled = (httpContext.Request.Form["isDataLogEnabled"] == "true"); } this.config.Save(); } } // GET request else if (httpContext.Request.HttpMethod == "GET") { // get configuration settings if (httpContext.Request.URL == "config/settings") { string jsonResp = "{ \"isDhcpEnabled\" : " + this.config.IsDhcpEnabled.ToString().ToLower() + "," + " \"ipAddress\" : \"" + this.config.IPAddress.ToString() + "\"," + " \"subnetMask\" : \"" + this.config.SubnetMask.ToString() + "\"," + " \"gatewayAddress\" : \"" + this.config.GatewayAddress.ToString() + "\"," + " \"isDataLogEnabled\" : " + this.config.IsDataLogEnabled.ToString().ToLower() + "}"; // set content type //httpContext.Response.ContentType = "application/json"; httpContext.Response.Body = jsonResp; } // get weather station data else if (httpContext.Request.URL.StartsWith("sensors")) { string jsonResp = "{ \"temperature\" : " + this.temperature + "," + " \"humidity\" : " + this.humidity + "," + " \"ldrResistance\" : " + this.ldrResistance + "," + " \"ambientLight\" : " + this.ambientLight + "," + " \"windSpeed\" : " + this.windSpeed + "}"; // set content type //httpContext.Response.ContentType = "application/json"; httpContext.Response.Body = jsonResp; } } }