SimpleHttpRequest.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. * Copyright (c) Contributors, http://www.openmetaverse.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. *
  27. */
  28. namespace Nwc.XmlRpc
  29. {
  30. using System;
  31. using System.IO;
  32. using System.Net.Sockets;
  33. using System.Collections;
  34. ///<summary>Very basic HTTP request handler.</summary>
  35. ///<remarks>This class is designed to accept a TcpClient and treat it as an HTTP request.
  36. /// It will do some basic header parsing and manage the input and output streams associated
  37. /// with the request.</remarks>
  38. public class SimpleHttpRequest
  39. {
  40. private String _httpMethod = null;
  41. private String _protocol;
  42. private String _filePathFile = null;
  43. private String _filePathDir = null;
  44. private String __filePath;
  45. private TcpClient _client;
  46. private StreamReader _input;
  47. private StreamWriter _output;
  48. private Hashtable _headers;
  49. /// <summary>A constructor which accepts the TcpClient.</summary>
  50. /// <remarks>It creates the associated input and output streams, determines the request type,
  51. /// and parses the remaining HTTP header.</remarks>
  52. /// <param name="client">The <c>TcpClient</c> associated with the HTTP connection.</param>
  53. public SimpleHttpRequest(TcpClient client)
  54. {
  55. _client = client;
  56. _output = new StreamWriter(client.GetStream());
  57. _input = new StreamReader(client.GetStream());
  58. GetRequestMethod();
  59. GetRequestHeaders();
  60. }
  61. /// <summary>The output <c>StreamWriter</c> associated with the request.</summary>
  62. public StreamWriter Output
  63. {
  64. get { return _output; }
  65. }
  66. /// <summary>The input <c>StreamReader</c> associated with the request.</summary>
  67. public StreamReader Input
  68. {
  69. get { return _input; }
  70. }
  71. /// <summary>The <c>TcpClient</c> with the request.</summary>
  72. public TcpClient Client
  73. {
  74. get { return _client; }
  75. }
  76. private String _filePath
  77. {
  78. get { return __filePath; }
  79. set
  80. {
  81. __filePath = value;
  82. _filePathDir = null;
  83. _filePathFile = null;
  84. }
  85. }
  86. /// <summary>The type of HTTP request (i.e. PUT, GET, etc.).</summary>
  87. public String HttpMethod
  88. {
  89. get { return _httpMethod; }
  90. }
  91. /// <summary>The level of the HTTP protocol.</summary>
  92. public String Protocol
  93. {
  94. get { return _protocol; }
  95. }
  96. /// <summary>The "path" which is part of any HTTP request.</summary>
  97. public String FilePath
  98. {
  99. get { return _filePath; }
  100. }
  101. /// <summary>The file portion of the "path" which is part of any HTTP request.</summary>
  102. public String FilePathFile
  103. {
  104. get
  105. {
  106. if (_filePathFile != null)
  107. return _filePathFile;
  108. int i = FilePath.LastIndexOf("/");
  109. if (i == -1)
  110. return "";
  111. i++;
  112. _filePathFile = FilePath.Substring(i, FilePath.Length - i);
  113. return _filePathFile;
  114. }
  115. }
  116. /// <summary>The directory portion of the "path" which is part of any HTTP request.</summary>
  117. public String FilePathDir
  118. {
  119. get
  120. {
  121. if (_filePathDir != null)
  122. return _filePathDir;
  123. int i = FilePath.LastIndexOf("/");
  124. if (i == -1)
  125. return "";
  126. i++;
  127. _filePathDir = FilePath.Substring(0, i);
  128. return _filePathDir;
  129. }
  130. }
  131. private void GetRequestMethod()
  132. {
  133. string req = _input.ReadLine();
  134. if (req == null)
  135. throw new ApplicationException("Void request.");
  136. if (0 == String.Compare("GET ", req.Substring(0, 4), true))
  137. _httpMethod = "GET";
  138. else if (0 == String.Compare("POST ", req.Substring(0, 5), true))
  139. _httpMethod = "POST";
  140. else
  141. throw new InvalidOperationException("Unrecognized method in query: " + req);
  142. req = req.TrimEnd();
  143. int idx = req.IndexOf(' ') + 1;
  144. if (idx >= req.Length)
  145. throw new ApplicationException("What do you want?");
  146. string page_protocol = req.Substring(idx);
  147. int idx2 = page_protocol.IndexOf(' ');
  148. if (idx2 == -1)
  149. idx2 = page_protocol.Length;
  150. _filePath = page_protocol.Substring(0, idx2).Trim();
  151. _protocol = page_protocol.Substring(idx2).Trim();
  152. }
  153. private void GetRequestHeaders()
  154. {
  155. String line;
  156. int idx;
  157. _headers = new Hashtable();
  158. while ((line = _input.ReadLine()) != "")
  159. {
  160. if (line == null)
  161. {
  162. break;
  163. }
  164. idx = line.IndexOf(':');
  165. if (idx == -1 || idx == line.Length - 1)
  166. {
  167. Logger.WriteEntry("Malformed header line: " + line, LogLevel.Information);
  168. continue;
  169. }
  170. String key = line.Substring(0, idx);
  171. String value = line.Substring(idx + 1);
  172. try
  173. {
  174. _headers.Add(key, value);
  175. }
  176. catch (Exception)
  177. {
  178. Logger.WriteEntry("Duplicate header key in line: " + line, LogLevel.Information);
  179. }
  180. }
  181. }
  182. /// <summary>
  183. /// Format the object contents into a useful string representation.
  184. /// </summary>
  185. ///<returns><c>String</c> representation of the <c>SimpleHttpRequest</c> as the <i>HttpMethod FilePath Protocol</i>.</returns>
  186. override public String ToString()
  187. {
  188. return HttpMethod + " " + FilePath + " " + Protocol;
  189. }
  190. /// <summary>
  191. /// Close the <c>SimpleHttpRequest</c>. This flushes and closes all associated io streams.
  192. /// </summary>
  193. public void Close()
  194. {
  195. _output.Flush();
  196. _output.Close();
  197. _input.Close();
  198. _client.Close();
  199. }
  200. }
  201. }