What naming convention is recommended when writing an MVC app that has both front-end and JSON paths to the required data?
For example, let's say the user of your site has "Things". They should be able to go to a page to view their things, but we also need a way to pull those things back as JSON on other pages. I've been able to think of several options but I'm not keen enough on any of them to proceed. Here's what I've got:
/things/list for UI, /json/things for JSON - this would require a JsonController which would end up serving different kinds of objects, thereby defeating any chance of entity separation before we even start.
/things/list for UI, /things/list/json for JSON - probably my preferred option at the moment, but requires magic stringing (albeit just "json"). Also, if you also need a (string id) action signature for taking in some filter parameters or such, then you have the choice of adding an extra route or doing some dirty string splitting.
/account/mythings for UI, /things/list for JSON - a bit cleaner, but there might not always be a relevant controller that you could serve the "things" from. Plus, you're mixing entities again.
All and any suggestions welcome, thanks!
Arguably the path names could all be the same. You can examine the Accept header for the mime-type of your client's desired response, and then return an appropriate view based on what you find there:
application/json: JSON View
text/xml: XML View
text/plain, text/html: JSP
View
Browsers set this field to HTML; your JSON clients would simply set this field as appropriate.
It's highly unlikely that anyone would be bookmarking a URL that requests JSON so I think that it's not that important to keep the URL as clean. It's also likely to be programmatically generated, not hand entered. Given these, I'd consider adding it as a query parameter.
/things/list -- HTML
/things/list?format=json -- JSON
This won't break your URLs if you do have ID parameters or need other parameters as well. It could also work with POSTs as well as GETs.
/things/1 -- HTML for "thing 1"
/things/1?format=json -- JSON for "thing 1"
I use the convention of
/things/list -- HTML
/things/_listpage -- AJAX
The rule is that all AJAXed actions/views have a leading underscore. This tells me that they are never called top-level, and usually have no master page associated. In this case, I keep the action under the same controller in order to share any associated logic.
Typically in the list view I would have a
<% RenderAction("_listpage", "things", new {page = ViewData["CURRENT_PAGE"]}); %>
I would recommend a slight variation/elaboration to the suggestion by #RedFilter
/things/list -- HTML
/things/_list -- return HTML help and examples (more for you than them).
/things/_list/schema -- schema info
/things/_list/json -- JSON format
/things/_list/xml -- XML format
/things/_list/csv -- csv format
/things/_list/tab -- tab deliminated format
/things/_list/wdsl -- implemented soap web service
etc.. I feel it is more extensible. It looks scary, but it is easy to pass the data contents through a decorator based on the format requested making a whole host of file formats available with practically just a few lines of code.
Here is a crude conceptual example:
public ActionResult _list(string id)
{
string data = "";
DataTable oDataTable = this.oDAO.Get("list"); // pretend data retrieval
try{
if(!String.IsNullOrEmpty(id)){
data = this.oDecorator.FormatData(id,oDataTable);
this.ContentTypeChange(id); // change application handler
}else{
data = this.GetHelp("_list");
}
}catch{}
ViewData["data"] = data;
return View();
}
...help can be more of a feature list, technical examples, or whatever you want. Of course you can start with just having native JSON and add more data formats to your decorator as requirements grow which is nice. For many of my projects it starts as a pure json rest pull by an AJAX and tends to bloom into other formats that are needed based on site popularity, so I have found this robust enough to use in an enterprise setting for smaller projects that often grow big.
Related
I have a RESTful interface and mainly one function. The function mainly takes one big binary file as input and returns the modified file. Let's assume it's an encryption function (it's not, but similar). Nothing gets stored on the server, so repeating the call is no problem. I also need to pass many parameters, like type of encryption, some information about the caller, if the file needs to be converted first, etc.
I was thinking to implement this with a URL with something like this: //server/v1/encrypt, a POST request, and all parameters including the file (base64 encoded) in a JSON in the body.
Now the JSON definition says POST should be used for creation requests and it cannot be cached. Caching is not really important for me (as the file is always different), but I would like to follow standards and recommendations and best practice.
I would assume for the type of request, the best would be to use GET, but GET cannot have a file in the body (as per question 978061). And also the parameters in the body as JSON is probably also not a good idea. But is it really better to have 50 parameters in the URL (either as part of the path or part of GET parameters)?
How would you implement this and why?
I have a situation where I have to write a api to create a resource and amongst datafields that I need to accept is a string that is basically contents of a html file. As I see it I have a choice between structuring the entire thing as a json object where this field is a string field with urlencoded html string , and having the Content Type as multipart/form-data where each of the fields and the html string (UTF-8 encoded) is a part in the message.
Not using json is something I am not comfortable with as I feel violating the REST standards in not structuring the content of the entity I am about to create thus there is a loss of information for the consumers as they can't tell immediately looking at my api definition about what data to feed to it. But practically multipart/form-data handles stuff like html file content better and more efficient as I will not have to urlencode it and can control the char-encoding also.
What will be a better approach in current context and upholding RESTful principles ? Also are there other trade-offs i should be aware of ? what about parsing a json with a huge string field (~ 200 Kb)embedded?
EDIT :- I was reading some similar questions on SO and one approach that stood out was the 2-step approach of making a first call with metadata to create the entity and then upload the file as an UPDATE process to the created entity wherein we use multipart/form-data. In that context, I guess , what I am asking is how sound is an approach where I send both metadata and the file in a single api call as multipart data , where each metadata field is actually a part in the multipart message as is the file.
The canonical way to upload files to REST API is using the multipart/form-data. As W3 recommendation guide says:
The content type "multipart/form-data" should be used for submitting
forms that contain files, non-ASCII data, and binary data.
Multipart/form-data has advantages over base64 to represent binary data. Is sticked to REST/Http philosophy, and simplify the develop of API clients.
Returning values from Forms: multipart/form-data
W3 Recommendation guide
The good practice is to use multipart/form-data whenever files are uploaded to the server along with database fields. Do not send a base64 JSON string as the request to your Rest API as it might corrupt the file or degrade the performance of your application.
As far as documenting multipart/form-data Rest API for your consumers is concerned you have to force your API consumers to use the same form fields which you have predefined in your web service.
Returning Values from Forms: multipart/form-data
I started using FormData objects everywhere on the client-side, in lieu of regular form input fields, for dynamic REST posts. FormData is presented in a positive light in various tutorials, so I went with it.
However, down the line, this caused me problems when decoding the form data into my Go structs. FormData objects are sent as "multipart/form-data" (regardless of files being sent) and I believe my decoder in Go didn't convert the raw data back to string form. Eventually my SQL queries were throwing panics, as hex data was being sent in where strings should have been.
So with some adjustment, I could use FormData however I've decided to revert to the simple universal recommendation: Use "multipart/form-data" only for special cases like when sending files. Otherwise, just use regular "application/x-www-form-urlencoded".
A REST API can have arguments in several places:
In the request body - As part of a json body, or other MIME type
In the query string - e.g. /api/resource?p1=v1&p2=v2
As part of the URL-path - e.g. /api/resource/v1/v2
What are the best practices and considerations of choosing between 1 and 2 above?
2 vs 3 is covered here.
What are the best practices and considerations of choosing between 1
and 2 above?
Usually the content body is used for the data that is to be uploaded/downloaded to/from the server and the query parameters are used to specify the exact data requested. For example when you upload a file you specify the name, mime type, etc. in the body but when you fetch list of files you can use the query parameters to filter the list by some property of the files. In general, the query parameters are property of the query not the data.
Of course this is not a strict rule - you can implement it in whatever way you find more appropriate/working for you.
You might also want to check the wikipedia article about query string, especially the first two paragraphs.
I'll assume you are talking about POST/PUT requests. Semantically the request body should contain the data you are posting or patching.
The query string, as part of the URL (a URI), it's there to identify which resource you are posting or patching.
You asked for a best practices, following semantics are mine. Of course using your rules of thumb should work, specially if the web framework you use abstract this into parameters.
You most know:
Some web servers have limits on the length of the URI.
You can send parameters inside the request body with CURL.
Where you send the data shouldn't have effect on debugging.
The following are my rules of thumb...
When to use the body:
When the arguments don't have a flat key:value structure
If the values are not human readable, such as serialized binary data
When you have a very large number of arguments
When to use the query string:
When the arguments are such that you want to see them while debugging
When you want to be able to call them manually while developing the code e.g. with curl
When arguments are common across many web services
When you're already sending a different content-type such as application/octet-stream
Notice you can mix and match - put the the common ones, the ones that should be debugable in the query string, and throw all the rest in the json.
The reasoning I've always used is that because POST, PUT, and PATCH presumably have payloads containing information that customers might consider proprietary, the best practice is to put all payloads for those methods in the request body, and not in the URL parms, because it's very likely that somewhere, somehow, URL text is being logged by your web server and you don't want customer data getting splattered as plain text into your log filesystem.
That potential exposure via the URL isn't an issue for GET or DELETE or any of the other REST operations.
I'm looking to run a script using Stripe.pm, basically looking to do credit card processing. The credit card number is not being passed at all. All the examples I see use a JSON object passed in a POST call but I have a lot of experience using Query Strings i.e.
http://www.example.com/cgi-bin/processingscript.pl?param1=XXXX¶m2=YYYYY¶m3=ZZZZZ
Is this a security risk? What is the advantage or disadvantage of posting using JSON versus a query string like I'm used to using?
From a purely technical point of view, there is no difference between POST and GET if you pass a reasonably short parameter. You can also just pass JSON as a GET parameter no problem:
GET foo.pl?json={'foo':'bar'}
It would make sense to url-encode the data in this case. You can also send the same request using POST.
If you do not want to use query params at all, you need POST and put your JSON into the request body. Depending on which option you choose, there are differences in how to deal with it in Perl. Let's say you are using the CGI module... Perl makes no difference between POST and GET params.
For the query string GET or POST, you need to do:
use CGI;
my $cgi = CGI->new;
my $json = $cgi->param('json');
If you put the payload directly into the request body, you will instead need to do:
use CGI;
my $cgi = CGI->new;
$cgi->param('POSTDATA');
This is documented in CGI under "handling non url-encoded ...".
For JSON, there is also of course the time it takes to parse it, but that should be negligible.
The advantage JSON has over query strings without JSON inside them is, that you can encode arbitrary complex data structures inside JSON, while plain-text query strings are just one level deep.
From a security point of view, pretty much everything has been said. I'll recap my own ideas:
use SSL
do not put sensitive stuff into log files
if you are dealing with CC data (even if it is not the number itself), take extra care; read up on PCI DSS and encrypt stuff during transmission
NEVER store a cvc!
if you want to learn more about that topic, there is a Stack Exchange site called Information Security.
Security
- making sure no one other than user/server know the data GET/POST has no influence. Use SSL to ensure this.
- Stopping the user passing "interesting" arguments to your script. POST has a certain amount of security-through-obscurity in that most users won't see the parameters, but it's no real security. You should check the parameters in your application to cover that.
Generally POST with a nice data package (e.g. JSON) makes for a much more flexible and maintainable application interface, and has the advantage that you don't need to worry about encoding and length of parameters the same way you do when using GET.
POST:
Generally safer for important data
Parameters not shown in url
You can pass longer Strings-Structures (e.g. JSON) than by using GET that has length limit on the parameters you send
So I have a theoretical question based on a lot of research that I have done recently with regards to REST API interfaces.
Firstly I understand that in REST, resources should be nouns and not verbs and each resource should be decoupled from the next resource, however the resources can return the same entities or collection of entities, depending on the purpose of the resource.
My focus however is performing restful search.
In all the research I have done, the most common solution I have come across is the use of parameters in the URL
api.test.com/search-cars?param1=val1¶m2=val2
Now while this is standard practice and is not truly breaking the rules of REST, why is it that no one represents the search parameters as an id (possibly in the form of JSON)
api.test.com/cars/{"color":"blue","year":"2013","make":"toyota"}
If I look at cars as a resource and represent my id as a JSON, I could easily say that I truly have a finite number of cars thus a finite and unique number of id's.
Further more this promotes pure rest by conforming to "resource/id"
What are the benefits and downsides to using parameters as in the first example?
What are the benefits and downsides to using JSON as an id with the "filters" as in the second example?
All your comments would be really helpful as I need to take a final decision on how to move forward with the first resource of my API. Also, I need to have a strong argument for my boss explaining why I decided on either of the methods.
The general form of an URL is
scheme://domain:port/path?query_string#fragment_id
So you propose two URLs:
search by query_string
search by last path segment
Search by query_string
I recommend to name the collection cars, not search-cars. As you write in your question, URLs identify resources. The cars resource identifies the collection of all cars. I have no idea what collection a resource called search-cars would identify.
GET http://api.test.com/cars
would return the collection of all cars.
GET http://api.test.com/cars/123
would return the car identified by 123.
GET http://api.test.com/cars?color=blue&year=2013
would return the collection of all blue cars build in 2013.
Search by path
Your second URL
GET http://api.test.com/cars/{"color":"blue","year":"2013","make":"toyota"}
would make the query (JSON) a part of the path. To make the two examples equal, I suppose to make the JSON a query parameter:
GET http://api.test.com/cars?search={"color":"blue","year":"2013","make":"toyota"}
JSON vs. named query parameters
Most REST frameworks support mapping of query params to method parameters.
Most REST frameworks allow you to map a path segment to a method parameter. And, again, most REST frameworks allow you to map JSON to an object or a simple dictionary.
What makes JSON harder to use is the need to escape the "{} characters:
{"color":"blue","year":"2013","make":"toyota"}
becomes
%7B%22color%22%3A%22blue%22%2C%22year%22%3A%222013%22%2C%22make%22%3A%22toyota%22%7D
which is not very nice.
Summary
You can use both the query_string and the path of the URL to identify a resource. Search parameters are better placed in the query_string because the ? can mentally be translated to the WHERE of SQL.
Don't use JSON in URLs because escaped JSON is hard to read.