using System; using ln.types; using System.IO; using System.Net.Sockets; using System.Net.Security; namespace ln.http.client { public class HttpClientRequest { public HttpClient HttpClient { get; } public URI URI { get => uri; set { if (!value.Scheme.Equals("http") && !value.Scheme.Equals("https")) throw new ArgumentOutOfRangeException(nameof(value), String.Format("unsupported url scheme: {0}", value.Scheme)); uri = value; } } public HttpHeaders Headers { get; } = new HttpHeaders(); public String Method { get; set; } URI uri; MemoryStream contentStream; HttpClientResponse clientResponse; public HttpClientRequest(HttpClient httpClient, URI uri) { HttpClient = httpClient; URI = uri; Headers.Add("user-agent", "ln.http.client"); } public Stream GetContentStream() { if (clientResponse != null) throw new NotSupportedException("Request has already been executed, content stream has been disposed"); if (contentStream == null) contentStream = new MemoryStream(); return contentStream; } public HttpClientResponse GetResponse() { if (clientResponse == null) { executeRequest(); } return clientResponse; } private Stream OpenConnection() { TcpClient tcpClient = null; SslStream sslStream = null; try { tcpClient = new TcpClient(); tcpClient.ExclusiveAddressUse = false; tcpClient.Connect(URI.Host, int.Parse(URI.Port)); if (!tcpClient.Connected) throw new IOException(String.Format("could not connect to host {0}",uri.Host)); if (uri.Scheme.Equals("https")) { sslStream = new SslStream(tcpClient.GetStream()); return sslStream; } return tcpClient.GetStream(); } catch (Exception) { if (sslStream != null) sslStream.Dispose(); if (tcpClient != null) tcpClient.Dispose(); throw; } } private void executeRequest() { if (contentStream.Length > 0) { byte[] requestContent = contentStream.ToArray(); Headers.Add("content-length", requestContent.Length.ToString()); } Stream connectionStream = OpenConnection(); clientResponse = new HttpClientResponse(this); contentStream.Dispose(); } } }