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

Delete method is not working #993

Closed
hyyan opened this issue Mar 16, 2015 · 15 comments
Closed

Delete method is not working #993

hyyan opened this issue Mar 16, 2015 · 15 comments
Labels

Comments

@hyyan
Copy link

hyyan commented Mar 16, 2015

Hey , thanks for the great work guys , it is impressive

I am trying to build a simple task api just to learn , and everything is working great , except for the delete request , the form validation is passing in html but it is not in json or xml and I keep getting the 400 code error (Bad Request)

I didn't post this in Stack Overflow cause I think it is a bug ,

Note : I am using the master brunch

Here's my bundle config ;

fos_rest:
    allowed_methods_listener: true
    param_fetcher_listener: true
    view:
        view_response_listener: 'force'
        formats:
            xml:  true
            json: true
        templating_formats:
            html: true
    format_listener:
        rules:
            - { path: ^/, priorities: [ html, json, xml ], fallback_format: ~, prefer_extension: true }
    allowed_methods_listener: true
    body_listener: true
    disable_csrf_role: ROLE_API

And here's my controller methods :

  /**
     * Creates a form to delete a Task entity by id.
     *
     * @param mixed $id The entity id
     *
     * @return \Symfony\Component\Form\Form The form
     */
    private function createDeleteForm($id)
    {
        return $this->createFormBuilder(null, array('csrf_protection' => false))
                        ->setAction($this->generateUrl('tasks_delete', array('id' => $id)))
                        ->setMethod('DELETE')
                        ->add('submit', 'submit', array('label' => 'Delete'))
                        ->getForm()
        ;
    }

  /**
     * Deletes a Task entity.
     *
     * @ApiDoc(
     *   resource = true,
     *   section= "Tasks",
     *   description = "Delete existing entity.",
     *   requirements={
     *      {
     *          "name"="id",
     *          "dataType"="integer",
     *          "requirement"="\d+",
     *          "description"="the task ID"
     *      }
     *   },
     *   statusCodes = {
     *     200 = "Returned when successful",
     *     404 = "Returned when entity does not exists",
     *     400 = "Returned when form can not be submitted",
     *   }
     * )
     */
    public function deleteAction(Request $request, $id)
    {

        $form = $this->createDeleteForm($id);
        $form->handleRequest($request);

        $code = 400;
        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $entity = $em->getRepository('AppBundle:Task')->getTaskById($id);

            if (!$entity) {
                throw $this->createNotFoundException('Unable to find Task entity.');
            }

            $em->remove($entity);
            $em->flush();

            $code = 204;
        }

        $view = $this->routeRedirectView('tasks', array(), $code);
        return $this->handleView($view);
    }

And finally the route:

tasks_delete:
    path:     /{id}
    defaults: { _controller: "AppBundle:Task:delete" , format: ~ }
    requirements: { _method: DELETE , id: \d+}

Any idea will be helpful , thanks in advance

@lsmith77
Copy link
Member

did you debug a bit what is going on? I guess the form is not considered to be valid? what data is in the $request->request in both cases? I assume there is some difference there that is causing the issue.

@hyyan
Copy link
Author

hyyan commented Mar 16, 2015

@lsmith77 thanks for replay , I have been debugging this for the last 3 days but with no luck which made think it is a bug .

The $request->request is empty ParameterBag when I use json or xml and contains the following when I use HTML

object(Symfony\Component\HttpFoundation\ParameterBag)[8]
  protected 'parameters' => 
    array (size=2)
      '_method' => string 'DELETE' (length=6)
      'form' => 
        array (size=1)
          'submit' => string '' (length=0)

@lsmith77
Copy link
Member

do you have the BodyListener activated?

@lsmith77
Copy link
Member

ah yes you do .. can you pastebin the body of the request you send for DELETE with json/xml?

@hyyan
Copy link
Author

hyyan commented Mar 16, 2015

@lsmith77 Yes the body listener is activated .
I am using curl to test the api , and I am sending an empty request body ,I mean no need to send anything.

Here is my curl command I am using

$ curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X
DELETE symfony-rest.localhost.com/web/app_dev.php/tasks/3
HTTP/1.1 400 Bad Request
Date: Mon, 16 Mar 2015 16:30:47 GMT
Server: Apache/2.2.22 (Win64) PHP/5.4.3
X-Powered-By: PHP/5.4.3
Cache-Control: no-cache
Location: http://symfony-rest.localhost.com/web/app_dev.php/tasks/
Allow: GET, PUT, DELETE
X-Debug-Token: 1adc07
X-Debug-Token-Link: /web/app_dev.php/_profiler/1adc07
Content-Length: 0
Connection: close
Content-Type: application/json

