Пример #1
0
        static async Task <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)
            {
                var    statusHeaders       = HttpHeaders.StatusHeader(response) + HttpHeaders.HeaderSeparator; // HTTP/1.1 xxx xxx\r\n
                Stream outputHeadersStream = null;

                switch (ch.ProcessingHeaders.Method)
                {
                case ProcessMethodEnum.RETURN:
                case ProcessMethodEnum.STDOUT:
                    outputHeadersStream = (returnstream ?? ctx.OutputStream);
                    goto default;

                case ProcessMethodEnum.FILE:
                    outputHeadersStream = ch.ProcessingHeaders.Stream.RawStream;
                    goto default;

                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.FromClass(ch),
                        PhpValue.Create(statusHeaders)
                    });

                    for (int i = 0; i < response.Headers.Count; i++)
                    {
                        var key   = response.Headers.GetKey(i);
                        var value = response.Headers.Get(i);

                        if (key == null || key.Length != 0)
                        {
                            // header
                            ch.ProcessingHeaders.User.Invoke(ctx, new[] {
                                PhpValue.FromClr(ch),
                                PhpValue.Create(key + ": " + value + HttpHeaders.HeaderSeparator),
                            });
                        }
                    }

                    // \r\n
                    ch.ProcessingHeaders.User.Invoke(ctx, new[] {
                        PhpValue.FromClr(ch),
                        PhpValue.Create(HttpHeaders.HeaderSeparator)
                    });

                    break;

                default:
                    if (outputHeadersStream != null)
                    {
                        await outputHeadersStream.WriteAsync(Encoding.ASCII.GetBytes(statusHeaders));

                        await outputHeadersStream.WriteAsync(response.Headers.ToByteArray());
                    }
                    else
                    {
                        Debug.Fail("Unexpected ProcessingHeaders " + ch.ProcessingHeaders.Method);
                    }
                    break;
                }
            }

            var stream = response.GetResponseStream();

            // gzip decode if necessary
            if (response.ContentEncoding == "gzip") // TODO: // && ch.AcceptEncoding.Contains("gzip") ??
            {
                ch.VerboseOutput("Decompressing the output stream using GZipStream.");
                stream = new GZipStream(stream, CompressionMode.Decompress, leaveOpen: false);
            }

            // read into output stream:
            switch (ch.ProcessingResponse.Method)
            {
            case ProcessMethodEnum.STDOUT: await stream.CopyToAsync(ctx.OutputStream); break;

            case ProcessMethodEnum.RETURN: stream.CopyTo(returnstream); break;

            case ProcessMethodEnum.FILE: await stream.CopyToAsync(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;
            }

            //
            stream.Dispose();
            stream = null;

            //

            return((returnstream != null)
                ? PhpValue.Create(new PhpString(returnstream.ToArray()))
                : PhpValue.True);
        }
Пример #2
0
        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);
        }