Can't define my API via Swagger; is this bad design? - api

One of our APIs accept certificates from our users. With current design, users dump raw certificate data in the payload and make a POST request with the content type set to application/x-pkcs12.
So essentially, our API is accepting raw bytes of a file in the body of the request.
If I try to define this API via Swagger, then I can't do so. Because, correct me if I'm wrong, the parameter of this operation will have to be 'in' body and the 'type' of this parameter would have to be file.
Swagger requires all body parameters to have the Schema object necessarily, and all parameters of type file should have 'in' value set to formData. Both of these requirements are contradictory to our case.
So my question is, is this Swagger's limitation? Or is this just bad API design, and should we be structuring/designing our API in some other way?
I'm fairly new to the world of APIs so I'm not sure which of the cases it is.
Thanks in advance.

I believe this can still be done. Your body parameter schema should have type []byte. When you call the API, your parameter value should be a base-64 encoded string of the file contents. This is similar to how you would send the contents of a binary .jpg file in the body of a request.

Swagger 2.0 allows parameters of type file. This seems to fit your use case.
parameters:
- name: cert
in: formData
description: The certificate
required: true
type: file

Your scenario is supported in OpenAPI 3.0. The previous version, OpenAPI/Swagger 2.0, allowed file uploads using multipart/form-data requests only, but 3.0 supports uploading raw files as well.
paths:
/cert:
post:
requestBody:
required: true
content:
application/x-pkcs12:
schema:
type: string
format: binary
responses:
...
More info: File Upload

Related

How REST API works?

enter image description here
What this picture actually describes?
I have a confusion, which is, whenever we are sending a GET request to the server via a API,
are we sending it in JSON format ?Or, in HTML or any simple Text format?
On the other hand, whenever the API is sending a request (HTTP verb actually) to the server, is it using HTTP format? and the server also returns a response in HTTP format or in JSON format?
I know this question is very silly....but I am very new in API world.
The picture is not accurate, the server sends a response and the MIME type does not matter, it can be even RDF n-triples or images depending on the type of the service and what it supports. The protocol is always HTTP, though theoretically it is possible to use a different protocol. REST has some mandatory constraints, you can read about them in the Fielding dissertation or I wrote about them here and here.

Designing an API OpenAPI 3.0 - header parameter Content type are ignored

This question is really a followup to an earlier question here
what I am trying to do is force the consumer of my api to ONLY send Content-Type as application/json
My environment is : Mule 4.4 runtime ( on prem , no usage of Anypoint Platform )
I am defining the spec in OAS 3.0 and am using swagger editor to create and edit specification
I have the following defined :
/user:
post:
parameters:
- in: header
name: Content-Type
required: true
schema:
type: string
enum:
- application/json
and I can see a warning:
Header Parameters named 'Content-type' are ignored. The values for the 'Content-Type' header are defined by 'RequestBody.content.media-type
Tried googling and found one link here But it simply states :
Make sure that you do not use the restricted values as header parameter names.
which really does not explain of how to enforce this criteria ?
As a side note - if I copy paste the same api spec in Design centre ( Anypoint platform ) it does not complain and infact mule runtime correctly validates and rejects requests that do not have application/json in content-type
Thanks
In OpenAPI (or even RAML) we don't treat the Content-Type header as a generic HTTP header. This applies to both requests and responses. As part of the specification you can define the media types for each request. The implementation will take care of processing it correctly and validate the right Content-Type header is used at execution time. Since you are trying to set it manually the implementation is giving you an expected warning.
Example:
paths:
/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX:
post:
requestBody:
content:
application/json:

Can I trust the .Length property on IFormFile in ASP.NET Core?

