//--- Constructors --- /// <summary> /// Create a new message. /// </summary> /// <param name="status">Http status.</param> /// <param name="headers">Header collection.</param> public DreamMessage(DreamStatus status, DreamHeaders headers) { this.Status = status; this.Headers = new DreamHeaders(headers); _bytes = new byte[0]; _noContent = true; }
internal static XDoc ExecuteFork(Plug env, DreamHeaders headers, XDoc fork) { // execute script commands XDoc reply = new XDoc("results"); string ID = fork["@ID"].Contents; if (!string.IsNullOrEmpty(ID)) { reply.Attr("ID", ID); } // TODO (steveb): we should use a 'fixed capacity' cue which marks itself as done when 'count' is reached XDoc forks = fork.Elements; foreach (XDoc cmd in forks) { // TODO (steveb): we should be doing this in parallel, not sequentially! try { reply.Add(ExecuteCommand(env, headers, cmd)); } catch (Exception e) { reply.Add(new XException(e)); } } return(reply); }
/// <summary> /// Create a new message. /// </summary> /// <param name="status">Http status.</param> /// <param name="headers">Header collection.</param> /// <param name="contentType">Content Mime-Type.</param> /// <param name="bytes">Message body.</param> public DreamMessage(DreamStatus status, DreamHeaders headers, MimeType contentType, byte[] bytes) { if (bytes == null) { throw new ArgumentNullException("bytes"); } this.Status = status; this.Headers = new DreamHeaders(headers); this.Headers.ContentLength = bytes.LongLength; this.Headers.ContentType = contentType ?? MimeType.DefaultMimeType; // set bytes _bytes = bytes; }
/// <summary> /// Create a new message. /// </summary> /// <param name="status">Http status.</param> /// <param name="headers">Header collection.</param> /// <param name="contentType">Content Mime-Type</param> /// <param name="contentLength">Content byte langth</param> /// <param name="stream">Stream to uas as the source for the message's content.</param> public DreamMessage(DreamStatus status, DreamHeaders headers, MimeType contentType, long contentLength, Stream stream) { this.Status = status; this.Headers = new DreamHeaders(headers); if (contentLength != -1) { this.Headers.ContentLength = contentLength; } this.Headers.ContentType = contentType ?? MimeType.DefaultMimeType; // set stream _stream = stream ?? Stream.Null; _streamOpen = !_stream.IsStreamMemorized(); }
/// <summary> /// WARNING: This method is thread-blocking. Please avoid using it if possible. /// </summary> internal static XDoc ExecutePipe(Plug env, DreamHeaders headers, XDoc pipe) { DreamMessage message = null; foreach (XDoc action in pipe["action"]) { string verb = action["@verb"].Contents; string path = action["@path"].Contents; XUri uri; if (!XUri.TryParse(path, out uri)) { uri = env.Uri.AtPath(path); } // create first message if (message == null) { message = DreamMessage.Ok(GetActionBody(action)); } message.Headers.AddRange(headers); // apply headers foreach (XDoc header in action["header"]) { message.Headers[header["@name"].Contents] = header.Contents; } // execute action message = Plug.New(uri).Invoke(verb, message); if (!message.IsSuccessful) { break; } } // prepare response if (message == null) { return(XDoc.Empty); } XDoc result = new XMessage(message); string ID = pipe["@ID"].Contents; if (!string.IsNullOrEmpty(ID)) { result.Root.Attr("ID", ID); } return(result); }
internal static XDoc ExecuteScript(Plug env, DreamHeaders headers, XDoc script) { // execute script commands XDoc reply = new XDoc("results"); string ID = script["@ID"].Contents; if (!string.IsNullOrEmpty(ID)) { reply.Attr("ID", ID); } foreach (XDoc cmd in script.Elements) { reply.Add(ExecuteCommand(env, headers, cmd)); } return(reply); }
/// <summary> /// WARNING: This method is thread-blocking. Please avoid using it if possible. /// </summary> internal static XDoc ExecuteAction(Plug env, DreamHeaders headers, XDoc action) { string verb = action["@verb"].Contents; string path = action["@path"].Contents; if ((path.Length > 0) && (path[0] == '/')) { path = path.Substring(1); } XUri uri; if (!XUri.TryParse(path, out uri)) { uri = env.Uri.AtAbsolutePath(path); } // create message DreamMessage message = DreamMessage.Ok(GetActionBody(action)); message.Headers.AddRange(headers); // apply headers foreach (XDoc header in action["header"]) { message.Headers[header["@name"].Contents] = header.Contents; } // BUG #814: we need to support events // execute action DreamMessage reply = Plug.New(uri).Invoke(verb, message); // prepare response XDoc result = new XMessage(reply); string ID = action["@ID"].Contents; if (!string.IsNullOrEmpty(ID)) { result.Root.Attr("ID", ID); } return(result); }
/// <summary> /// Add a range of headers. /// </summary> /// <param name="headers">Header collection</param> /// <returns>Current instance.</returns> public DreamHeaders AddRange(DreamHeaders headers) { if (headers != null) { // add entries foreach (KeyValuePair <string, Entry> header in headers._headers) { Entry existing; // find existing entry if (_headers.TryGetValue(header.Key, out existing)) { existing = existing.Last; } // add new entries for (Entry other = header.Value; other != null; other = other.Next) { if (existing == null) { existing = new Entry(other.Value); _headers[header.Key] = existing; } else { existing.Next = new Entry(other.Value); existing = existing.Next; } } } // add cookies if (headers.HasCookies) { foreach (DreamCookie cookie in headers.Cookies) { Cookies.Add(cookie); } } } return(this); }
/// <summary> /// Create a new message. /// </summary> /// <param name="status">Http status.</param> /// <param name="headers">Header collection.</param> /// <param name="contentType">Content Mime-Type.</param> /// <param name="doc">Message body.</param> public DreamMessage(DreamStatus status, DreamHeaders headers, MimeType contentType, XDoc doc) { if (doc == null) { throw new ArgumentNullException("doc"); } this.Status = status; this.Headers = new DreamHeaders(headers); // check if document is empty if (doc.IsEmpty) { // we store empty XML documents as text content; it causes less confusion for browsers this.Headers.ContentType = MimeType.TEXT; this.Headers.ContentLength = 0L; _doc = doc; _bytes = new byte[0]; } else { this.Headers.ContentType = contentType ?? MimeType.XML; _doc = doc.Clone(); } }
//--- Methods --- internal static XDoc ExecuteCommand(Plug env, DreamHeaders headers, XDoc cmd) { try { switch (cmd.Name.ToLowerInvariant()) { case "script": return(ExecuteScript(env, headers, cmd)); case "fork": return(ExecuteFork(env, headers, cmd)); case "action": return(ExecuteAction(env, headers, cmd)); case "pipe": return(ExecutePipe(env, headers, cmd)); default: throw new DreamException(string.Format("unregonized script command: " + cmd.Name.ToString())); } } catch (Exception e) { return(new XException(e)); } }
/// <summary> /// Create a new message. /// </summary> /// <param name="status">Http status.</param> /// <param name="headers">Header collection.</param> /// <param name="contentType">Content Mime-Type.</param> /// <param name="text">Message body.</param> public DreamMessage(DreamStatus status, DreamHeaders headers, MimeType contentType, string text) : this(status, headers, contentType, contentType.CharSet.GetBytes(text)) { }
/// <summary> /// Create a new message. /// </summary> /// <param name="status">Http status.</param> /// <param name="headers">Header collection.</param> /// <param name="doc">Message body.</param> public DreamMessage(DreamStatus status, DreamHeaders headers, XDoc doc) : this(status, headers, MimeType.XML, doc) { }
/// <summary> /// Create new instance. /// </summary> /// <param name="headers">Headers to copy into new instance.</param> public DreamHeaders(DreamHeaders headers) { AddRange(headers); }