Why use a JSON object to pass data with POST versus a Query String in Perl? - json

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&param2=YYYYY&param3=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

Related

REST interface: design for many parameters and big data

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?

JSON REST endpoint returning / consuming JSON literals

Is it advisable or not in a RESTful web service to use JSON literal values (string / number) as input parameter in the payload or in the response body?
If I have an endpoint PUT /mytodolist is it OK for it to accept a JSON string literal value "Take out the rubbish" in the request payload (with Content-Type=application/json) or should it accept a JSON object instead ({"value":"Take out the rubbish"})?
Similarly, is it fine for GET /mytodolist/1 to return "Take out the rubbish" in the response body or should it return a proper JSON object {"value":"Take out the rubbish"}
Spring MVC to makes implementing and testing such endpoints easy, however clients have flagged this as non standard or hard to implement. In my point of view JSON literals are JSON, but not JSON objects, so I'd say it is fine. I have found no recommendations using Google.
EDIT 1: Clafirication
The question is entirely about the 'standard', if it allows this or not.
I understand the problem with the extensibility, but one can never design a fully extensible interface IMHO. If changes need to be done, we can try extending what we have in a backwards compatible way, but there will come a time when it becomes messy and an other approach is required - which is commonly handled by versioning the API in one way or another. I find it a fair point even though, because using literals as request/response body immediately becomes inextensible, while coming up with a reasonable one-attribute JSON object does not.
It is also understood that some frameworks have problems with handling JSON literals, this is the origin of this question. The tool I used happened to support this, so I thought this was all right, but the front-end library did not.
Still, what I am intending to find out right now, is if using JSON literals is according to the de-facto standard (even if it is a cornercase) or not.
I would recommend to use JSON object always. One reason is that for Content-Type application/json people expect something staring with "{" and not all frameworks will handle json literals properly. Second reason is that probably you will add some additional attributes to you list item (due date, category, priority, etc). And then you'll break backward compatibility, by adding new field.
It may be acceptable in the context of your example, but keep in mind that unambiguous interfaces are easier to use and that will encourage adoption.
For example, your interface could interpret "Take out he rubbish" as the same as {task:"take out the rubbish"}, but once you add additional properties (eg "when" or "who") the meaning of a solitary string in the request becomes ambiguous. It's inevitable that you'll add support for new properties as your interface matures.

REST API Best practices: args in query string vs in request body

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.

questions wcf rest service with webclient

I'm getting confused on a few things in regards to wcf rest.
If you call a login method, should I use a POST or GET? After implementing a POST, I started to find various articles saying you should only use post to update data, and get for retrieving data. Which is the most appropriate method?
If I had to change the Login method from a Post to a Get, how would I call this?
http://....myservice.svc/login/{username}/{passpord} or is there another way to call this?
Note that in my post method, I'm passing and returning data in json format.
I need to create a search function that requires to pass various parameters i.e. list, string, list, etc... I assume in this instance I would have to define GET method, but again how to I pass these list of objects? Convert them to json first and pass them as parameters?
A brief url sample would be great.
Ok, I guess I'll answer my own question based on further finding when researching it and remember that my answer is based on using JSON as parameters. I'm not sure how it would behave if xml was used as I did not try it.
It appears to make more sense to use POST when logging in as you do not want to display the information you are posting via a url. You could encrypt the data and pass it in the url using a GET method... Again I could be wrong, but that's how I interpreted the various articles I read.
Again, in this instance, it appears POST is the best solution if a) you require a large amount of data to be passed to your url and b) if you do not want to show this data to the user. If your query only requires simple parameters (i.e. userid, type, etc...) and you don't mind showing this info, you can use the GET method.
If you require to pass multiple parameters to a function, you should instead pass a single parameter. This parameter should be a single object. This object should be made of all the parameters you wanted to use in the first place, this way, when using the POST method, this object can easily be converted to JSON and it will handle passing multiple parameters through a single object and it will handle numeric, string, list<>, array<>, etc... very nicely.

MVC naming conventions for JSON actions

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.