public bool TryReadRequest(out HttpRequestData r) { r = new HttpRequestData(); // wait for some request bytes if (WaitForRequestBytes() == 0) { return(false); } // reader header bytes until \r\n\r\n const int MaxHeaderBytes = 32000; const byte CR = ((byte)'\r'); const byte LF = ((byte)'\n'); byte[] hb = null; int hbLen = -1; byte[] body = null; int bodyLen = 0; do { byte[] newBytes = ReadRequestBytes(MaxHeaderBytes); if (newBytes == null) { return(false); } if (hb == null) { hb = newBytes; } else { int len = hb.Length + newBytes.Length; if (len > MaxHeaderBytes) { return(false); } byte[] bytes = new byte[len]; Buffer.BlockCopy(hb, 0, bytes, 0, hb.Length); Buffer.BlockCopy(newBytes, 0, bytes, hb.Length, newBytes.Length); hb = bytes; } // look for \r\n\r\n in hb int l = hb.Length; for (int i = 0; i < l - 1; i++) { if (i < l - 3 && hb[i] == CR && hb[i + 1] == LF && hb[i + 2] == CR && hb[i + 3] == LF) { hbLen = i + 3; break; } else if (hb[i] == LF && hb[i + 1] == LF) { hbLen = i + 1; break; } } }while (hbLen < 0); // store the initial body chunk if (hbLen < hb.Length) { bodyLen = hb.Length - hbLen; body = new byte[bodyLen]; Buffer.BlockCopy(hb, hbLen, body, 0, bodyLen); } // convert headers to strings string[] headers = Encoding.UTF8.GetString(hb, 0, hbLen).Replace("\r\n", "\n").Split('\n'); // parse request line string[] firstLine = headers[0].Split(' '); if (firstLine.Length < 2) { return(false); } r.Method = firstLine[0].Trim(); r.Uri = firstLine[1].Trim(); // parse headers int contentLength = -1; for (int i = 1; i < headers.Length; i++) { string h = headers[i]; int j = h.IndexOf(':'); if (j > 0) { string k = h.Substring(0, j).Trim(); string v = h.Substring(j + 1).Trim(); r.Headers.Add(new KeyValuePair <string, string>(k, v)); if (string.Compare(k, "content-length", StringComparison.OrdinalIgnoreCase) == 0) { if (!int.TryParse(v, out contentLength)) { contentLength = -1; } } } } // store the body from the first chunk if (bodyLen > 0) { r.Body.Add(body); } // read remaining body, if any if (contentLength > 0 && bodyLen < contentLength) { // 100 response to POST if (r.Method == "POST") { WriteResponse(100, null, null, true); } while (bodyLen < contentLength) { byte[] bytes = ReadRequestBytes(contentLength - bodyLen); if (bytes == null || bytes.Length == 0) { return(false); } bodyLen += bytes.Length; r.Body.Add(bytes); } } return(true); }
public bool TryReadRequest(out HttpRequestData r) { r = new HttpRequestData(); // wait for some request bytes if (WaitForRequestBytes() == 0) return false; // reader header bytes until \r\n\r\n const int MaxHeaderBytes = 32000; const byte CR = ((byte)'\r'); const byte LF = ((byte)'\n'); byte[] hb = null; int hbLen = -1; byte[] body = null; int bodyLen = 0; do { byte[] newBytes = ReadRequestBytes(MaxHeaderBytes); if (newBytes == null) return false; if (hb == null) { hb = newBytes; } else { int len = hb.Length + newBytes.Length; if (len > MaxHeaderBytes) return false; byte[] bytes = new byte[len]; Buffer.BlockCopy(hb, 0, bytes, 0, hb.Length); Buffer.BlockCopy(newBytes, 0, bytes, hb.Length, newBytes.Length); hb = bytes; } // look for \r\n\r\n in hb int l = hb.Length; for (int i = 0; i < l - 1; i++) { if (i < l - 3 && hb[i] == CR && hb[i + 1] == LF && hb[i + 2] == CR && hb[i + 3] == LF) { hbLen = i + 3; break; } else if (hb[i] == LF && hb[i + 1] == LF) { hbLen = i + 1; break; } } } while (hbLen < 0); // store the initial body chunk if (hbLen < hb.Length) { bodyLen = hb.Length - hbLen; body = new byte[bodyLen]; Buffer.BlockCopy(hb, hbLen, body, 0, bodyLen); } // convert headers to strings string[] headers = Encoding.UTF8.GetString(hb, 0, hbLen).Replace("\r\n", "\n").Split('\n'); // parse request line string[] firstLine = headers[0].Split(' '); if (firstLine.Length < 2) return false; r.Method = firstLine[0].Trim(); r.Uri = firstLine[1].Trim(); // parse headers int contentLength = -1; for (int i = 1; i < headers.Length; i++) { string h = headers[i]; int j = h.IndexOf(':'); if (j > 0) { string k = h.Substring(0, j).Trim(); string v = h.Substring(j + 1).Trim(); r.Headers.Add(new KeyValuePair<string, string>(k, v)); if (string.Compare(k, "content-length", StringComparison.OrdinalIgnoreCase) == 0) { if (!int.TryParse(v, out contentLength)) contentLength = -1; } } } // store the body from the first chunk if (bodyLen > 0) r.Body.Add(body); // read remaining body, if any if (contentLength > 0 && bodyLen < contentLength) { // 100 response to POST if (r.Method == "POST") WriteResponse(100, null, null, true); while (bodyLen < contentLength) { byte[] bytes = ReadRequestBytes(contentLength - bodyLen); if (bytes == null || bytes.Length == 0) { return false; } bodyLen += bytes.Length; r.Body.Add(bytes); } } return true; }
void ProcessRequest(HttpSocket s) { HttpRequestData r = null; string path = null; // reply to unreadable requests if (!s.TryReadRequest(out r)) { s.WriteErrorResponse(400, "Unparsable bad request"); } // deny non-GET requests else if (r.Method != "GET") { s.WriteErrorResponse(405, "Method other than GET"); } // process special commands else if (TryProcessSpecialCommand(s, r.Uri)) { // done } // deny requests that cannot be mapped to disk else if (!TryMapUri(r.Uri, out path)) { s.WriteErrorResponse(404, "URI cannot be mapped to disk"); } // process file requests else if (TryProcessFileRequest(s, r.Uri, path)) { // done } // process directory requests else if (TryProcessDirectoryRequest(s, r.Uri, path)) { // done } // process XAP requests else if (TryProcessXapRequest(s, path)) { // done } // process XAP listing requests else if (TryProcessXapListingRequest(s, r.Uri, path)) { // done } // process requests for assemblies contained in Chiron's localAssemblyPath else if (TryProcessAssemblyRequest(s, r.Uri)) { // done } // process requests for .slvx files contained in Chiron's localAssemblyPath else if (TryProcessExternalRequest(s, r.Uri)) { //done } else { // not found s.WriteErrorResponse(404, "Resource not found"); } Chiron.Log(s.StatusCode, (r != null && r.Uri != null ? r.Uri : "[unknown]"), s.BytesSent, s.Message); }