Is using JSON as HTTP GET input Paramter a valid RESTful Service? - rest

I have the following Backend API:
Endpoint
HTTP GET
https://localhost:8443/getSomeParameterInfo
Query Parameter
?inputAsJson
example
{
'url': 'http://semanticstuff.org/blah#Parameter,
'parameters_1': 'value1',
'someArray': [
'http://semanticstuff.org/blah#something1,
'http://semanticstuff.org/blah#something2
],
'someOtherArray': [
'http://....'
]
}
the Final HTTP GET Call is
https://localhost:8443/getSomeParameterInfo?inputAsJson={aboveMentioned JSON}
Due to everchanging requirements for the Backend, the above mentioned JSON Structure keep increasing by addition of new key:value pairs. (This JSON Structure is also a query for a database)
Hinderances
Due to uses of weblinks as values it becomes necessary to use encodeURIComponent function for a successful REST Call. This means, the quotes, forward slashses etc. need to be encoded to get a Reply. This becomes quite tedious when one requires to do tests on standalone basis (using Postman or other REST Clients)
I have not seen a JSON structure passed to an API as mentioned above and hence I wish to confirm about the best practices and/or proper way to use large number of parameters when making such a RESTful call

I usually tend to think that getting something via a POST is a "bad" practice.
However, it sounds like body in GET is not something forbidden but still something not widely implemented in frameworks.
In your case, it will depends on how many attributes you have and the global length or your json.
If you keep on using GET method, then using an "exploded" key-value representation of your JSON should be the way to go.
Exemple:
{ "myKey": "myValue", "childObjKey": {"childObjProp": "childValue}}
could become
?myKey=myValue&childObjKey.childObjProp=childValue
But there are some limits on query parmeters' length which can be implemented in clients and/or servers.
If your number of parameters is huge and values' length are unpredictable (text without length limit for instance), then using POST should be the way to go.

Related

Should I use GET or POST REST API Method?

I want to retrieve data about a bunch of resources. Let's say an Array of book id and the response is JSON Array of book objects. I want to send the request payload as JSON to the server.
Should I use GET and POST method?
Note:
I don't want to make multiple GET request for each book ID.
POST seems to be confusing as it is supposed to be used only when the request creates a resource or modifies the server state.
I want to retrieve data about a bunch of resources. Let's say an Array of book id and the response is JSON Array of book objects.
If you are thinking about passing the array of book id as the message body of the HTTP Request, then GET is a bad idea.
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
You should use POST instead
POST seems to be confusing as it is supposed to be used only when the request creates a resource or modifies the server state.
That's not quite right. POST can be used for anything -- see GraphQL or SOAP. But what you give up by using POST is the ability of intermediate components to participate in the conversation.
For example, for cases that are effectively read-only, you would like to use a safe method, because that allows pre-caching optimization, and automated retry of lost responses on an unreliable network. POST doesn't have extra semantic constraints, so you lose out.
What HTTP really wants is that you GET using the URI; this can be done in one of two relatively straightforward ways:
POST the ids to the server, to create a new resource (meaning that the server retains for itself a copy of the list of ids), and receive a new resource identifier back in exchange. Then GET using this new identifier any time you want to know the current representation of the results.
Encode the information you need into the URI itself. Most commonly, this is done using the query part of the URI, although that isn't strictly necessary. The downside here is that if the URI encoded representation of the array of ids is very long, you may have trouble with some implementations that enforce arbitrary URI limits.
There aren't always great answers:
The REST interface is designed to be efficient for large-grain hypermedia data transfer, optimizing for the common case of the Web, but resulting in an interface that is not optimal for other forms of architectural interaction.
If I understand correctly, you want to get a list of all of the items in a list, in one pull. This would be possible using GET, as REST returns the JSON it can by default be up to 100 items, and you can get more items if needed by specifying $top.
As far as writing back or to the server, POST would be what your looking for, this to my understanding would need to be one for one.
you are going to use a GET-Request and put your request-data (book-id array) in the data-section of your ajax (or whatever you're going to use) request. See How to pass parameters in GET requests with jQuery

What is the best practice to HTTP GET only the list of objects that I require

I am in a situation where in I want to REST GET only the objects that I require by addressing them with one of the parameters that I know about those objects.
E.g., I want to GET all the USERS in my system with ids 111, 222, 333.
And the list can be bigger, so I don't think it is best way to append the URL with what is required, but use payload with json.
But I am skeptical using JSON payload in a GET request.
Please suggest a better practice in the REST world.
I am skeptical using JSON payload in a GET request.
Your skepticism is warranted; here's what the HTTP specification has to say about GET
A payload within a GET request message has no defined semantics
Trying to leverage Undefined Behavior is a Bad Idea.
Please suggest a better practice in the REST world.
The important thing to recognize is that URI are identifiers; the fact that we sometimes use human readable identifiers (aka hackable URI) is a convenience, not a requirement.
So instead of a list of system ids, the URI could just as easily be a hash digest of the list of system ids (which is probably going to be unique).
So your client request would be, perhaps
GET /ea3279f1d71ee1e99249c555f3f8a8a8f50cd2b724bb7c1d04733d43d734755b
Of course, the hash isn't reversible - if there isn't already agreement on what that URI means, then we're stuck. So somewhere in the protocol, we're going to need to make a request to the server that includes the list, so that the server can store it. "Store" is a big hint that we're going to need an unsafe method. The two candidates I would expect to see here are POST or PUT.
A way of thinking about what is going on is that you have a single resource with two different representations - the "query" representation and the "response" representation. With PUT and POST, you are delivering to the server the query representation, with GET you are retrieving the response representation (for an analog, consider HTML forms - we POST application/x-www-form-urlencoded representations to the server, but the representations we GET are usually friendlier).
Allowing the client to calculate a URI on its own and send a message to it is a little bit RPC-ish. What you normally do in a REST API is document a protocol with a known starting place (aka a bookmark) and a sequence of links to follow.
(Note: many things are labeled "REST API" that, well, aren't. If it doesn't feel like a human being navigating a web site using a browser, it probably isn't "REST". Which is fine; not everything has to be.)
But I believe POST or PUT are for some requests that modify the data. Is it a good idea to use query requests with them ?
No, it isn't... but they are perfect for creating new resources. Then you can make safe GET calls to get the current representation of the resource.
REST (and of course HTTP) are optimized for the common case of the web: large grain hypermedia, caching, all that good stuff. Various use cases suffer for that, one of which is the case of a transient message with safe semantics and a payload.
TL;DR: if you don't have one of the use cases that HTTP is designed for, use POST -- and come to terms with the fact that you aren't really leveraging the full power of HTTP. Or use a different application - you don't have to use HTTP if its a bad fit.

Is it RESTful to include parameters in a GET request’s body rather than the URI?

I have a complicated schema that requires complicated API calls. For many resource retrievals, the user would want to specify several parameters to filter the results. Including all of these parameters in the URI seems like it would be messy and difficult for front-end developers to craft, so I’ve opted to put the parameters into the request body as JSON. Unfortunately, this doesn’t seem to sit well with the web back-end I’m using (Django-Rest Framework). Is this RESTful, or am I making a mistake?
As a follow-up question, if I should put the parameters in the URI, how would I represent complex pieces of data, like lists of strings, and the relationships between pieces of data?
Is this RESTful, or am I making a mistake?
It sounds to me as though you are making a mistake. The authority in this case is RFC 7231
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
My interpretation is this: caching is an important part of the web; for caching to work as people would expect it requires compliant caches to be able to manage that message body as part of the key.
An HTTP method that may serve your needs better is SEARCH.
The SEARCH method plays the role of transport mechanism for the query and the result set. It does not define the semantics of the query. The type of the query defines the semantics.
SEARCH is a safe method; it does not have any significance other than executing a query and returning a query result.
If that doesn't fit your needs, you could look through the HTTP method registry to see if one of the other standards fits your use case.
how would I represent complex pieces of data, like lists of strings, and the relationships between pieces of data?
The real answer is "any way you want" -- the origin server has control of its URI space, and any information encoded into it is done so at the server's convenience for its own use.
You could, for instance, consider using one of the Base64 encodings defined in RFC 4648
From what I read about RESTful, you can only use GET, POST, PUT, PATCH, and DELETE.
The GET and DELETE are not expected to include a body. As #VoiceOfUnreason mentioned, this is mainly because caches can have difficulties handling a body along a GET. That being said, if your results are never cached, it should not be a concern at all. (i.e. return Cache: no-cache and other similar HTTP header from your server.)
There is no real convention on the Query String and supporting lists or JSON and such. If you want to keep a GET, you could use an encoded JSON string, though. There is no problem with that, except the length of the URL.
http://www.example.com/?query=<encoded-json>
(encoded just means that you have to properly escape URI special characters, what the JavaScript encodeURICompent() function does.)
The length of the URL should be kept under 1Kb to be 100% safe. You can do some research on it, I think that the browser with the most stringent limit is around 2k.
If you want to use a bigger query, then you should revert your queries to using a POST and not a GET. Then the buffer is normal in that situation and the reply is not expected to be cached.
Real World Use (but Not An Excuse)
If you look into Elasticsearch, you will see that all their queries accept a JSON. You can send a DSL query using a GET or a POST. Either one accept a JSON in their body.
They offer the POST because most browsers will not accept to attach a body to a GET method. So GET queries would not work at all from a browser.
Example of Arrays in Query Strings
There has been various libraries, and at least PHP, that added support for arrays in parameters. In most cases this is done by supporting the array syntax in the parameter name. For example:
path/?var[1]=123&var[2]=456&var[3]=789
In this case, those languages will convert the value in an array. $_GET['var'][1] would then return 123.
This is not a convention, just an extension of that specific environment.

What's the best best way to send complex option data in a GET request without using body payload?

so I finished a server in Node using Express (developed through testing) and while developing my frontend I realized that Java doesn't allow any body payload in GET requests. I've done some reading around and understand that the Http specs do allow this, but most often the standard is to not put any payload in GET. So if not this, then what's the best way to put this into a GET request. The data I include is mostly simple fields except in my structure some of them are nested and some of them are arrays, that's why sending JSON seemed so easy. How else should I do this?
For example I have a request with this data
{
token,
filter: {
author_id,
id
},
limit,
offset
}
I've done some reading around and understand that the Http specs do allow this, but most often the standard is to not put any payload in GET.
Right - the problem is that there are no defined semantics, which means that even if you control both the client and the server, you can't expect intermediaries participating in the discussion to cooperate. See RFC-7231
The data I include is mostly simple fields except in my structure some of them are nested and some of them are arrays, that's why sending JSON seemed so easy. How else should I do this?
The HTTP POST method is the appropriate way to deliver a payload to a resource. POST is the most general method in the HTTP vocabulary, it covers all use cases, even those covered by other cases.
What you lose in POST is the fact that the request is safe and idempotent, and you don't get any decent caching behavior.
On the other hand, if the JSON document is being used to constrain the representation that is returned by the resource, then it is correct to say that the JSON is part of the identifier for that document, in which case you encode it into the query
/some/hierarchical/part?{encoded json goes here}
This gives you back the safe semantic, supports caching, and so on.
Of course, if your json structures are complicated, then you may find yourself running into various implicit limits on URI length.
I found some interesting specs for GET that allow more complex objects to be posted (such as arrays and objects with properties inside). Many frameworks that support GET queries seem to parse this.
For arrays, redefine the field. For example for the array ids=[1,2,3]
test.com?ids=1&ids=2&ids=3
For nested objects such as
{
filter.id: 5,
filter.post: 2
}
test.com?filter[id]=5&filter[post]=2

Rest POST VS GET if payload is huge

I understand the definition of GET and POST as below.
GET: List the members of the collection, complete with their member URIs for further navigation. For example, list all the cars for sale.
POST: Create a new entry in the collection where the ID is assigned automatically by the collection. The ID created is usually included as part of the data returned by this operation.
MY API searches for some detail in server with huge request payload with JSON Message in that case Which Verb should i use ?
Also can anyone please let me know the length of the characters that can be passed in query string.
The main difference between a GET and POST request is that in the former, the entire request is encoded as part of the URL itself, whereas in the latter, parameters are sent after the header. In addition, in GET request, different browsers will impose different limits on how big the URL can be. Most modern browsers will allow at least 200KB, however Internet Explorer seems to limit the URL size to 2KB.
That being said, if you have any suspicion that you will be passing in a large number of parameters which could exceed the limit imposed on GET requests by the receiving web server, you should switch to POST instead.
Here is a site which surveyed the GET behavior of most modern browsers, and it is worth a read.
Late to the party but for anyone searching for a solution, this might help.
I just came up with 2 different strategies to solve this problem. I'll create proof of concept API and test which one suites me better. Here are the solution I'm currently thinking:
1. X-HTTP-Method-Override:
Basically we would tunnel a GET request using POST/PUT method, with added X-HTTP-Method-Override request header, so that server routes the request to GET call. Simple to implement and does work in one trip.
2. Divide and Rule:
Divide requests into two separate requests. Send a POST/PUT request with all payload, to which server will create necessary response and store it in cache/db along with a key/id to access the data. Then server will respond with either "Location" header or the Key/id through which the stored response can be accessed.
Now send GET request with the key/location given by server on previous POST request. A bit complicated to implement and needs two requests, also requires a separate strategy to clean the cached responses.
If this is going to be a typical situation for your API then a RESTful approach could be to POST query data to a buffer endpoint which returns a URI from which you can GET your results.
Who knows maybe a cache of these will mitigate the need to send "huge" blobs of data about.
Well You Can Use Both To get Results From Server By Passing Some Data To server
In Case Of One Or Two Parameters like Id
Here Only One Parameter Is Used .But 3 to 4 params can Be used This Is How I Used In angularjs
Prefer : Get
Example : $http.get('/getEmployeeDataById?id=22');
In Case It Is Big Json Object
Prefer : Post
Example : var dataObj =
{
name : $scope.name,
age : $scope.age,
headoffice : $scope.headoffice
};
var res = $http.post('/getEmployeesList', dataObj);
And For Size Of Characters That Can Be Passed In Query String Here Is Already Answered
If you're getting data from the server, use GET. If you want to post something, use POST. Payload size is irrelevent. If you want to work with smaller payloads, you could implement pagination.