UploadStreamBase.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using Best.HTTP.Hosts.Connections;
  2. namespace Best.HTTP.Request.Upload
  3. {
  4. // [Request Creation] --> [Request Queued] --> [UploadStream.SetupRequestHeaders call] --> [Send Request Headers] --> [UploadStream.PrepareToSend call] --> [UploadStream.Read to Send Request Body] -> [Dispose UploadStream]
  5. public static class UploadReadConstants
  6. {
  7. public static int WaitForMore = -1;
  8. public static int Completed = 0;
  9. }
  10. /// <summary>
  11. /// Abstract class to serve as a base for non-conventional streams used in HTTP requests.
  12. /// </summary>
  13. /// <remarks>
  14. /// The return value of <see cref="System.IO.Stream.Read(byte[], int, int)"/> is treated specially in the plugin:
  15. /// <list type="bullet">
  16. /// <item>
  17. /// <term>Less than zero(<c>-1</c>)</term>
  18. /// <description> indicates that no data is currently available but more is expected in the future. In this case, when new data becomes available the IThreadSignaler object must be signaled.</description>
  19. /// </item>
  20. /// <item>
  21. /// <term>Zero (<c>0</c>)</term>
  22. /// <description> means that the stream is closed, no more data can be expected.</description>
  23. /// </item>
  24. /// <item><description>Otherwise it must return with the number bytes copied to the buffer.</description></item>
  25. /// </list>
  26. /// A zero value to signal stream closure can follow a less than zero value.
  27. /// </remarks>
  28. public abstract class UploadStreamBase : System.IO.Stream
  29. {
  30. /// <summary>
  31. /// Gets the <see cref="IThreadSignaler"/> object for signaling when new data is available.
  32. /// </summary>
  33. public IThreadSignaler Signaler { get; private set; }
  34. /// <summary>
  35. /// Length in bytes that the stream will upload.
  36. /// </summary>
  37. /// <remarks>
  38. /// The return value of Length is treated specially in the plugin:
  39. /// <list type="bullet">
  40. /// <item><term>-2</term><description>The stream's length is unknown and the plugin have to send data <c>with 'chunked' transfer-encoding</c>.</description></item>
  41. /// <item><term>-1</term><description>The stream's length is unknown and the plugin have to send data <c>as-is, without any encoding</c>.</description></item>
  42. /// <item><term>0</term><description>No content to send. The content-length header will contain zero (<c>0</c>).</description></item>
  43. /// <item><term>>0</term><description>Length of the content is known, will be sent <c>as-is, without any encoding</c>. The content-length header will contain zero (<c>0</c>).</description></item>
  44. /// </list>
  45. /// Constants for the first three points can be found in <see cref="Best.HTTP.Request.Upload.BodyLengths"/>.
  46. /// </remarks>
  47. public override long Length => throw new System.NotImplementedException();
  48. /// <summary>
  49. /// Called before sending out the request's headers. Perform content processing to calculate the final length if possible.
  50. /// In this function the implementor can set headers and other parameters to the request.
  51. /// </summary>
  52. /// <remarks>Typically called on a thread.</remarks>
  53. /// <param name="request">The <see cref="HTTPRequest"/> associated with the stream.</param>
  54. public abstract void BeforeSendHeaders(HTTPRequest request);
  55. /// <summary>
  56. /// Called just before sending out the request's body, and saves the <see cref="IThreadSignaler"/> for signaling when new data is available.
  57. /// </summary>
  58. /// <param name="request">The HTTPRequest associated with the stream.</param>
  59. /// <param name="threadSignaler">The <see cref="IThreadSignaler"/> object to be used for signaling.</param>
  60. /// <remarks>Typically called on a separate thread.</remarks>
  61. /// <summary>
  62. /// Called just before sending out the request's body, saves the <see cref="IThreadSignaler"/> that can be used for signaling when new data is available.
  63. /// </summary>
  64. /// <param name="request">The HTTPRequest associated with the stream.</param>
  65. /// <param name="threadSignaler">The <see cref="IThreadSignaler"/> object to be used for signaling.</param>
  66. /// <remarks>Typically called on a separate thread.</remarks>
  67. public virtual void BeforeSendBody(HTTPRequest request, IThreadSignaler threadSignaler) => this.Signaler = threadSignaler;
  68. protected override void Dispose(bool disposing)
  69. {
  70. base.Dispose(disposing);
  71. this.Signaler = null;
  72. }
  73. }
  74. }