Skip to content

POST and PUT requests add 201 response by default #490

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

Closed
pezholio opened this issue Aug 2, 2016 · 12 comments
Closed

POST and PUT requests add 201 response by default #490

pezholio opened this issue Aug 2, 2016 · 12 comments

Comments

@pezholio
Copy link
Contributor

pezholio commented Aug 2, 2016

My app actually returns a 202, as the job is queued and a URL to poll is returned, but the generated Swagger docs return a 201 response, as well as my (correct) 202 response. Is this by design? If so, can I override this?

@LeFnord
Copy link
Member

LeFnord commented Aug 2, 2016

hi @pezholio … did I understanding it right, two response objects would be generated in the swagger documentation, one with 201 and a second with 202 as key for POST? Is it also for PUT?

In my understanding of the http status codes, this is the most correct documentation for your described POST behaviour. 202 for the request was accepted, but performed later and 201 for the final success response, the performing was done – resource created.

please can you provide a pseudo code – perfectly as a spec 😉 - so it can be reproduced and documented, thanks

@pezholio
Copy link
Contributor Author

pezholio commented Aug 2, 2016

Hi,

Here's my actual code:

module Octopub
  module Datasets
    class Create < Grape::API

      desc 'Creates a dataset for an authenticated user. Returns a Job URL, which you can then poll to check the creation status of a job', http_codes: [
        { code: 202, message: 'OK', model: Octopub::Entities::Job }
      ]
      params do
        requires :dataset, type: Hash do
          requires :name, type: String, desc: 'The name of the dataset'
          optional :description, type: String, desc: 'A short description of the dataset'
          optional :owner, type: String, desc: 'The Github organisation to publish the dataset to'
          optional :publisher_name, type: String, desc: 'The name of the person / organisation publishing the data'
          optional :publisher_url, type: String, desc: 'The website of the person / organisation publishing the data'
          requires :license, type: String, desc: 'The ID of the dataset\'s license', values: ["cc-by", "cc-by-sa", "cc0", "OGL-UK-3.0", "odc-by", "odc-pddl"]
          optional :frequency, type: String, desc: 'How freqently the dataset is updated', values: ['One-off', 'Annual', 'Every working day', 'Daily', 'Monthly', 'Every minute', 'Every quarter', 'Half yearly', 'Weekly']
          optional :schema, type: String, desc: 'The URL of a JSON table schema to validate against your file(s)'
        end
        requires :files, type: Array do
          requires :title, type: String, desc: 'The name of the file'
          optional :description, type: String, desc: 'A short description of the file'
          requires :file, type: File, desc: 'The actual file'
        end
      end
      post :datasets do
        authenticate!
        process_files(params["files"])
        job = CreateDataset.perform_async(params["dataset"], params["files"], current_user.id)

        status 202
        Octopub::Entities::Job.represent(job)
      end

    end
  end
end

The expected result would be for only one response (a 202) to be generated, but Grape Swagger seems to generate a response for 201 as well, as shown here:

...
{
  "responses": {
    "201": {
      "description": "Creates a dataset for an authenticated user. Returns a Job URL, which you can then poll to check the creation status of a job",
      "schema": {
        "$ref": "#/definitions/Dataset"
      }
    },
    "202": {
      "description": "OK",
      "schema": {
        "$ref": "#/definitions/Job"
      }
    }
  }
}
...

@LeFnord
Copy link
Member

LeFnord commented Aug 2, 2016

ah, I see … http_codes … clever.

what I'm still intersted in is, how looks the definition of Dataset … think it could be possible missing, cause the params didn't have param_type: 'body' and only for this a definition would be generated

@pezholio
Copy link
Contributor Author

pezholio commented Aug 2, 2016

Here you go 😄

module Octopub
  module Entities
    class Dataset < Grape::Entity
      include GrapeRouteHelpers::NamedRouteMatcher

      expose :id
      expose :url do |dataset|
        api_datasets_path(id: dataset.id)
      end

      expose :name
      expose :description
      expose :publisher do
        expose :publisher_name, as: :name
        expose :publisher_url, as: :url
      end
      expose :license do |dataset|
        license = Odlifier::License.define(dataset.license)
        {
          id: license.id,
          title: license.title,
          url: license.url
        }
      end
      expose :frequency
      expose :owner
      expose :url, as: :github_url
      expose :gh_pages_url
      expose :certificate_url
      expose :dataset_files, using: Octopub::Entities::File, as: :files, documentation: { is_array: true }
    end
  end
end

@LeFnord
Copy link
Member

LeFnord commented Aug 2, 2016

no, sorry I mean the swagger definition for Dataset, if they exist

@pezholio
Copy link
Contributor Author

pezholio commented Aug 2, 2016

Ah, gotcha - here you go:

{
  "Dataset": {
    "type": "object",
    "properties": {
      "id": {
        "type": "string"
      },
      "github_url": {
        "type": "string"
      },
      "name": {
        "type": "string"
      },
      "description": {
        "type": "string"
      },
      "publisher": {
        "type": "string"
      },
      "license": {
        "type": "string"
      },
      "frequency": {
        "type": "string"
      },
      "owner": {
        "type": "string"
      },
      "gh_pages_url": {
        "type": "string"
      },
      "certificate_url": {
        "type": "string"
      },
      "files": {
        "type": "array",
        "items": {
          "$ref": "#/definitions/File"
        }
      }
    },
    "description": "Edits a dataset for an authenticated user. Returns a Job URL, which you can then poll to check the creation status of a job"
  }
}

I've put the whole generated Swagger file in a gist if that helps too

@LeFnord
Copy link
Member

LeFnord commented Aug 2, 2016

it looks all fine, but of this #file-swagger-json-L483, here is the bug … please can you provide a spec for only this part

@LeFnord
Copy link
Member

LeFnord commented Aug 2, 2016

… and you should add: consumes: ['application/www_url_encoded'] to the desc method,
but more important is, how can an array of files be translated into a valid swagger, cause this is a intuitive correct representation:

{
  "in": "formData",
  "name": "file[file]",
  "description": "The actual file",
  "type": "array",
  "items": {
    "type": "file"
  },
  "required": false
}

but this isn't valid in swagger :(

@LeFnord
Copy link
Member

LeFnord commented Aug 2, 2016

I opened an issue #748 for it

@pezholio
Copy link
Contributor Author

pezholio commented Aug 3, 2016

Ah, nice. Thanks 👍

I'll try and get a spec written up today for the other issue 😄

@pezholio
Copy link
Contributor Author

pezholio commented Aug 3, 2016

I've added a failing spec here:

pezholio@08f22e7

The result is:

  1) swagger spec v2.0 only returns one response if only one is given
     Failure/Error:
       expect(json['paths']['/delay_thing']['post']['responses']).to eq({
          "202"=>{"description"=>"OK"}
       })

       expected: {"202"=>{"description"=>"OK"}}
            got: {"201"=>{"description"=>"This creates Thing after a delay", "schema"=>{"$ref"=>"#/definitions/Something"}}, "202"=>{"description"=>"OK"}}

       (compared using ==)

       Diff:
       @@ -1,2 +1,3 @@
       +"201" => {"description"=>"This creates Thing after a delay", "schema"=>{"$ref"=>"#/definitions/Something"}},
        "202" => {"description"=>"OK"},

I assume that the issue is because grape-swagger assumes all PUT and POST requests will result in a 201 response by default, and http_codes only adds new responses, or overrides defaults. Is that right?

@pezholio
Copy link
Contributor Author

pezholio commented Aug 5, 2016

Fixed by #491

@pezholio pezholio closed this as completed Aug 5, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants