using System; using System.IO; using System.Text; using ln.json; using ln.mime; namespace ln.http; public abstract class HttpContent : IDisposable { public HttpContent(string contentType) { ContentType = contentType; } public string ContentType { get; } public abstract long Length { get; } public abstract void CopyTo(Stream targetStream); public virtual void Dispose() { } } public class StringContent : HttpContent { public string Text { get; set; } = String.Empty; public Encoding Encoding { get; set; } public StringContent(string text, string contentType) :base(contentType) { Encoding = Encoding.UTF8; Text = text; } public StringContent(string text) :this(text, "text/plain; charset=utf-8") { } public override long Length => Encoding.GetBytes(Text ).Length; public override void CopyTo(Stream targetStream) { byte[] bytes = Encoding.GetBytes(Text); targetStream.Write(bytes, 0, bytes.Length); } } public class FileContent : HttpContent { public string FileName { get; set; } public FileContent(string filename, string contentType) : base(contentType) { FileName = filename; } public FileContent(string filename) :this(filename, new MimeTypes().GetMimeTypeByExtension(Path.GetExtension(filename)).ToString()) { } public override long Length => new FileInfo(FileName).Length; public override void CopyTo(Stream targetStream) { using FileStream fs = new FileStream(FileName, FileMode.Open, FileAccess.Read); fs.CopyTo(targetStream); } } public class JsonContent : HttpContent { public JSONValue Value { get; set; } private byte[] _bytes; public JsonContent(JSONValue json) :base("application/json") { Value = json; } public override long Length { get { if (_bytes is null) Serialize(); return _bytes.Length; } } public override void CopyTo(Stream targetStream) { if (_bytes is null) Serialize(); targetStream.Write(_bytes, 0, _bytes.Length); } public void Serialize() { string jsonText = Value.ToString(); _bytes = Encoding.UTF8.GetBytes(jsonText); } } public class StreamContent : HttpContent { public Stream Stream { get; protected set; } public bool DisposeStream { get; } public StreamContent(Stream stream) : this(stream, true, "application/octet-stream") { } public StreamContent(Stream stream, bool disposeStream) :this(stream, disposeStream, "application/octet-stream") {} public StreamContent(Stream stream, string contentType) :this(stream, true, contentType) { } public StreamContent(Stream stream, bool disposeStream, string contentType) :base(contentType) { Stream = stream; DisposeStream = disposeStream; } public override long Length => Stream.CanSeek ? Stream.Length - Stream.Position : Stream.Length; public override void CopyTo(Stream targetStream) => Stream.CopyTo(targetStream); public override void Dispose() { if (DisposeStream) Stream.Dispose(); } } public class StreamedContent : HttpContent { public MemoryStream ContentStream { get; } public StreamedContent(string contentType) :base(contentType) { ContentStream = new MemoryStream(); } public override long Length => ContentStream.Length; public override void CopyTo(Stream targetStream) { ContentStream.Position = 0; ContentStream.CopyTo(targetStream); } public override void Dispose() { ContentStream?.Dispose(); } }