We have an API endpoint that allows users to upload images; one of its parameters is an IFormFileCollection.
We'd like to validate the file size to make sure that the endpoint isn't being abused so I'm checking the Length property of each IFormFile, but I don't know whether I can trust this property or not, i.e. does this come from the request? Is it considered 'input', much like Content-Length is?
If you have an IFormFileCollection parameter, and you send data using a "form-data" content-type in the request, that parameter will be bound by a whole lot of plumbing that's hard to dig through online, but if you just debug the action method that accepts the IFormFileCollection (or any collection of IFormFile, really)and inspect the collection, you'll see that the uploaded files will already have been saved on your server's disk.
That's because the entire multi-part form request's body has to be read to determine how many files there are, if any, and form parameters, and validate the request body's format while it's reading it.
So yes, by the time your code ends up there, you can trust IFormFile.Length, because it's pointing to a local file that exists and contains that many bytes.
You're too late there to reject the request though, as it's been already entirely read. You better fix rate and size limits lower in the stack, like on the web server or firewall.
Content-Length is compressed number of bytes of data in the body , it is not reliable since it may include extra data ,for example , you are sending multipart request . Just use the IFormFile.length for features like calculation or validation .

Karate support for validating pipe separated response and avro format

We have webservice where we send the request body as binary (avro format) through postman and have a pipe separated response. We were able send this request using karate and get a valid response but made observation that by default karate sets the content type as ‘application/octect-stream’ where as we expect content type to be application/json. Is there a reason why karate uses application/octect-stream for avro format?
Also for pipe separated response does karate support any default validations similar to json/xml validations?
For e.g : if the sample response is like
|PDT|! PRODUCT!|Item1|!SKUID!|sku123a|!DETAILS!|Itemname|itemnumber|price|!FINISH!|
Karate tries to guess the content-type but clearly needs help here, please refer to the documentation for the header keyword, and you can set (over-ride) it easily: https://github.com/intuit/karate#header
For the second question, I suggest you write a simple utility to convert that response to JSON and then you will be able to do all kinds of awesome validations in Karate. This example should be self-explanatory: dogs.feature

REST api request method input parameters

i've been researching/creating a REST api, in the backbone.js to php context.
i understand the concept of HTTP verbs and when they should be used
GET - select
POST - create
PUT - update
DELETE - delete
i also understand the concept of passing an identifier as a semantic url, e.g.
GET http://api/users/123
DELETE http://api/users/123
in these cases the "123" is the id the business logic will use to get/delete a user.
but what about the POST and PUT contexts? when sending a request to
PUT http://api/users/123
the api will update user id 123 with the supplied parameters, here's where my question arises.
i would assume the input parameters to update with would be sent as PUT parameters. in php syntax this is represented as: file_get_contents('php://input') (this is the same for delete requests.)
when testing this via backbone.js it works perfectly.
but when i try and create a new element with
POST http://api/users/
i would assume the input values would sent as POST parameters/ in php syntax this is represented as $_POST. but this does not work.
after some testing, and reading up on rails style REST apis (which is what the backbone docs suggest), i realized that all request variables are sent the same way. if i change my code to use file_get_contents('php://input') to get the request parameters for every request type, backbone works perfectly.
is this standard fair for REST apis? or just "rails flavored" ones?
PUT, POST, PATCH, etc (everything but GET and DELETE*) accept request bodies. Generally data is passed as either:
A URL encoded string of name/value pairs (exactly the same as a URL querystring) that is decoded and parsed by the server into $_POST (or similar depending on your web framework of choice). This typically relies on the presence of a Content-Type header set to application/x-www-form-urlencoded (browsers do this by default when forms are submitted). If you see the data in file_get_contents('php://input') but not $_POST it's very likely this header is not present or is set to another value. If you're using Chrome, you can see what headers and body the client is sending in the Network tab of the dev tools.
The other popular request body format is to use Content-Type: application/json and then write out a JSON string to the body. This can be accessed via file_get_contents('php://input') and then parsed with a JSON parser.
* Note on DELETE: it's a little unclear whether or not using a request body with DELETE is allowed or a good practice.