@lsmith77
Copy link
Member

but I am right that in the xml/json case the $form->isValid() check returns false? then the issue is that the form layer isn't happy.

/cc @webmozart

@lsmith77
Copy link
Member

ping

@hyyan
Copy link
Author

hyyan commented Mar 22, 2015

@lsmith77 Sorry for taking so long to answer , it is work , sorry again

You were write the form layer is not happy in xml/json case , I have edited my curl command to become like this:

$ curl -i -H "Accept: application/json" -H "Content-Type: application/json" -X
DELETE symfony-rest.localhost.com/web/app_dev.php/tasks/3 -d '{"form":""}'
HTTP/1.1   204 
Date: Mon, 16 Mar 2015 16:30:47 GMT
Server: Apache/2.2.22 (Win64) PHP/5.4.3
X-Powered-By: PHP/5.4.3
Cache-Control: no-cache
Location: http://symfony-rest.localhost.com/web/app_dev.php/tasks/
Allow: GET, PUT, DELETE
X-Debug-Token: 1adc07
X-Debug-Token-Link: /web/app_dev.php/_profiler/1adc07
Content-Length: 0
Connection: close
Content-Type: application/json

as you can see from the response the form method $fomr->isValid() is happy when I passed the form name in the request body , so it is something about the form name . so I tried to change the form name to null so I can execute the request without passing the form name in the request body , but that did not work. I am not sure how to solve this with the DELETE request

If you think this must not be discussed here , feel free to close the issue , and I will try Stackoverflow to get this right

Thanks for being patient with me 😄

@tystr
Copy link
Contributor

tystr commented Apr 15, 2015

@hyyan Why do you need to use a form when deleting a resource?

@hyyan
Copy link
Author

hyyan commented Apr 15, 2015

@tystr Because I am serving the HTML view from same controller which needs a form to perform delete request ? Is that wrong ?

@stof
Copy link
Member

stof commented Apr 18, 2015

@hyyan if you used a form with a non-empty root name, it indeed must appear in the request, otherwise it won't be considered as submitted. If you want to avoid this, you could use an empty form name:

$form = $this->get('form.factory')->createNamed('', $type, $data);

@hyyan
Copy link
Author

hyyan commented Apr 18, 2015

@stof Thanks for replay , I have tried this as you suggest , but still the same , working for HTML but it is not for json/xml

$this->get('form.factory')->createNamed(
                     ''
                    , 'form'
                    , array(

                    )
                    , array(
                        'action' => $this->generateUrl('tasks_delete', array('id' => $id)),
                        'method' => 'DELETE' ,
                        'csrf_protection' => false,
                        'allow_extra_fields' => true,

                        )
                    )
                    ->add('submit', 'submit', array('label' => 'Delete'))

@lsmith77 lsmith77 added the Form label Jul 10, 2015
@lsmith77 lsmith77 modified the milestones: 1.8, 1.7 Jul 10, 2015
@lsmith77 lsmith77 modified the milestones: 1.7, 1.8 Aug 9, 2015
@lsmith77 lsmith77 modified the milestones: 1.8, 2.0 Aug 29, 2015
@lsmith77 lsmith77 modified the milestone: 2.0 Nov 10, 2015
@bpolaszek
Copy link

Hello,

I'm running on exactly the same issue here.
I have the same controller serving HTML and JSON.

When using a browser and HTML, the form fakes the DELETE method and sends a POST request with an hidden input, thus validating the form. When using Postman or curl with the real DELETE method, the request body is empty, preventing the form from being submitted.

Though I guess Friends of Symfony will find a turnaround about this (I hope so!), I'm wondering if this issue shouldn't be related to the Symfony Form Component itself?

@GuilhemN
Copy link
Member

@hyyan @bpolaszek could you create a fork of the symfony-rest-edition reproducing this issue ?

@xabbuh
Copy link
Member

xabbuh commented Feb 15, 2016

@hyyan @bpolaszek You need to make sure that the Content-Type header is application/x-www-form-urlencoded. Otherwise, the HttpFoundation component would not properly populate the request parameters for DELETE requests: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpFoundation/Request.php#L282-L287

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

No branches or pull requests

7 participants