HTTP Headers to use to specify CSV delimiter and options - rest

I would like my REST service to accept CSV files in addition to JSON and XML.
I would accept an HTTP PUT request such as:
PUT /myservice/user
Content-Type: text/csv; charset=utf-8
"tomas";"1980-01-01"
"george";"1981-02-02"
I would like to be able to accept different delimiters and other format options for my CSV file. Preferably without using the querystring, which doesn't seem to be the proper tool for that. I understand I could just invent my own headers such as:
PUT /myservice/user
Content-Type: text/csv; charset=utf-8
CSV-Delimiter: ,
CSV-Options: merge-duplicates, no-header-row
Or maybe I could invent my own parameters to Content-Type if that is allowed (after all it is a part of the content-type just like the charset used):
PUT /myservice/user
Content-Type: text/csv; charset=utf-8; delimiter=,; options=no-header-row
What would be the proper way to handle this? Are there any HTTP-headers conventionally used for this?

For "no-header-row" a parameter already exists: [header="present"|"absent"].
As for adding new parameters to the content-type header:
New parameters SHOULD NOT be defined as a way to introduce new
functionality in types registered in the standards tree, although new
parameters MAY be added to convey additional information that does
not otherwise change existing functionality. An example of this
would be a "revision" parameter to indicate a revision level of an
external specification such as JPEG. Similar behavior is encouraged
for media types registered in the vendor or personal trees but is not
required.

Related

Is the charset parameter allowed on application/octet-stream MIME type

I am working on a project where I need to send requests over email instead of http,
to prevent email servers or clients from messing with the body (especially urls) I have set the Content-Type header in my SMTP request to application/octet-stream instead of text/plain.
The content however is actually plain text so I also specified ;charset=UTF-8.
Looking at RFC it seems that the charset parameter is only allowed for text/* types, however I also found many examples where charset was used with application/* types.
Now I wonder, is application/octet-stream; charset=UTF-8 a valid MIME type?
As the application/octet-stream definition (IANA-RFC) doesn't define a charset for this applicationtype and the definition for application/json (IANA-RFC) a mimetype thats used more often includes a note:
No "charset" parameter is defined for this registration.
Adding one really has no effect on compliant recipients.
I would strongly recommend to assume that the statement not only applies in this special case, but also in other application/* which have no charset defined.
So I can't say if it is valid to pass parameters that aren't defined, but the RFC clearly implies that the charset parameter for application/octet-stream (and other application/* that do not define charset) has no effect.

Exposing the JSON Schema for API endpoints?

Is there a standard to where and how to expose the schema of API endpoints?
For example, let's say the following API endpoints are available:
api/companies/
api/companies/{id}/employees/
Where should the schema for the company and employee resources be exposed?
api/company-schema.json and api/employee-schema.json?
api/schemas/company.json and api/schemas/employee.json?
You can setup your schema endpoints any way you like, but you should use one of the recommended correlation methods. The idea is that there is no universal rule for accessing schemas. Instead, the resource itself identifies the schema that describes it.
So, feel free to expose your schemas any way you like. And then feel free to change it if you need to without fear of breaking client implementations. Just change your response headers to point to the new schema and clients should be able to handle the change dynamically.
The most straightforward correlation method is to include a describedby Link header.
HTTP/1.1 200 OK
Content-Type: application/json
Link: </schema/companies>; rel="describedby"
{ ... }
The other option is to use the schema content-type parameter. (Note: Previous versions of JSON Schema used profile instead of schema).
HTTP/1.1 200 OK
Content-Type: application/json; schema="/schema/companies"
{ ... }
However, the schema parameter is not actually defined for the application/json media-type, so there are potential interoperability issues with that method. That's one reason why the application/schema-instance+json media type was introduced. It works just like application/json, but defines a few capabilities that the normal JSON media-type doesn't.
HTTP/1.1 200 OK
Content-Type: application/schema-instance+json; schema="/schema/companies"
{ ... }
EDIT 2020/24/01: Fix broken link and update answer to reflect changes in recent drafts.
Why not expose it on where it is called?
For example
schema/companies
schema/companies/10/employees
Change the api to schema
I'm going with the Link header with these as the urls
/api/companies.schema
/api/companies/{id}/employees.schema

Perl Change Content Type Of Response

I am calling a SOAP web service as client.
Following is content-type value of response
Content-Type: text/xml
I requested customer to add UTF-8 to response as follow:
Content-Type: text/xml;charset=utf-8
But customer says that it can be from client side. Is this possible? Can I determine content type of server as client?
PS: I noticed that the cited RFC2376 is obsolete by RFC3023 (conservative enough) and then RFC7303 that I'm omitting to evaluate now in involved current use and content, so the relevance of the following might not be that definitive, I'm feeling to delete it.
You have everything formal in RFC2376 XML Media Types: Section 3.1 text/xml Registration
See also Section 6 Examples of that RFC, particularly Section 6.4 text/xml with Omitted Charset
The server side (your customer) is STRONGLY RECOMMENDED to use charset parameter that they are not currently using.
And if charter is omitted XML processors MUST use the default charset value of "us-ascii"
You are right asking the customer to specify charset, the "MUST" in the RFC is a strong requirement that limits also your adaptability from client side when they are not sending us-ascii.

How to design REST API for export endpoint?

I am designing a REST API and am running into a design issue. I have alerts that I'd like the user to be able to export to one of a handful of file formats. So we're already getting into actions/commands with export, which feels like RPC and not REST.
Moreover, I don't want to assume a default file format. Instead, I'd like to require it to be provided. I don't know how to design the API to do that, and I also don't know what response code to return if the required parameter isn't provided.
So here's my first crack at it:
POST /api/alerts/export?format=csv
OR
POST /api/alerts/export/csv
Is this endpoint set up the way you would? And is it set up in the right way to require the file format? And if the required file format isn't provided, what's the correct status code to return?
Thanks.
In fact you should consider HTTP content negotiation (or CONNEG) to do this. This leverages the Accept header (see the HTTP specification: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1) that specifies which is the expected media type for the response.
For example, for CSV, you could have something like that:
GET /api/alerts
Accept: text/csv
If you want to specify additional hints (file name, ...), the server could return the Content-Disposition header (see the HTTP specification: http://www.w3.org/Protocols/rfc2616/rfc2616-sec19.html#sec19.5.1) in the response, as described below:
GET /api/alerts
Accept: text/csv
HTTP/1.1 200 OK
Content-Disposition: attachment; filename="alerts.csv"
(...)
Hope it helps you,
Thierry

Is this an appropriate to encode CSV attributes as parameters on the text/csv mime type?

RFC 4180 talks about the text/csv mime type, but doesn't go into some of the more obvious variations that one would have to support, for example the separator used (ok ok so if it's Csv then it should obviously be a comma) and whether there is a header row or not.
I'd like to add parameters like separator=, and headerrow=0|1 to the mime type such that REST APIs that consume CSV files can consume them appropriately.
The alternative would seem to be to add the parameters to the URL but that feels wrong.