# Request \> getBody \> getSize Returns null

**URL:** <https://discourse.slimframework.com/t/request-getbody-getsize-returns-null/5753>\
**Category:** Migration\
**Created:** [November 16, 2023, 10:21am UTC](https://discourse.slimframework.com/t/request-getbody-getsize-returns-null/5753 "2023-11-16T10:21:47Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![RedK](https://avatars.discourse-cdn.com/v4/letter/r/7bcc69/32.png) [@RedK](https://discourse.slimframework.com/u/RedK)\
**Post date:** [November 16, 2023, 10:21am UTC](https://discourse.slimframework.com/t/request-getbody-getsize-returns-null/5753/1 "2023-11-16T10:21:47Z")

</div>

Good morning,

I would like to comment something I found, I’m not sure if I missed some steps, or, is something already known. I haven’t found info about this subject.

I’m currently migrating from Slim v3 into v4 using [slim/psr7](https://github.com/slimphp/Slim-Psr7) to create the requests. Before now I was using the getSize function in the PSR7 StreamInterface to measure the requests size, but, when changed to the new version it didn’t work as before, I can’t get the request size from this function, it always return null. After digging a bit the code I have found that the base PHP resource on my requests has changed from previous versions, the library slim/psr7 creates a request with a php://input resource which doesn’t allow the fstat operation done in the Stream class of the same library, so, it can’t get the size from the resource. Before now it was php://temp w+ which allows the fstat function.

[slim/psr7 Body creation](https://github.com/slimphp/Slim-Psr7/blob/master/src/Factory/ServerRequestFactory.php#L91)  
[slim/psr7 Stream getSize](https://github.com/slimphp/Slim-Psr7/blob/master/src/Factory/ServerRequestFactory.php#L91)

POC

```auto
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Factory\AppFactory;

require __DIR__. '/../vendor/autoload.php';

$app = AppFactory::create();

$app->post('/hello/{name}', function (Request $request, Response $response, array $args) {
    $name = $args['name'];

    $result = $request->getBody()->getSize() === null
        ? 'getSize returns null'
        : 'getSize returns ' . $request->getBody()->getSize();

    $response->getBody()->write($result);

    return $response;
});

$app->run();

```

These are the dependencies

```auto
{
    "require": {
        "slim/slim": "^4.12",
        "slim/psr7": "^1.6"
    }
}

```

Finally, I call this endpoint with

```auto
POST http://localhost:8010/hello/test
content-type: application/json
Accept: text/plain

{"test": "test"}

```

Thank you in advance!

---

<div class="post-metadata">

**Author:** ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)\
**Post date:** [November 16, 2023, 12:40pm UTC](https://discourse.slimframework.com/t/request-getbody-getsize-returns-null/5753/2 "2023-11-16T12:40:23Z")

</div>

I just have tested this behavior also with other PSR-7 implementations, such as Nyholm and I get the same result (null). Nyholm also uses `php://input` within the `ServerRequestCreator::fromGlobals` method.

Indeed, it looks like a `php://input` resource / stream does not provide support for `fstat`. See here:

- [Online PHP editor | output for MARG2](https://3v4l.org/MARG2)

I assume that all PSR-7 implementations are affected by this bug, and I’m a bit confused  
about it.

- [Request getSize() returns null for php://input stream · Issue #254 · Nyholm/psr7 · GitHub](https://github.com/Nyholm/psr7/issues/254)

---

<div class="post-metadata">

**Author:** ![RedK](https://avatars.discourse-cdn.com/v4/letter/r/7bcc69/32.png) [@RedK](https://discourse.slimframework.com/u/RedK)\
**Post date:** [November 16, 2023, 3:24pm UTC](https://discourse.slimframework.com/t/request-getbody-getsize-returns-null/5753/3 "2023-11-16T15:24:14Z")

</div>

Hello,

Thanks for your quick response, I have tried Guzzle implementation also, and it still uses the php://temp writable resource, Laminas uses php://input, it depends on their implementation.

By now, my intention is to continue with the Slim/Psr-7 implementation, I was thinking about using the Content-Length header, I suppose it will be mostly the same.

---

<div class="post-metadata">

**Author:** ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)\
**Post date:** [November 16, 2023, 4:11pm UTC](https://discourse.slimframework.com/t/request-getbody-getsize-returns-null/5753/4 "2023-11-16T16:11:52Z")

</div>

You can also try this workaround:

```php
$realSize = strlen((string)$request->getBody());

```

---

<div class="post-metadata">

**Author:** ![RedK](https://avatars.discourse-cdn.com/v4/letter/r/7bcc69/32.png) [@RedK](https://discourse.slimframework.com/u/RedK)\
**Post date:** [November 17, 2023, 11:19am UTC](https://discourse.slimframework.com/t/request-getbody-getsize-returns-null/5753/5 "2023-11-17T11:19:22Z")

</div>

Hi,

Sorry I can’t answer until now. It was my first thought, but, the request body is being read into memory, on large requests, depending on the usage it can duplicate the memory needed.

Thank you so much for the proposal, have a nice weekend!

---

<div class="post-metadata">

**Author:** ![odan](https://avatars.discourse-cdn.com/v4/letter/o/9de053/32.png) [@odan](https://discourse.slimframework.com/u/odan)\
**Post date:** [November 17, 2023, 2:17pm UTC](https://discourse.slimframework.com/t/request-getbody-getsize-returns-null/5753/6 "2023-11-17T14:17:01Z")

</div>

Indeed, this is not the best solution, because it reads the request into memory.  
Another, more memory efficient way would be to read the last position of the stream:

```php
$size = $request->getBody()->tell();

```

I just found out, that when you send POST request as `multipart/form-data` the input stream length is always null, because PHP itself has already processed that stream to populate the $\_POST variable. Just in this case, the request size would be null anyway.

---

<div class="post-metadata">

**Author:** ![RedK](https://avatars.discourse-cdn.com/v4/letter/r/7bcc69/32.png) [@RedK](https://discourse.slimframework.com/u/RedK)\
**Post date:** [November 20, 2023, 5:04pm UTC](https://discourse.slimframework.com/t/request-getbody-getsize-returns-null/5753/7 "2023-11-20T17:04:39Z")

</div>

Hi,

Thanks!, something like this can measure this kind of resource and leave it as it was… It works with php://input

```auto
    if($request->getBody()->isSeekable()) {
        $currentPosition = $request->getBody()->tell();
        $request->getBody()->seek(0, SEEK_END);
        $sizeInBytes = $request->getBody()->tell();
        $request->getBody()->seek($currentPosition);
    }

```

I have edited the post, to find the last position is 0, SEEK\_END, if the post body is empty, seek with position -1 will fail

---

<div class="post-metadata">

**Author:** ![RedK](https://avatars.discourse-cdn.com/v4/letter/r/7bcc69/32.png) [@RedK](https://discourse.slimframework.com/u/RedK)\
**Post date:** [November 21, 2023, 12:12am UTC](https://discourse.slimframework.com/t/request-getbody-getsize-returns-null/5753/8 "2023-11-21T00:12:50Z")

</div>

I havent tested everything already, but this could be an alternative way to get the size on the Stream class…

```auto
    public function getSize(): ?int
    {
        if ($this->stream && !$this->size && $this->isSeekable() && !$this->isPipe()) {
            $currentPosition = ftell($this->stream);
            fseek($this->stream, 0, SEEK_END);
            $endPosition = ftell($this->stream);
            fseek($this->stream, $currentPosition, SEEK_SET);
            if (false !== $endPosition) {
                $this->size = $endPosition;
            }
        }
        return $this->size;
    }

```
