RESTful service using only GET and POST methods - node.js

RESTful services are implemented currently with GET, POST, PUT , PATCH and DELETE
or at least using 4 of that. (usually method PATCH is not used).
Is it possible to implement a RESTful API using only GET and POST
making the post behave as a POST, PUT or DELETE, depending on some parameter passed in url or headers or just as that article mention doing a semantic url like:
/users/delete
/users/update
I was searching something like that and found that article but it is not very complete and is a little old.
https://www.infoq.com/news/2010/06/get-post-alone-restful
I know that in some web frameworks (like Django) they only allow method POST and GET, but i think this occur for compatibility reasons, with previous versions of the framework.
In one hand Fielding talking about restful services the unique restriction is about semantics, but using the example above we have a sematic use ok.
Without ambiguity between a POST or PUT or DELETE.

Yes, it is possible and it is even often done in practice for some specific use cases - for example because you can only use GET and POST in HTML forms, or when you need to have "PATCH" but it is not supported by the clients that you need to cooperate with.
If you use Express, there is method-override module:
https://github.com/expressjs/method-override
that lets you have an HTML form like:
<form method="POST" action="/resource?_method=DELETE">
<button type="submit">Delete resource</button>
</form>
that would delete a resource instead of posting it.
The method override is usually done with a query parameter like "_method" above or with a special header like "X-HTTP-Method-Override" that can be set to "DELETE" or "PATCH" or whatever you want.

Related

Why do we even need anything other than POST and GET HTTP protocols?

Why can we not just use POST and GET? I feel like everything that PUT PATCH DELETE etc can do can also be done by POST and GET, plus it’s a lot simpler.
Each HTTP verb has a very specific semantic to guide it's usage. Yes, you can use POST to update or delete something in the server, or even use GET method to do any changes, but using PATCH and DELETE for instance makes it much more clear to whoever human is reading it. Also you can have the same URL path with different behavior according to the HTTP verb.

Correct way to implement a REST API using MVC

Summary
I am seeing a lot of contradictory architectural examples of a REST API in my work and keep getting different opinions on the subject.
I am familiar with the principles of REST and seeing as each endpoint points to a resource followed by a verb such as /project/create project/123/read.
Following the MVC pattern assuming I have a controller that is responsible for updating a project resource:
router.put("/project/:id/update", ProjectController.put)
First question:
Should this route be responsible for all updates to this resource, in example, assuming different features on my client like marking a project as finished or changing it's title are separated and might not have anything in common for the user. Ending up with the route described above, or should there be something like this:
router.put("/project/:id/mark-as-done", ProjectController.markAsDone)
router.put("/project/:id/update-info", ProjectController.updateInfo)
Second question:
Assuming I want to create a notification resource if a project is created/updated/deleted. Since the notification is a resource on it's own I am not sure how to go about this, but what I assumed and was taught is to use another callback:
router.put("/project/:id/update", ProjectController.put, NotificationController.create)
Third question:
Could I use the same controller to read all resources or just one, for example:
router.get("/project/read", ProjectController.get)
router.get("/project/:id/read", ProjectController.get)
Making the logic in the controller method determinate if it will return all projects or just one. Or should it be separated into different methods?
I would define APIs like this:-
CRUD for Project entity
create- router.post(/projects)
update:- router.put(/projects/:id)
delete:- router.delete(/projects/:id)
read:- router.get(/projects) and/or router.get(/projects/:id)
You can define all above routes in ProjectController.
Regarding Notification entity you can define as follows
read:- router.get(/projects/:id/notifications)
The same can be applied to PUT, DELETE, POST
Here is a good article defining rest guidelines https://stackoverflow.blog/2020/03/02/best-practices-for-rest-api-design/

Breeze JS Security and Headers

We have used Breeze in our solution and it is working well. However, we are now at a place where we need to pass some identifying information as part of the header when we make the WebAPI call. How is this accomplished with Breeze queries?
I assume this link should help you;
http://www.breezejs.com/documentation/controlling-ajax
In general, you need to configure the internal ajax adapter (probably jQuery) before making a request.

Post Form to a page in CQ5

