If I’m exporting (or accepting) data structures for a given HTML page, is there a Best Practice or convention for forming JSON (etc) URLs?. For example, something like ...?fmt=<fmt> or perhaps ...?fmt=<fmt>&part=<part>?
URLs lengths are limited by the browsers so it is not good idea to send large structures as part of the URL. So if you can then use POST queries and send data within body of the request (GET requests cannot have body according to spec).
And if you really know what you are doing and you still want to continue, then I would say that you should use URL-safe base 64 encoding.
If yes, then “best practice” states don’t do it. The “format” isn’t something that should be part of the URL (other than supporting looking at data by typing the URL in the browser’s address bar) but should be supported via content negotiation.
The only problem I have with this approach is that it pretty much requires writing
some client code in order to get at the JSON data. Although the curl(1) command
has a -H flag which can be used to set headers, I don’t know of anything analogous
in the world of web browsers.
For browsers the initial point of contact tends to be text/html or text/plain.
If you look at the developer console’s network traffic you’ll notice that the browser doesn’t specify an Accept header - leaving it up to the server to serve the default media type as there often is only one.
However if there are multiple representations of the same resource, it’s discouraged to use distinct URLs for each representation. The resource should be identified by the URL (a URI) but the format of the representation should be handled via Accept/Content-Type (if there is more than one possible format).
application/json , application/toml and application/x-yaml are intended for consumption by programmatic clients - not straight inclusion in a static web page.
suggests that the JSON version of the URL /foo could be something like /api/foo.
defmodule HelloWeb.Router do
use HelloWeb, :router
pipeline :browser do
plug :accepts, ["html"]
pipeline :api do
plug :accepts, ["json"]
scope "/", HelloWeb do
get "/", PageController, :index
scope "/api", HelloWeb do
That split has largely to do with the separate Plug pipelines as API requests typically don’t require a lot of the baggage that exists for the browser (and APIs may need their own type of baggage).
Plug accepts/2 can take multiple media types, so the data format isn’t hardwired.
The controller can access the requested format through get_format/1. In fact render/3 uses it to choose the template with the correct format.
I really don’t think the header method is really the best to be honest. For example, at work here I have a webpage table report that can be downloaded as html, json, csv, formatted-pretty-excel, pdf, and can be expanded in the future, this is done by just adding something like .csv or .xlsx or whatever to the end of the url. When sending URL’s to other systems or synching to excel or so forth I can only send a URL, thus using a header only method seems quite impossible to support.
So yes, I do it not by doing something like ?fmt=json, but rather by just appending .json to the end of the URL (before the query args if any). There is a plug that strips that off and sets the content format based on that. Without it, then it defaults to the header as usual.
The first thing we need to understand is that a URI is not a file name.
Using URI patterns I’ve seen
as the preferred alternative - simply to break away from the mental model of a file.
But the thing is operating in this way creates another conceptual problem. There are three distinct URIs up there - how do we know that they refer to the same resource? One would guess because they share the same root in the URI but to know you would have to retrieve them and compare them on the semantic level.
I wouldn’t say this is used enough to be considered a best practice at all – and I don’t know if that would be the best for your case, but a “standard” way of describing URLs with client parameters is brought by the URI Template specification