Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dingo api: DataArraySerializer is not applied #45

Open
gazben opened this issue Jun 4, 2018 · 7 comments
Open

Dingo api: DataArraySerializer is not applied #45

gazben opened this issue Jun 4, 2018 · 7 comments
Assignees
Labels
compatibility Issue about compatibility

Comments

@gazben
Copy link

gazben commented Jun 4, 2018

  1. Tell us your PHP version(php -v)

PHP 7.2.6 (cli) (built: May 26 2018 07:45:18) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies with Xdebug v2.6.0, Copyright (c) 2002-2018, by Derick Rethans

  1. Tell us your Swoole version(php --ri swoole)

swoole support => enabled
Version => 2.2.0
Author => tianfeng.han[email: mikan.tenny@gmail.com]
coroutine => enabled
epoll => enabled
eventfd => enabled
timerfd => enabled
signalfd => enabled
cpu affinity => enabled
spinlock => enabled
rwlock => enabled
async http/websocket client => enabled
Linux Native AIO => enabled
pcre => enabled
zlib => enabled
mutex_timedlock => enabled
pthread_barrier => enabled
futex => enabled

Directive => Local Value => Master Value
swoole.aio_thread_num => 2 => 2
swoole.display_errors => On => On
swoole.use_namespace => On => On
swoole.use_shortname => On => On
swoole.fast_serialize => Off => Off
swoole.unixsock_buffer_size => 8388608 => 8388608
  1. Tell us your Laravel/Lumen version(check composer.json & composer.lock)

Lumen (5.6.3)

  1. Detail description about this issue(error/log)

If you use Dingo api from the second response the data misses the "data" wrapper set in a provider (DataArraySerializer). Even if I re register with the config, the wrapper does not come back.

  1. Give us a reproducible code block and steps

The provider where I set thhe response adapter to DataArraySerializer:

<?php

namespace App\Providers;

use League\Fractal\Manager;
use Dingo\Api\Transformer\Factory;
use Illuminate\Support\ServiceProvider;
use Dingo\Api\Transformer\Adapter\Fractal;
use League\Fractal\Serializer\DataArraySerializer;

class DingoServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    public function boot()
    {
        app(Factory::class)->setAdapter(function ($app) {
            return new Fractal(new Manager, 'include', ',');
        });

        app(Factory::class)->setAdapter(function ($app) {
            $fractal = new Manager;
            $fractal->setSerializer(new DataArraySerializer());

            return new Fractal($fractal);
        });
    }
}

I register this in the bootstrap/app.php: $app->register(App\Providers\DingoServiceProvider::class);
On the first request/response the response is wrapped inside a "data" array. The second response gives exactly the same output, but without the data array wrapping.

First response:

{"data":[{"id":1,"name":"asd, ...}]}

Second response:

[{"id":1,"name":"asd, ...}]

I tried setting the "register_providers" array, and add the boot function lines to the register method.
The problem is, that the cleaning between two requests clears something and I cannot set it back.

@hhxsv5
Copy link
Owner

hhxsv5 commented Jun 5, 2018

OK, I will check it later.

@gazben
Copy link
Author

gazben commented Jun 5, 2018

If anyone has this, the problem is that the Dingo router dispatching is not applied.
My debug messages:

PHP webserver:

production.INFO: DingoServiceProvider@register  
production.INFO: DingoRouter@dispatch--begin  
production.INFO: DingoRouter@routesDispatched:1  
production.INFO: Current route: api/sites  
production.INFO: SiteController@index | Serializer: League\Fractal\Serializer\DataArraySerializer  
production.INFO: DingoRouter@dispatch--end  
production.INFO: DingoRouter@prepareResponse--begin  
production.INFO: DingoHttpResponseFactory@morph  
production.INFO: DingoRouter@prepareResponse--end  

Swoole webserver:

production.INFO: DingoServiceProvider@register  
production.INFO: Current route: api/sites/asd  
production.INFO: SiteController@index | Serializer: League\Fractal\Serializer\DataArraySerializer  

@gazben
Copy link
Author

gazben commented Jun 6, 2018

If you want to re-register the LumenServiceProvider it will get into an infinite loop.
I think the problem is here (but I still don't know how to fix it):


    /**
     * Add the request middleware to the beginning of the middleware stack on the
     * Lumen application instance.
     *
     * @param \ReflectionClass $reflection
     *
     * @return void
     */
    protected function addRequestMiddlewareToBeginning(ReflectionClass $reflection)
    {
        $property = $reflection->getProperty('middleware');
        $property->setAccessible(true);

        $middleware = $property->getValue($this->app);

        array_unshift($middleware, Request::class);

        $property->setValue($this->app, $middleware);
        $property->setAccessible(false);
    }

@hhxsv5
Copy link
Owner

hhxsv5 commented Jun 7, 2018

@gazben Thanks for your feedback, this issue is similar to #28.
So far, I don't have a graceful solution. But I will follow it up.

@hhxsv5 hhxsv5 self-assigned this Jun 7, 2018
@hhxsv5 hhxsv5 added the compatibility Issue about compatibility label Jun 7, 2018
@gazben
Copy link
Author

gazben commented Jun 7, 2018

@hhxsv5 Thank you for, looking into this. I ran out of time to fix this issue, but I wrote the meaningful parts above. If I can come up with something I will let you know.

@gazben
Copy link
Author

gazben commented Jun 13, 2018

The main problem is located the same as in #28 the removeMiddlewareFromApp function in the router adapter is not reset after the first request is served, and will get into the infinite loop because the Request middleware is not removed.

If I just disable the thing:

    protected function removeMiddlewareFromApp()
    {
        if ($this->middlewareRemoved) {
            \Log::info('Middleware already removed!');
            return;
        }

        $this->middlewareRemoved = false; // this is true originally
...

The GET/POST requests will work fine. But the OPTIONS requests are failing with no error message just the 500 status code and no log. So basically the same as #28.
Without logs I'am running out of ideas :(

@gazben
Copy link
Author

gazben commented Jun 13, 2018

@hhxsv5 Can I return a response from a middleware in laravels? The function is called according to the logs, but after it returns, it throws a 500 error.

My cors middleware:

    public function handle(Request $request, Closure $next)
    {
        if($request->isMethod('OPTIONS')) {
            $response = new \Dingo\Api\Http\Response(null);
            $this->setCorsHeaders($request, $response);
            return $response;
        }

        return $next($request);
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compatibility Issue about compatibility
Projects
None yet
Development

No branches or pull requests

2 participants