static Task <WebResponse> ExecHttpRequestInternalAsync(Context ctx, CURLResource ch, Uri uri) { var req = WebRequest.CreateHttp(uri); // setup request: Debug.Assert(ch.Method != null, "Method == null"); req.Method = ch.Method; req.AllowAutoRedirect = ch.FollowLocation && ch.MaxRedirects != 0; req.Timeout = ch.Timeout <= 0 ? System.Threading.Timeout.Infinite : ch.Timeout; req.ContinueTimeout = ch.ContinueTimeout; req.Accept = "*/*"; // default value if (req.AllowAutoRedirect) { // equal or less than 0 will cause exception req.MaximumAutomaticRedirections = ch.MaxRedirects < 0 ? int.MaxValue : ch.MaxRedirects; } if (ch.CookieContainer != null) { if (ch.Result != null) { // pass cookies from previous response to the request AddCookies(ch.Result.Cookies, ch.CookieContainer); } req.CookieContainer = ch.CookieContainer; } //req.AutomaticDecompression = (DecompressionMethods)~0; // NOTICE: this nullify response Content-Length and Content-Encoding if (ch.CookieHeader != null) { TryAddCookieHeader(req, ch.CookieHeader); } if (ch.Username != null) { req.Credentials = new NetworkCredential(ch.Username, ch.Password ?? string.Empty); } // TODO: certificate if (!string.IsNullOrEmpty(ch.ProxyType) && !string.IsNullOrEmpty(ch.ProxyHost)) { req.Proxy = new WebProxy($"{ch.ProxyType}://{ch.ProxyHost}:{ch.ProxyPort}") { Credentials = string.IsNullOrEmpty(ch.ProxyUsername) ? null : new NetworkCredential(ch.ProxyUsername, ch.ProxyPassword ?? string.Empty) }; } else { // by default, curl does not go through system proxy req.Proxy = s_DefaultProxy.Value; } // ch.ApplyOptions(ctx, req); // make request: // GET, HEAD if (string.Equals(ch.Method, WebRequestMethods.Http.Get, StringComparison.OrdinalIgnoreCase) || string.Equals(ch.Method, WebRequestMethods.Http.Head, StringComparison.OrdinalIgnoreCase)) { // nothing to do } // POST else if (string.Equals(ch.Method, WebRequestMethods.Http.Post, StringComparison.OrdinalIgnoreCase)) { ProcessPost(ctx, req, ch); } // PUT else if (string.Equals(ch.Method, WebRequestMethods.Http.Put, StringComparison.OrdinalIgnoreCase)) { ProcessPut(req, ch); } // DELETE, or custom method else { // custom method, nothing to do } // if (ch.StoreRequestHeaders) { ch.RequestHeaders = HttpHeaders.HeaderString(req); // and restore it when constructing CURLResponse } // return(req.GetResponseAsync()); }
static PhpValue ProcessResponse(Context ctx, CURLResource ch, HttpWebResponse response) { // in case we are returning the response value var returnstream = ch.ProcessingResponse.Method == ProcessMethodEnum.RETURN ? new MemoryStream() : null; // handle headers if (!ch.ProcessingHeaders.IsEmpty) { switch (ch.ProcessingHeaders.Method) { case ProcessMethodEnum.RETURN: case ProcessMethodEnum.STDOUT: (returnstream ?? ctx.OutputStream).Write(response.Headers.ToByteArray()); break; case ProcessMethodEnum.FILE: ch.ProcessingHeaders.Stream.RawStream.Write(response.Headers.ToByteArray()); break; case ProcessMethodEnum.USER: // pass headers one by one, // in original implementation we should pass them as they are read from socket: ch.ProcessingHeaders.User.Invoke(ctx, new[] { PhpValue.FromClr(ch), PhpValue.Create(HttpHeaders.StatusHeader(response) + HttpHeaders.HeaderSeparator) }); for (int i = 0; i < response.Headers.Count; i++) { // header ch.ProcessingHeaders.User.Invoke(ctx, new[] { PhpValue.FromClr(ch), PhpValue.Create(response.Headers[i] + HttpHeaders.HeaderSeparator), }); } // \r\n ch.ProcessingHeaders.User.Invoke(ctx, new[] { PhpValue.FromClr(ch), PhpValue.Create(HttpHeaders.HeaderSeparator) }); break; default: Debug.Fail("Unexpected ProcessingHeaders " + ch.ProcessingHeaders.Method); break; } } var stream = response.GetResponseStream(); // read into output stream: switch (ch.ProcessingResponse.Method) { case ProcessMethodEnum.STDOUT: stream.CopyTo(ctx.OutputStream); break; case ProcessMethodEnum.RETURN: stream.CopyTo(returnstream); break; case ProcessMethodEnum.FILE: stream.CopyTo(ch.ProcessingResponse.Stream.RawStream); break; case ProcessMethodEnum.USER: if (response.ContentLength != 0) { // preallocate a buffer to read to, // this should be according to PHP's behavior and slightly more effective than memory stream byte[] buffer = new byte[ch.BufferSize > 0 ? ch.BufferSize : 2048]; int bufferread; while ((bufferread = stream.Read(buffer, 0, buffer.Length)) > 0) { ch.ProcessingResponse.User.Invoke(ctx, new[] { PhpValue.FromClr(ch), PhpValue.Create(new PhpString(buffer.AsSpan(0, bufferread).ToArray())), // clone the array and pass to function }); } } break; case ProcessMethodEnum.IGNORE: break; } // return((returnstream != null) ? PhpValue.Create(new PhpString(returnstream.ToArray())) : PhpValue.True); }
static Task <WebResponse> ExecHttpRequestInternalAsync(Context ctx, CURLResource ch, Uri uri) { var req = WebRequest.CreateHttp(uri); // setup request: Debug.Assert(ch.Method != null, "Method == null"); req.Method = ch.Method; req.AllowAutoRedirect = ch.FollowLocation; req.Timeout = ch.Timeout; req.ContinueTimeout = ch.ContinueTimeout; req.MaximumAutomaticRedirections = ch.MaxRedirects; if (ch.UserAgent != null) { req.UserAgent = ch.UserAgent; } if (ch.ProtocolVersion != null) { req.ProtocolVersion = ch.ProtocolVersion; } if (ch.Referer != null) { req.Referer = ch.Referer; } if (ch.Headers != null) { AddHeaders(req, ch.Headers); } if (ch.CookieHeader != null) { TryAddCookieHeader(req, ch.CookieHeader); } if (ch.CookieFileSet) { req.CookieContainer = new CookieContainer(); } if (ch.Username != null) { req.Credentials = new NetworkCredential(ch.Username, ch.Password ?? string.Empty); } if (ch.AcceptEncoding != null) { req.Accept = ch.AcceptEncoding; } // TODO: certificate // TODO: proxy // make request: // GET, HEAD if (string.Equals(ch.Method, WebRequestMethods.Http.Get, StringComparison.OrdinalIgnoreCase) || string.Equals(ch.Method, WebRequestMethods.Http.Head, StringComparison.OrdinalIgnoreCase)) { // nothing to do } // POST else if (string.Equals(ch.Method, WebRequestMethods.Http.Post, StringComparison.OrdinalIgnoreCase)) { ProcessPost(ctx, req, ch); } // PUT else if (string.Equals(ch.Method, WebRequestMethods.Http.Put, StringComparison.OrdinalIgnoreCase)) { ProcessPut(req, ch); } // DELETE, or custom method else { // custom method, nothing to do } // if (ch.StoreRequestHeaders) { ch.RequestHeaders = HttpHeaders.HeaderString(req); // and restore it when constructing CURLResponse } // return(req.GetResponseAsync()); }