Closed vlavlad closed 5 years ago
Hi! Glad you're finding the package useful.
This potentially looks like a bug, but I'd need to investigate to confirm. I haven't actually tried this on an update request, which is maybe why it is working for create but not update. I'll take a look.
@lindyhopchris Thanks, please let me know if you find the way to move on this issue.
Confirmed as a bug as I've been able to reproduce in a test.
@vlavlad I believe I've fixed this in 32b781d4482022221547f361d1056bea3d8cc4ea
You can give it a go by doing:
$ composer require cloudcreativity/laravel-json-api:dev-develop
For the create request, you will have added some code to your create
methods in your Validators and Adapter class. For the update request, you'll have to do the same to the update
methods on those classes.
Let me know how you get on and whether this solves the problem for you.
@lindyhopchris Thanks for quick feedback. I have a new issue. I can't achieve the update method in Adapter for multipart/form-data content type. Probably the reason is validateDocument method. Looks like it's waiting for the document as a JSON object with the type and attributes. But in the way I use updating via multipart/form-data, I can't pass the JSON object for the resource because we use form data to send data to the server rather than JSON.
Log:
[2019-06-17 17:34:48] local.ERROR: Expecting a resource type. {"userId":1,"email":"vfa@fasf.com","exception":"[object] (InvalidArgumentException(code: 0): Expecting a resource type. at /var/www/dev-local-server/vendor/cloudcreativity/laravel-json-api/src/Document/ResourceObject.php:79) [stacktrace]
"}
You'd need to change the update
method on your validators class, in the same way that you must have changed the create
method on your validators to get the create requests working.
You can see an example of that here: https://github.com/cloudcreativity/laravel-json-api/blob/develop/tests/dummy/app/JsonApi/Avatars/Validators.php
Note you'll also need to make changes to your adapter as well, along the lines of this: https://github.com/cloudcreativity/laravel-json-api/blob/develop/tests/dummy/app/JsonApi/Avatars/Adapter.php#L62-L80
Let me know whether or not you've made those changes and are still encountering problems.
@vlavlad i think your issue is related to the method request you are using. PHP simply does not process the incoming data for PUT, PATCH or DELETE requests with multipart/form-data content type. https://bugs.php.net/bug.php?id=55815
You could try this class https://gist.github.com/devmycloud/df28012101fbc55d8de1737762b70348 to parse the data sent in your request. I would prefer a middleware approache to do that. It's up to you.
Laravel implements an other solution to this, but i think this is not revelant in our case when using this package. https://laravel.com/docs/5.5/routing#form-method-spoofing
Edit: Another thing you should know. If you make a PATCH request (using one of the above solutions to parse data) with multipart content type and uploading a file you can't use validator to the field of the file. Since the file will not pass the PHP is_uploaded_file() test you will receive an error "The [field] failed to upload." https://github.com/illuminatech/multipart-middleware
Edit2: Actually, the best way i found to make a PATCH request to update a resource with multipart/form-data content type, is to make a POST request with a field "_method" which has value "PATCH". This way, all the inputs are correctly parsed and validation still working, even for files. In your decoder you should return "$request->except('_method')" if you have other fields than files.
@freddy38510 thanks for this - yes I totally agree that you'd probably need to use method spoofing for this.
@vlavlad any update on how you're getting on? I've now released this in 1.2.0
- so keen to work out if the issue can be closed or if more fixes are required.
Hi @lindyhopchris, Sorry for the delay, I tried out that it works correctly for me. I didn't find any issue and did the implementation with update feature. Thank you.
@freddy38510 I read about it before. For me, sending of the POST request with _method="PATCH" works. Thank you too.
I think that the issue can be closed.
Great, glad to hear this is solved!
Hi, thanks for this very useful package for Laravel.
I developed the ContentNegotiator for mine resource as you represented it here. It's working correctly for multipart/form-data in uploading the image. But I've faced with the issue when I'm sending the PATCH request to update the image /api/v1/storage-images/42 The API throws the error "Expecting request to contain a JSON API document." I checked that is likely related to the difference between the validateDocument method in UpdateResource and classes CreateResource.
1) Is there any way to move on this issue or updating must work only with "Content-Type: application/vnd.api+json"?
2) Does documentation has an example of an implementation for updating the resource with multipart/form-data content-type?
Here is the call stack:
[2019-06-16
08:37:02] local.ERROR: Expecting JSON API document to be an object. {"userId":1,"email":"dasdas@ddd.com","exception":"[object] (CloudCreativity\LaravelJsonApi\Exceptions\InvalidArgumentException(code: 0): Expecting JSON API document to be an object. at /var/www/dev-local-server/vendor/cloudcreativity/laravel-json-api/src/Validation/Spec/AbstractValidator.php:75) [stacktrace]0 /var/www/dev-local-server/vendor/cloudcreativity/laravel-json-api/src/Validation/Spec/CreateResourceValidator.php(67): CloudCreativity\LaravelJsonApi\Validation\Spec\AbstractValidator->__construct(Object(CloudCreativity\LaravelJsonApi\Store\Store), Object(CloudCreativity\LaravelJsonApi\Validation\ErrorTranslator), NULL)
1 /var/www/dev-local-server/vendor/cloudcreativity/laravel-json-api/src/Validation/Spec/UpdateResourceValidator.php(59): CloudCreativity\LaravelJsonApi\Validation\Spec\CreateResourceValidator->__construct(Object(CloudCreativity\LaravelJsonApi\Store\Store), Object(CloudCreativity\LaravelJsonApi\Validation\ErrorTranslator), NULL, 'storage-images')
2 /var/www/dev-local-server/vendor/cloudcreativity/laravel-json-api/src/Factories/Factory.php(390): CloudCreativity\LaravelJsonApi\Validation\Spec\UpdateResourceValidator->__construct(Object(CloudCreativity\LaravelJsonApi\Store\Store), Object(CloudCreativity\LaravelJsonApi\Validation\ErrorTranslator), NULL, 'storage-images', '42')
3 /var/www/dev-local-server/vendor/cloudcreativity/laravel-json-api/src/Http/Requests/UpdateResource.php(85): CloudCreativity\LaravelJsonApi\Factories\Factory->createExistingResourceDocumentValidator(NULL, 'storage-images', '42')
4 /var/www/dev-local-server/vendor/cloudcreativity/laravel-json-api/src/Http/Requests/ValidatedRequest.php(266): CloudCreativity\LaravelJsonApi\Http\Requests\UpdateResource->validateDocument()
5 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Foundation/Providers/FormRequestServiceProvider.php(30): CloudCreativity\LaravelJsonApi\Http\Requests\ValidatedRequest->validateResolved()
6 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Container/Container.php(1069): Illuminate\Foundation\Providers\FormRequestServiceProvider->Illuminate\Foundation\Providers\{closure}(Object(CloudCreativity\LaravelJsonApi\Http\Requests\UpdateResource), Object(Illuminate\Foundation\Application))
7 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Container/Container.php(1033): Illuminate\Container\Container->fireCallbackArray(Object(CloudCreativity\LaravelJsonApi\Http\Requests\UpdateResource), Array)
8 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Container/Container.php(1018): Illuminate\Container\Container->fireAfterResolvingCallbacks('CloudCreativity...', Object(CloudCreativity\LaravelJsonApi\Http\Requests\UpdateResource))
9 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Container/Container.php(677): Illuminate\Container\Container->fireResolvingCallbacks('CloudCreativity...', Object(CloudCreativity\LaravelJsonApi\Http\Requests\UpdateResource))
10 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Container/Container.php(609): Illuminate\Container\Container->resolve('CloudCreativity...', Array)
11 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Foundation/Application.php(759): Illuminate\Container\Container->make('CloudCreativity...', Array)
12 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/RouteDependencyResolverTrait.php(79): Illuminate\Foundation\Application->make('CloudCreativity...')
13 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/RouteDependencyResolverTrait.php(46): Illuminate\Routing\ControllerDispatcher->transformDependency(Object(ReflectionParameter), Array)
14 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/RouteDependencyResolverTrait.php(27): Illuminate\Routing\ControllerDispatcher->resolveMethodDependencies(Array, Object(ReflectionMethod))
15 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/ControllerDispatcher.php(41): Illuminate\Routing\ControllerDispatcher->resolveClassMethodDependencies(Array, Object(CloudCreativity\LaravelJsonApi\Http\Controllers\JsonApiController), 'update')
16 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Route.php(219): Illuminate\Routing\ControllerDispatcher->dispatch(Object(Illuminate\Routing\Route), Object(CloudCreativity\LaravelJsonApi\Http\Controllers\JsonApiController), 'update')
17 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Route.php(176): Illuminate\Routing\Route->runController()
18 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Router.php(682): Illuminate\Routing\Route->run()
19 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(30): Illuminate\Routing\Router->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
20 /var/www/dev-local-server/vendor/cloudcreativity/laravel-json-api/src/Http/Middleware/NegotiateContent.php(102): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
21 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): CloudCreativity\LaravelJsonApi\Http\Middleware\NegotiateContent->handle(Object(Illuminate\Http\Request), Object(Closure))
22 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
23 /var/www/dev-local-server/vendor/cloudcreativity/laravel-json-api/src/Http/Middleware/Authorize.php(87): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
24 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): CloudCreativity\LaravelJsonApi\Http\Middleware\Authorize->handle(Object(Illuminate\Http\Request), Object(Closure), Object(App\JsonApi\DefaultAuthorizer))
25 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
26 /var/www/dev-local-server/vendor/cloudcreativity/laravel-json-api/src/Http/Middleware/BootJsonApi.php(78): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
27 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): CloudCreativity\LaravelJsonApi\Http\Middleware\BootJsonApi->handle(Object(Illuminate\Http\Request), Object(Closure), 'default')
28 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
29 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Middleware/SubstituteBindings.php(41): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
30 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\Routing\Middleware\SubstituteBindings->handle(Object(Illuminate\Http\Request), Object(Closure))
31 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
32 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php(43): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
33 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\Auth\Middleware\Authenticate->handle(Object(Illuminate\Http\Request), Object(Closure), 'api')
34 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
35 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Middleware/ThrottleRequests.php(58): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
36 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\Routing\Middleware\ThrottleRequests->handle(Object(Illuminate\Http\Request), Object(Closure), 60, '1')
37 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
38 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(104): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
39 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Router.php(684): Illuminate\Pipeline\Pipeline->then(Object(Closure))
40 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Router.php(659): Illuminate\Routing\Router->runRouteWithinStack(Object(Illuminate\Routing\Route), Object(Illuminate\Http\Request))
41 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Router.php(625): Illuminate\Routing\Router->runRoute(Object(Illuminate\Http\Request), Object(Illuminate\Routing\Route))
42 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Router.php(614): Illuminate\Routing\Router->dispatchToRoute(Object(Illuminate\Http\Request))
43 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(176): Illuminate\Routing\Router->dispatch(Object(Illuminate\Http\Request))
44 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(30): Illuminate\Foundation\Http\Kernel->Illuminate\Foundation\Http\{closure}(Object(Illuminate\Http\Request))
45 /var/www/dev-local-server/vendor/fideloper/proxy/src/TrustProxies.php(57): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
46 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Fideloper\Proxy\TrustProxies->handle(Object(Illuminate\Http\Request), Object(Closure))
47 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
48 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(31): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
49 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))
50 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
51 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/TransformsRequest.php(31): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
52 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\Foundation\Http\Middleware\TransformsRequest->handle(Object(Illuminate\Http\Request), Object(Closure))
53 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
54 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php(27): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
55 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\Foundation\Http\Middleware\ValidatePostSize->handle(Object(Illuminate\Http\Request), Object(Closure))
56 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
57 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/CheckForMaintenanceMode.php(62): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
58 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(163): Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode->handle(Object(Illuminate\Http\Request), Object(Closure))
59 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Routing/Pipeline.php(53): Illuminate\Pipeline\Pipeline->Illuminate\Pipeline\{closure}(Object(Illuminate\Http\Request))
60 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php(104): Illuminate\Routing\Pipeline->Illuminate\Routing\{closure}(Object(Illuminate\Http\Request))
61 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(151): Illuminate\Pipeline\Pipeline->then(Object(Closure))
62 /var/www/dev-local-server/vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php(116): Illuminate\Foundation\Http\Kernel->sendRequestThroughRouter(Object(Illuminate\Http\Request))
63 /var/www/dev-local-server/public/index.php(55): Illuminate\Foundation\Http\Kernel->handle(Object(Illuminate\Http\Request))
64 {main}
"} `