public function __invoke($context)
 {
     // _GET vars
     $context['_GET'] = array();
     if (isset($context['env']['QUERY_STRING'])) {
         parse_str($context['env']['QUERY_STRING'], $context['_GET']);
     }
     // _COOKIE vars
     if (isset($context['env']['HTTP_COOKIE'])) {
         $ck = new HTTPParser\Cookies($context['env']['HTTP_COOKIE']);
     } else {
         $ck = new HTTPParser\Cookies(null);
     }
     $context['_COOKIE'] = $ck;
     // _POST and _FILES
     $stream_name = null;
     if ($context['env']['REQUEST_METHOD'] === 'POST') {
         $context['_POST'] = array();
         $context['_FILES'] = array();
         $form_data = (empty($context['env']['CONTENT_TYPE']) or strpos($context['env']['CONTENT_TYPE'], 'application/x-www-form-urlencoded') === 0);
         $multipart = (isset($context['env']['CONTENT_TYPE']) and strpos($context['env']['CONTENT_TYPE'], 'multipart/form-data') === 0);
         if ($form_data or $multipart) {
             $buffer = stream_get_contents($context['stdin'], $context['env']['CONTENT_LENGTH']);
             if (isset($this->options['forward_stream']) and $this->options['forward_stream'] === true) {
                 // user asks us to provide a valid stream to app
                 $_old_stdin = $context['stdin'];
                 $context['stdin'] = Keeper::create($buffer)->fopen();
             }
             if ($multipart) {
                 self::parseMultipart($context['env']['CONTENT_TYPE'], $buffer, $context['_POST'], $context['_FILES']);
             } elseif ($form_data) {
                 parse_str($buffer, $context['_POST']);
             }
             unset($buffer);
             // free memory
         }
     }
     // EXECUTE
     $result = call_user_func($this->app, $context);
     if (!is_array($result)) {
         return $result;
     }
     // Append cookie-headers
     $result[1] = array_merge($result[1], $ck->_getHeaders());
     // Cleanup
     if (isset($_old_stdin)) {
         // remove our "fake" stream
         fclose($context['stdin']);
         $context['stdin'] = $_old_stdin;
     }
     if (isset($context['env']['_FILES'])) {
         // remove created files, if there were any
         foreach ($context['env']['_FILES'] as $file) {
             if ($file['error'] == UPLOAD_ERR_OK and file_exists($file['tmp_name'])) {
                 unlink($file['tmp_name']);
             }
         }
     }
     return $result;
 }
 public function testPOST()
 {
     $test = $this;
     $parser = new HTTPParser(function ($context) use($test) {
         $test->assertArrayHasKey('_GET', $context);
         $test->assertArrayHasKey('_COOKIE', $context);
         $test->assertArrayHasKey('_POST', $context);
         $test->assertArrayHasKey('_FILES', $context);
         $test->assertEmpty($context['_GET']);
         $test->assertEmpty($context['_COOKIE']->__toArray());
         $test->assertEmpty($context['_POST']);
         $test->assertEmpty($context['_FILES']);
     });
     $parser(['env' => ['REQUEST_METHOD' => 'POST', 'QUERY_STRING' => '', 'CONTENT_LENGTH' => 0], 'stdin' => Keeper::create('')->fopen()]);
     $parser = new HTTPParser(function ($context) use($test) {
         $test->assertEquals(['abc' => 'def', 'ghi' => 'jkl', 'a' => ['b', 'c']], $context['_POST']);
     });
     $parser(['env' => ['REQUEST_METHOD' => 'POST', 'QUERY_STRING' => '', 'CONTENT_LENGTH' => 27], 'stdin' => Keeper::create('abc=def&ghi=jkl&a[]=b&a[]=c')->fopen()]);
     $parser = new HTTPParser(function ($context) use($test) {
         $test->assertEquals(['abc' => 'def', 'ghi' => 'jkl', 'a' => ['b', 'c']], $context['_POST']);
     });
     $parser(['env' => ['REQUEST_METHOD' => 'POST', 'QUERY_STRING' => '', 'CONTENT_LENGTH' => 27, 'CONTENT_TYPE' => 'application/x-www-form-urlencoded; charset=utf-8'], 'stdin' => Keeper::create('abc=def&ghi=jkl&a[]=b&a[]=c')->fopen()]);
     $parser = new HTTPParser(function ($context) use($test) {
         $test->assertEmpty($context['_POST']);
     });
     $parser(['env' => ['REQUEST_METHOD' => 'POST', 'QUERY_STRING' => '', 'CONTENT_LENGTH' => 27, 'CONTENT_TYPE' => 'foo/bar'], 'stdin' => Keeper::create('abc=def&ghi=jkl&a[]=b&a[]=c')->fopen()]);
 }
 public function getStdin()
 {
     if (null === $this->stream) {
         $this->stream = \AiP\Common\StringStream\Keeper::create($this->body)->fopen();
     }
     return $this->stream;
 }