I have a custom search component which searches for some parameter(s) from a dropdown [myParam] and displays the search results in another page. I currently use the default (GET) form
<form id="searchForm" action="/content/myWeb/searchResult.html" method="get" target="_blank">
In the result page, a component picks up the request params and processes the search.
I need to make it a POST submission so that the search parameters are NOT visible in the URL. But if I make it a method="Post" in the form above, I get this error:
Status
500
Message
javax.jcr.nodetype.ConstraintViolationException: no matching property definition found for {}myParam
Location /content/myWeb/searchResult
Parent Location /content/myWeb
Path
/path/to/search/page
That exception is the incidental way that Sling tells you that the servlet to which you are attempting to POST can not be found. What happens, in this case, is that Sling defaults to the SlingDefaultPostServlet, which attempts to to POST properties (represented by your form values) to the node /content/myWeb/searchResult. There's no way for Sling to say "I can't find a servlet that's registered to your request", so it just falls back to it's default behavior.
I'm assuming /content/myWeb/searchResult is a cq:Page node type. That node type is very restrictive, which is why it tells you that you cannot add properties that correspond to your form values.
This worked before, because your GET request to /content/myWeb/searchResult.html was able to resolve and execute. All GET requests to a page node can be served up by the system, inherently.
Now, since you are trying to do a POST, you need to create and register a new servlet that can handle this POST request. To do this, you'll need to create a SlingPostServlet and register it to your specific path (not recommended) or a specific selector/extension combination (recommended). That servlet should process the request parameters and respond with an HTML document.
A caveat...
What I just described will help you technically build what you are asking. That said, I don't agree with the premise that you should "make it a POST to hide the request parameters." The reason this is so much extra work, is because you are circumventing the principles of REST, which Sling is theoretically built to support. Your URL (via request path and parameters) should be communicating "I want the page at /content/myWeb/searchResult, given the criteria param1=x, param2=y, and so on". The GET with request params is an appropriately RESTful request.
I suggest you rethink what you're trying to do. Building a more complex solution around RESTful principles is not a good practice.
Just as a sidenote, you can always check if a given URL is bound to a servlet via the sling servlet resolver. Reachable via the OSGI-console or via URL:
http://localhost:4502/system/console/servletresolver
This can at least help you find closure on, if the servlet is registered to the given URL.
You can create a POST.jsp for your page, which could handle the POST request.
It is not restful to make get like request with POST, but sometimes it can be useful. Also With POST, dispatcher won't cache your request.

How can Socket.io and RESTFul work together?

(I'm not familiar to RESTFul, please correct me if my concept is wrong)
In RESTFul architecture, we map every action to an URL. If I click "post a article", may it's actually URL http://example.com/ and some data action=post&content=blahblah.
If I want to post, but not refresh the whole web page, I can use javascript's XMLHTTPRequest. I post it and then get it's content and insert it to a div in my page. These action is all asynchronous.
Then I know there is something named WebSocket and it's wrapper socket.io. It use "message" to communicate between client and server. When I click "post" the client just call socket.send(data) and wait for server's client.send(data). It's magical. But how about URL?
It's possible to use the two model both without repeating myself? In other word, every action has it's URL, and some of them can interact with user real-timely(by socket.io?)
Moreover, should I do this? In a very interactive web program(ex. games), the RESTFul is still meaningful?
You're defining a handler for actions that map to REST over http. POST and GET generally refer to update and query over an entity. There's absolutely no reason you can't just define a handler for generic versions of these CRUD operations that can be used in both contexts. The way I generally do this is by introducing the concept of a 'route' to the real-time transport, and mapping those back to the same CRUD handlers.
You have a session, you can impose the same ACL, etc.
 +---------------------------------+
 |                                 |
 |      BROWSER                    |
 |                                 |
 +--+--^-------------------+---^---+
    |  |                   |   |
    |  |                   |   |
 +--v--+---+            +--v---+---+
 |         |            |          |
 | HTTP    |            | SOCKET.IO|
 +--+---^--+            +--+---^---+
    |   |                  |   |
 +--v---+------------------v---+---+
 |                                 |
 |        ROUTING/PUBSUB           |
 +-+--^-------+--^-------+--^------+
   |  |       |  |       |  |
 +-v--+--+  +-v--+--+  +-v--+-+
 |       |  |       |  |      |
 | USERS |  | ITEMS |  |ETC   |
 +-------+  +-------+  +------+
     ENTITY CRUD HANDLERS
I posted this on my blog recently:
Designing a CRUD API for WebSockets
When building Weld, we are using both REST and WebSockets (Socket.io). Three observations on WebSockets:
Since WebSockets are so free-form, you can name events how you want but it will eventually be impossible to debug.
WebSockets don’t have the request/response form of HTTP so sometimes it can be difficult to tell where an event is coming from, or going to.
It would be nice if the WebSockets could fit into the existing MVC structure in the app, preferably using the same controllers as the REST API.
My solution:
I have two routing files on my server: routes-rest.js and routes-sockets.js
My events look like this example: "AppServer/user/create".
I use forward slashes (“/”) to make the events look like routing paths.
The first string is the target (~”host name” if this actually was a path).
The second string is the model.
The third string is the CRUD verb: i.e. create, read, update, delete.

Resources