I wanted to clarify on a usecase where i struggled to use GET method for a fetch operation.
I was asked to build a API to generate message from a predefined template. In the request i receive template-ID and the dynamic content which needs to be substituted. Dynamic content vary based on the template-ID.
I have designed like
Method = POST
URL pattern = /messagegenerator/v1/templateID
Body = Dynamic Content in the form of JSON
Response = Plain text message
Problem i faced: When i use GET method then template content should be passed in the URL which has length restriction. We wanted to prepare email message which has more dynamic content.
Ultimately this service won't create any resource but still i forced to use POST method.
Am i missing something?
Rest standard missing?
Is there any better way of doing this?
Is there any restrictions on the length of get URL parameters?
Although there is no url limit in the standard, there is this old advice about keeping your urls under 2000 characters: What is the maximum length of a URL in different browsers?
To the point: in your case sending a POST request with all data in the body is the best solution. Putting email body fragments, or anything that huge (if I understand correctly) into a url is very ugly :). Even if the request does not change anything on the server technically, you should use POST, yes.
You need to create a new API which supports http get method, because one API can't receive more than on http method.
As you pointed out, in REST the POST method is thought of creating a new resource. In your case a new resource "message" is generated indeed by posting the content even if you do not keep it on the server.
But you are using POST on a template! This should create a new template. To resolve this, add a subresource to the template resource so you can express that it is a message that is created.
I would even extend the URL by adding a "template" after the "v1" to make more explicit that it is the "template" resouce on the first level.
The only change necessary for that would be to modify the URL like this:
URL pattern = /messagegenerator/v1/template/<templateID>/message
So you could have (even if you do not implement it now):
GET on /messagegenerator/v1/template/ -> Deliver a list of templates
POST on /messagegenerator/v1/template/ -> Create a new template
DELETE on /messagegenerator/v1/template/<templateID> -> Remove a template
PUT on /messagegenerator/v1/template/<templateID> -> Modify a template
GET on /messagegenerator/v1/template/<templateID>/message -> Deliver a list of messages
POST on /messagegenerator/v1/template/<templateID>/message -> Create a new message
DELETE on /messagegenerator/v1/template/<templateID>/message/<messageID> -> Remove a message
PUT on /messagegenerator/v1/template/<templateID>/message/<messageID> -> Modify a message
So you could even manage and return old messages if you saved and assigned them an ID!
Related
I write an API for report fetching with detailed filters, such as filters for recordIds, userIds, tagIds, basically multiple different id lists are part of the filter.
So far I coded these fetches as POST requests with id lists in body but I got curious if it is possible to handle these filters as a GET request instead?
What I searched so far yielded that, it doesn't seem possible since there is multiple List based filters and request is likely too big to be a GET but still, I'm curious if there is possible work arounds?
In my opinion, this is according to your requirement.
If you are using post, you could post a complex object inside the body and this request will be more security than the get method.
If you wan to use get method, you could put all the parameter inside the url. Each url will contains the limit and build the complex object in the url is not recommended. If this also match your production environment, you could modify the codes to use get method.
Is it possible to modify a property of a change request by using the OSLC-CM REST API of a change management system. The system that I'm trying to achieve that is Rational Change.
I can browse and query via the REST API, but to modify anything I need to resort to command line which is rather slow.
Is there a way?
BR,
Pawel
To update resources using the OSLC-CM REST API you simply just can use HTTP PUT. In order to do this, you'll first need the URL of the Change Request.
The steps to achieve this (using any HTTP client) are:
acquire URL for Change Request (usually done by query, or stored reference, etc)
Perform an HTTP GET on that URL, specifying a format for use in editing. This is done using 'Accept' header, some typical values would be 'application/xml', 'application/json' or 'application/rdf+xml'.
Note, it is a good idea to set the header 'OSLC-Core-Verson: 2.0' as well to ensure you are working with the 2.0 formats.
Once you have fetched the resource, modify the property to the value you want.
Using HTTP PUT, send the modified resource in the content body to the same URL you fetched the resource from.
Additionally you will most likely need to pass along some additional headers to help the server detect any possible conflict.
You should get back a 200 (OK) or 204 (No content) response on success.
An optimization would be to do the same steps as above but only request the properties of interest and only send them by using the selective properties feature of OSLC.
So I've finally got it working with some help from googlegroups
To recap what I've done so that someone else might benefit too (I really have searched for it and the IBM documentation is as in most of the cases not helping):
So to modify PR/CR' implement_actual_effort attribute on the Rational Change server the following procedure was successful (using Firefox REST plugin):
1. In Headers set: Accept to application/xml, Content-Type to application/xml
Put the oslc address of the cr i URL in my case it was:
http://[IP:PORT]/change/oslc/db/[DB hex ID]/role/User/cr/[web_encoded_name_of_the_CR]?oslc_cm.properties=change:implement_actual_effort
(note in browser http://[IP:PORT]/change/oslc/db/[DB hex ID]/role/User/cr/[web_encoded_name_of_the_CR] will open change page of the CR/PR)
In REST client set Method to GET and press SEND
Click on the Response Body (RAW), copy xml Body
Change Method to PUT, change the value of the attribute (in the xml in Body window)
Press SEND
Attribute should have been changed right now, and the response should be similiar to what you've sent, with the attribute showing the change.
Note that to change an attribute (called property from oslc point of view) one has to provide ?oslc_cm.properties=[properties delimited with comma]
and in the request body xml the same properties have to be present, if I remember correctly if the property isn't mentioned in the xml it will be set to default
I hope this helps someone
BR,
Pawel
Given a one page app that uses push state and RESTful backend, we can imagine accessing the listing of a resource at /resourceName (i.e. /users). So /users would create a formated list of users
Now the problem is that this resource JSON or XML feed should also be mapped to /resourceName, so if boot form my application entry point at / then all is good, when navigating to /users the JS router can trigger a Ajax call that get the JSON data. Now the problem is if the URL is pointing directly at /users then i will land on a JSON feed instead of the actual listing. I could route all call to a main entry point and then let the JS router do the work though if i do so the AJAX call to fetch JSON wil brake.
I remember a while ago people adding .json to their json request, or even a GET parameter ?format=json and then having the controller taking different actions. I find that somewhat hacky.. Are there any other ways to go about this?
For that matter i am using laravel4 backend and backboneJS
I think the .json on the end of the request is the best approach. the other approach could be to create a separate endpoint endpoint for api request api.mydomain.com vs www.mydomain.com
What method you use to get a different response depends on how you'd like to go about it. Since you're asking about an opinionated topic (There is no one right answer), here's some options you can explore.
First, here's a good read from Apigee on API design, which covers what I'll write about here. See page 20 on "Support multiple formats"
The Rails way: Append a .json, .xml or other extension at the end of your request and handle that code within Laravel (You may want to use the "before" filter to check the request or Laravel's excellent route parameters, which allow the use of regex to define the route).
You can check the "accept" header in the request and set that header in your ajax calls to "application/json" instead of the default "application/html" to inform your application which format to use in its response. Again, the before or after filters may come in handy to check the request and define the response as appropriate
Create a query string `?format=json" or similar. Same comments as in point 1.
Laravel doesn't have built-in methods to change the response for you. You can, however, fairly easily detect what's being asked and choose which format to return in. It does take some thinking about how you want to accomplish that, however.
Some options off the top of my head:
Use the "before" or "after" filter to check what the request "wants" for a format, and do some transformations on the response to make that work
Extend the request and response class to "automate" this (request class to detect format, response class to transform the response to the correct format)
Hope that helps
It's valid to say which representation do you want. E.g. JSON, XML or binary, depends on what you want and which serializers have you developed.
You framework should support either setting of default representation or if you provide some mapping URL -> method you should be able to say which representation you are going to return - also either by default or taken within some object which represents your request.
I ended up using different endpoints as suggested by #Aaron Saunders. In laravel 4 this is dumb easy to implement using group routes:
app.php:
'domain' => 'whatever.dev',
routes.php:
define('APP_DOMAIN', 'app.' . Config::get('app.domain'));
define('API_DOMAIN', 'api.' . Config::get('app.domain'));
Route::group(array('domain' => API_DOMAIN), function()
{
// API ROUTES
});
Route::group(array('domain' => APP_DOMAIN), function()
{
// VIEW ROUTES
});
Beautiful!
Pardon the simple question, but it seems most searches try to tell me which methods are designed for what actions. Eg, create & edit is PUT, create from plural (articles) is POST, and so on. (If you disagree with this, i was just using it as an example. :)
With that said, how do you initiate a resource edit? To create a resource, with a known url you preform a GET on an non-existing URL. Eg, GET:mysite/resource_one. This then returns a form, and the form submits a PUT to the same address and bam, the resource is created.
Now how do you edit that same resource? With 4 Methods, designed for CRUD, i am having issues because i can only seem to think of one way. To go to a new resource. Eg, GET:mysite/resource_one/edit. This then presents a form with existing data, you edit it, and then the data is submitted to GET:mysite/resource_one. This seems odd to me in a system that seems to be designed to allow full CRUD to be preformed on a resource, without leaving said resource.
So.. what is the proper method? I mean, if GET:mysite/resource_one/edit is right, then why not GET:mysite/resource_one/delete, GET:mysite/resource_two/create, and so on..
Replies much appreciated!
The URL always represents the resource, not the action. Thus, while mysite/resource_one/edit might be a proper URL to a page that initiates editing a resource, it's not a part of the REST API itself, it's part of the web app that uses that REST API to manipulate that resource. Moreover, in that example mysite/resource_one would be a confusing representation of the resource.
To create a new resource, you use POST on the parent resource, with the body of the request containing the data for the new resource. The response contains the URL for the newly created resource.
To update an existing resource, you use PUT on the resource URL, with the body of the request containing either full or partial update of the resource data.
We are trying to implement a REST API for an application we have now. We want to expose read/write capabilities for various resources using the REST API. How do we implement the "form" part of this? I get how to expose "read" of our data by creating RESTful URLs that essentially function as method calls and return the data:
GET /restapi/myobject?param=object-id-maybe
...and an XML document representing some data structure is returned. Fine.
But, normally, in a web application, an "edit" would involve two requests: one to load the current version of the resources and populate the form with that data, and one to post the modified data back.
But I don't get how you would do the same thing with HTTP methods that REST is sort of mapped to. It's a PUT, right? Can someone explain this?
(Additional consideration: The UI would be primarily done with AJAX)
--
Update: That definitely helps. But, I am still a bit confused about the server side? Obviously, I am not simply dealing with files here. On the server, the code that answers the requests should be filtering the request method to determine what to do with it? Is that the "switch" between reads and writes?
There are many different alternatives you can use. A good solution is provided at the microformats wiki and has also been referenced by the RESTful JSON crew. As close as you can get to a standard, really.
Operate on a Record
GET /people/1
return the first record
DELETE /people/1
destroy the first record
POST /people/1?_method=DELETE
alias for DELETE, to compensate for browser limitations
GET /people/1/edit
return a form to edit the first record
PUT /people/1
submit fields for updating the first record
POST /people/1?_method=PUT
alias for PUT, to compensate for browser limitations
I think you need to separate data services from web UI. When providing data services, a RESTful system is entirely appropriate, including the use of verbs that browsers can't support (like PUT and DELETE).
When describing a UI, I think most people confuse "RESTful" with "nice, predictable URLs". I wouldn't be all that worried about a purely RESTful URL syntax when you're describing web UI.
If you're submitting the data via plain HTML, you're restricted to doing a POST based form. The URI that the POST request is sent to should not be the URI for the resource being modified. You should either POST to a collection resource that ADDs a newly created resource each time (with the URI for the new resource in the Location header and a 202 status code) or POST to an updater resource that updates a resource with a supplied URI in the request's content (or custom header).
If you're using an XmlHttpRequest object, you can set the method to PUT and submit the data to the resource's URI. This can also work with empty forms if the server supplies a valid URI for the yet-nonexistent resource. The first PUT would create the resource (returning 202). Subsequent PUTs will either do nothing if it's the same data or modify the existing resource (in either case a 200 is returned unless an error occurs).
The load should just be a normal GET request, and the saving of new data should be a POST to the URL which currently has the data...
For example, load the current data from http://www.example.com/record/matt-s-example and then, change the data, and POST back to the same URL with the new data.
A PUT request could be used when creating a new record (i.e. PUT the data at a URL which doesn't currently exist), but in practice just POSTing is probably a better approach to get started with.