Beispiel #1
0
        /// <summary>
        /// Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
        /// </summary>
        /// <param name="Uri">URI</param>
        /// <param name="TimeoutMs">Timeout, in milliseconds. (Default=60000)</param>
        /// <param name="Headers">Optional headers. Interpreted in accordance with the corresponding URI scheme.</param>
        /// <exception cref="InvalidOperationException">No <see cref="HttpxProxy"/> set in the HTTPX <see cref="Types"/> module parameter.</exception>
        /// <exception cref="ArgumentException">If the <paramref name="Uri"/> parameter is invalid.</exception>
        /// <exception cref="ConflictException">If an approved presence subscription with the remote entity does not exist.</exception>
        /// <exception cref="ServiceUnavailableException">If the remote entity is not online.</exception>
        /// <exception cref="TimeoutException">If the request times out.</exception>
        /// <returns>Content-Type, together with a Temporary file, if resource has been downloaded, or null if resource is data-less.</returns>
        public async Task <KeyValuePair <string, TemporaryFile> > GetTempFileAsync(Uri Uri, int TimeoutMs, params KeyValuePair <string, string>[] Headers)
        {
            if (proxy is null)
            {
                if (!Types.TryGetModuleParameter("HTTPX", out object Obj) ||
                    !(Obj is HttpxProxy Proxy))
                {
                    throw new InvalidOperationException("A HTTPX Proxy object has not been registered.");
                }

                proxy = Proxy;
            }

            GetClientResponse Rec = await proxy.GetClientAsync(Uri);

            List <HttpField> Headers2 = new List <HttpField>();

            foreach (KeyValuePair <string, string> Header in Headers)
            {
                switch (Header.Key.ToLower())
                {
                case "host":
                    Headers2.Add(new HttpField("Host", Rec.BareJid));
                    break;

                case "cookie":
                case "set-cookie":
                    // Do not forward cookies.
                    break;

                default:
                    Headers2.Add(new HttpField(Header.Key, Header.Value));
                    break;
                }
            }

            State State = null;
            Timer Timer = null;

            try
            {
                State = new State();
                Timer = new Timer((P) =>
                {
                    State.Done.TrySetResult(false);
                }, null, TimeoutMs, Timeout.Infinite);

                Rec.HttpxClient.Request(Rec.FullJid, "GET", Rec.LocalUrl, (sender, e) =>
                {
                    if (e.Ok)
                    {
                        State.HttpResponse = e.HttpResponse;

                        if (e.StatusCode >= 200 && e.StatusCode < 300)
                        {
                            if (e.HasData)
                            {
                                State.File = new TemporaryFile();

                                if (!(e.Data is null))
                                {
                                    State.File.Write(e.Data, 0, e.Data.Length);
                                    State.Done.TrySetResult(true);
                                }
                            }
                            else
                            {
                                State.Done.TrySetResult(true);
                            }
                        }
Beispiel #2
0
        /// <summary>
        /// Posts to a resource, using a Uniform Resource Identifier (or Locator).
        /// </summary>
        /// <param name="Uri">URI</param>
        /// <param name="EncodedData">Encoded data to be posted.</param>
        /// <param name="ContentType">Content-Type of encoded data in <paramref name="EncodedData"/>.</param>
        /// <param name="TimeoutMs">Timeout, in milliseconds. (Default=60000)</param>
        /// <param name="Headers">Optional headers. Interpreted in accordance with the corresponding URI scheme.</param>
        /// <returns>Encoded response.</returns>
        /// <exception cref="InvalidOperationException">No <see cref="HttpxProxy"/> set in the HTTPX <see cref="Types"/> module parameter.</exception>
        /// <exception cref="ArgumentException">If the <paramref name="Uri"/> parameter is invalid.</exception>
        /// <exception cref="ArgumentException">If the object response be decoded.</exception>
        /// <exception cref="ConflictException">If an approved presence subscription with the remote entity does not exist.</exception>
        /// <exception cref="ServiceUnavailableException">If the remote entity is not online.</exception>
        /// <exception cref="TimeoutException">If the request times out.</exception>
        /// <exception cref="OutOfMemoryException">If resource too large to decode.</exception>
        /// <exception cref="IOException">If unable to read from temporary file.</exception>
        public async Task <KeyValuePair <byte[], string> > PostAsync(Uri Uri, byte[] EncodedData, string ContentType, int TimeoutMs, params KeyValuePair <string, string>[] Headers)
        {
            if (proxy is null)
            {
                if (!Types.TryGetModuleParameter("HTTPX", out object Obj) ||
                    !(Obj is HttpxProxy Proxy))
                {
                    throw new InvalidOperationException("A HTTPX Proxy object has not been registered.");
                }

                proxy = Proxy;
            }

            GetClientResponse Rec = await proxy.GetClientAsync(Uri);

            List <HttpField> Headers2       = new List <HttpField>();
            bool             HasContentType = false;

            foreach (KeyValuePair <string, string> Header in Headers)
            {
                switch (Header.Key.ToLower())
                {
                case "host":
                    Headers2.Add(new HttpField("Host", Rec.BareJid));
                    break;

                case "cookie":
                case "set-cookie":
                    // Do not forward cookies.
                    break;

                case "content-type":
                    Headers2.Add(new HttpField(Header.Key, Header.Value));
                    HasContentType = true;
                    break;

                default:
                    Headers2.Add(new HttpField(Header.Key, Header.Value));
                    break;
                }
            }

            if (!HasContentType)
            {
                Headers2.Add(new HttpField("Content-Type", ContentType));
            }

            MemoryStream Data  = new MemoryStream(EncodedData);
            State        State = null;
            Timer        Timer = null;

            try
            {
                State = new State();
                Timer = new Timer((P) =>
                {
                    State.Done.TrySetResult(false);
                }, null, TimeoutMs, Timeout.Infinite);

                Rec.HttpxClient.Request(Rec.FullJid, "POST", Rec.LocalUrl,
                                        1.1, Headers2, Data, async(sender, e) =>
                {
                    if (e.Ok)
                    {
                        State.HttpResponse  = e.HttpResponse;
                        State.StatusCode    = e.StatusCode;
                        State.StatusMessage = e.StatusMessage;

                        if (e.HasData)
                        {
                            State.Data = new MemoryStream();

                            if (!(e.Data is null))
                            {
                                await State.Data.WriteAsync(e.Data, 0, e.Data.Length);
                                State.Done.TrySetResult(true);
                            }
                        }
                        else
                        {
                            State.Done.TrySetResult(true);
                        }
                    }
                    else
                    {
                        State.Done.TrySetException(new IOException(string.IsNullOrEmpty(e.ErrorText) ? "Unable to get resource." : e.ErrorText));
                    }
                }, async(sender, e) =>
                {
                    await State.Data.WriteAsync(e.Data, 0, e.Data.Length);
                    if (e.Last)
                    {
                        State.Done.TrySetResult(true);
                    }
                }, State);

                if (!await State.Done.Task)
                {
                    throw new TimeoutException("Request timed out.");
                }

                Timer.Dispose();
                Timer = null;

                if (State.StatusCode >= 200 && State.StatusCode < 300)
                {
                    return(new KeyValuePair <byte[], string>(State.Data?.ToArray(), State.HttpResponse?.ContentType));
                }
                else
                {
                    ContentType = string.Empty;
                    EncodedData = State.Data?.ToArray();

                    throw HttpxGetter.GetExceptionObject(State.StatusCode, State.StatusMessage,
                                                         State.HttpResponse, EncodedData, ContentType);
                }
            }
            finally
            {
                State.Data?.Dispose();
                State.Data = null;

                State.HttpResponse?.Dispose();
                State.HttpResponse = null;

                Timer?.Dispose();
                Timer = null;

                Data.Dispose();
            }
        }
Beispiel #3
0
        /// <summary>
        /// Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
        /// </summary>
        /// <param name="Uri">URI</param>
        /// <param name="TimeoutMs">Timeout, in milliseconds. (Default=60000)</param>
        /// <param name="Headers">Optional headers. Interpreted in accordance with the corresponding URI scheme.</param>
        /// <exception cref="InvalidOperationException">No <see cref="HttpxProxy"/> set in the HTTPX <see cref="Types"/> module parameter.</exception>
        /// <exception cref="ArgumentException">If the <paramref name="Uri"/> parameter is invalid.</exception>
        /// <exception cref="ConflictException">If an approved presence subscription with the remote entity does not exist.</exception>
        /// <exception cref="ServiceUnavailableException">If the remote entity is not online.</exception>
        /// <exception cref="TimeoutException">If the request times out.</exception>
        /// <returns>Content-Type, together with a Temporary file, if resource has been downloaded, or null if resource is data-less.</returns>
        public async Task <KeyValuePair <string, TemporaryStream> > GetTempStreamAsync(Uri Uri, int TimeoutMs, params KeyValuePair <string, string>[] Headers)
        {
            if (proxy is null)
            {
                if (!Types.TryGetModuleParameter("HTTPX", out object Obj) ||
                    !(Obj is HttpxProxy Proxy))
                {
                    throw new InvalidOperationException("A HTTPX Proxy object has not been registered.");
                }

                proxy = Proxy;
            }

            GetClientResponse Rec = await proxy.GetClientAsync(Uri);

            List <HttpField> Headers2 = new List <HttpField>();
            bool             HasHost  = false;

            foreach (KeyValuePair <string, string> Header in Headers)
            {
                switch (Header.Key.ToLower())
                {
                case "host":
                    Headers2.Add(new HttpField("Host", Rec.BareJid));
                    HasHost = true;
                    break;

                case "cookie":
                case "set-cookie":
                    // Do not forward cookies.
                    break;

                default:
                    Headers2.Add(new HttpField(Header.Key, Header.Value));
                    break;
                }
            }

            if (!HasHost)
            {
                Headers2.Add(new HttpField("Host", Uri.Authority));
            }

            State State = null;
            Timer Timer = null;

            try
            {
                State = new State();
                Timer = new Timer((P) =>
                {
                    State.Done.TrySetResult(false);
                }, null, TimeoutMs, Timeout.Infinite);

                Rec.HttpxClient.Request(Rec.FullJid, "GET", Rec.LocalUrl, async(sender, e) =>
                {
                    if (e.Ok)
                    {
                        State.HttpResponse  = e.HttpResponse;
                        State.StatusCode    = e.StatusCode;
                        State.StatusMessage = e.StatusMessage;

                        if (e.HasData)
                        {
                            State.File = new TemporaryStream();

                            if (!(e.Data is null))
                            {
                                await State.File.WriteAsync(e.Data, 0, e.Data.Length);
                                State.Done.TrySetResult(true);
                            }
                        }
                        else
                        {
                            State.Done.TrySetResult(true);
                        }
                    }
                    else
                    {
                        State.Done.TrySetException(e.StanzaError ?? new Exception("Unable to get resource."));
                    }
                }, async(sender, e) =>
                {
                    await(State.File?.WriteAsync(e.Data, 0, e.Data.Length) ?? Task.CompletedTask);
                    if (e.Last)
                    {
                        State.Done?.TrySetResult(true);
                    }
                }, State, Headers2.ToArray());

                if (!await State.Done.Task)
                {
                    throw new TimeoutException("Request timed out.");
                }

                Timer.Dispose();
                Timer = null;

                if (State.StatusCode >= 200 && State.StatusCode < 300)
                {
                    TemporaryStream Result = State.File;
                    State.File = null;

                    return(new KeyValuePair <string, TemporaryStream>(State.HttpResponse?.ContentType, Result));
                }
                else
                {
                    string ContentType = string.Empty;
                    byte[] Data;

                    if (State.File is null)
                    {
                        Data = null;
                    }
                    else
                    {
                        int Len = (int)State.File.Length;

                        ContentType         = State.HttpResponse.ContentType;
                        State.File.Position = 0;
                        Data = new byte[Len];
                        await State.File.ReadAsync(Data, 0, Len);
                    }

                    throw GetExceptionObject(State.StatusCode, State.StatusMessage,
                                             State.HttpResponse, Data, ContentType);
                }
            }
            finally
            {
                State.File?.Dispose();
                State.File = null;

                State.HttpResponse?.Dispose();
                State.HttpResponse = null;

                Timer?.Dispose();
                Timer = null;
            }
        }