10

I'm use L5-Swagger 5.7.* package (wrapper of Swagger-php) and tried describe Laravel REST API. So, my code like this:

/**
 * @OA\Post(path="/subscribers",
 *     @OA\RequestBody(
 *         @OA\MediaType(
 *            mediaType="application/json",
 *            @OA\Schema(
 *               type="object",
 *               @OA\Property(property="email", type="string")
 *            )
 *        )
 *    ),
 *   @OA\Response(response=201,description="Successful created"),
 *   @OA\Response(response=422, description="Error: Unprocessable Entity")
 * )
 */
public function publicStore(SaveSubscriber $request)
{
    $subscriber = Subscriber::create($request->all());
    return new SubscriberResource($subscriber);
}

But when I try send request via swagger panel I get code:

curl -X POST "https://examile.com/api/subscribers" -H "accept: */*" -H "Content-Type: application/json" -H "X-CSRF-TOKEN: " -d "{\"email\":\"bademail\"}"

As you can see, accept is not application/json and Laravel doesn't identify this as an AJAX request. So, when I send wrong data and expect to get 422 with errors in real I get 200 code with errors in "session". Request (XHR) through the swagger panel is also processed incorrectly, CURL code just for clarity.

Also, I found that in the previous version was used something like:

* @SWG\Post(
*     ...
*     consumes={"multipart/form-data"},
*     produces={"text/plain, application/json"},
*     ...)

But now it's already out of date.

So, how get 422 code without redirect if validation fails? Or maybe add 'XMLHttpRequest' header? What is the best thing to do here?

Nikolay Votintsev
  • 452
  • 1
  • 6
  • 14
  • 1
    if you want laravel to identify it as a json request you need to specify that you're accepting json above anything else i.e. `accept: application/json, */*`. From the server's perspective there's no such thing as "an AJAX request" . There's nothing fundamentally special about requests that JavaScript makes. JQuery will add an `X-Requested-With: XMLHttpRequest` header to give a hint to the server that it's AJAX but other libraries don't do this because there shouldn't be a reason to. – apokryfos Nov 06 '18 at 08:38
  • My question is how to make the Swagger panel send a request to the Laravel so that it returns JSON without redirect. – Nikolay Votintsev Nov 06 '18 at 08:55
  • Check https://swagger.io/docs/specification/describing-responses/ there should be a way to specify that your response is json so that *should* make the client try to accept that response type – apokryfos Nov 06 '18 at 09:54
  • What about `consumes={"application/json"}`? – Travis Britz Nov 06 '18 at 10:03
  • 1
    @TravisBritz Consumes and Produces fields was removed from OpenAPI specification – Nikolay Votintsev Nov 06 '18 at 10:10
  • Maybe @OA\MediaType needs to be inside Response instead of RequestBody? – Travis Britz Nov 06 '18 at 10:25

2 Answers2

13

The response(s) didn't specify a mimetype.

 @OA\Response(response=201, description="Successful created"),

If you specify a json response, swagger-ui will send an Accept: application/json header.

PS. Because json is so common swagger-php has a @OA\JsonContent shorthand, this works for the response:

@OA\Response(response=201, description="Successful created", @OA\JsonContent()),

and the requestbody:

@OA\RequestBody(
  @OA\JsonContent(
    type="object",
    @OA\Property(property="email", type="string")
  )
),
Bob Fanger
  • 28,949
  • 7
  • 62
  • 78
-1

you can use this, i use Request class, on the file Request

use Illuminate\Contracts\Validation\Validator;
use Illuminate\Http\Exceptions\HttpResponseException;
    public function rules()
    {
    return [
        'currentPassword' => 'required',
        'newPassword' => 'required|same:confirmPassword',
        'confirmPassword' => 'required'
    ];
    }
    protected function failedValidation(Validator $validator)
    {
        throw new HttpResponseException(response()->json([
            'errors' => $validator->errors(),
            'status' => true
        ], 422));
    }