How to enable/disable HTTP methods for RESTful Web service? - rest

I'm writing a RESTful Web service.
Technologies that I use:
Eclipse EE Kepler IDE
GlassFish 3 (based on Java 6)
Jersey
JDK v7
When I annotate a Java method with, for example, the #DELETE annotation
I get the following HTTP error (invoked via URI):
HTTP Status 405 - Method Not Allowed
I would like to know how to enable/disable (so that to enable/disable the above HTTP error) those methods (PUT, HEAD, etc.) and at which level it can be done (Glassfish, Web.xml, etc). As well, can you invoke all of those resource methods (annotated with HTTP method type) from either Web browser's URI, within the <form>, or stand-alone client application (non-browser)?
For example, whether or not the following config line on deployment descriptor is present, it makes no difference:
<security-constraint>
<web-resource-collection>
<web-resource-name>RESTfulServiceDrill</web-resource-name>
<url-pattern>/drill/rest/resource/*</url-pattern>
<http-method>DELETE</http-method>
</web-resource-collection>
Of course, one's can disable a specific resource method by throwing an exception from it (and map it to an HTTP error) as the indication of it. That would indicate that the implementation is not available, for example.
So far, only #GET and #POST (on the <form>) resource methods work out, the other annotated methods, such as #POST (via URI), #PUT, #DELETE, #OPTIONS returns the above HTTP error. And this is where my question needs solutions. Why does the mentioned resource methods cause HTTP error when the former two don't?
An example of a resource method:
#DELETE
#Consumes(MediaType.TEXT_PLAIN)
#Produces(MediaType.TEXT_PLAIN)
#Path("/getDelete/{value}/{cat}")
public String getDelete(#PathParam("value") String value, #PathParam("cat") String cat){
return value+" : "+cat;
}
Invoking URL:
getDelete
The deployment descriptor is empty, except for the above lines of XML code. So far, I made the app to work by using annotations, no Web.xml (only contains some default values, such as index.jsp files).
Any ideas out there?

To my understanding, You have your REST APIs exposed and you are trying to access it from HTML <form>.Now you are able to access the GET and POST methods(REST APIs) from HTML <form> but not PUT, DELETE and other HTTP methods.
The reason why you get Method Not Allowed exception when you try to access DELETE or PUT or other HTTP methods is, HTML <form> does not support methods other than GET and POST.
Even if you try
<form method="delete"> or <form method="put">
HTML will not understand these methods and consider this as simply <form> (i.e) default form method is GET.
So even you have mentioned method as DELETE or PUT. It is a GET request.
And when the call is made, the jersey container tries to find the requestpath(here"/getDelete/{value}/{cat}") with the specified method(here GET).
Though this path exists,you have mentioned DELETE as acceptable method in your resource(#DELETE annotation says so). But Jersey is looking for GET now.Since it cant find #GET, it returns Method not allowed Exception.
So, how to solve it?
In HTML <form> you cant use HTTP methods other than GET and POST. It is better to have a wrapper in between the REST layer and HTML. So that you can make a POST call from your HTML, then the wrapper handles that call and which in-turns calls the DELETE of REST layer.
And, why POST method is not working from browser is, By default Browser makes a GET call. Have a look at Postman to make REST calls with different Http methods.

Related

How to redirect the url from nested site in pencilblue?

I want to 301 redirect the URLs from previous site that are nested, as pencilblue doesn’t support them,
e.g. a/b to page/b
For this I have been experimenting in include/http/request_handler.js but facing some issues.
Call never comes inside RequestHandler.prototype.handleRequest or even RequestHandler.prototype.onSessionRetrieved (seems these methods are not being called from anywhere)
Therefore I placed the code in RequestHandler and after confirming that req is not for public resource or api, I create a new url and execute
return this.doRedirect(newUrl, 301)
This actually works but at the same time I receive
Can’t render headers after they are sent error
#1075 has not helped me much as I’m not sure which specific controller I should modify. I need to catch the req as early as possible and see if it’s a page then redirect to page prefixed url.
Thanks in advance.
There are couple of ways to do redirects. You can do them from a controller or from middleware. You are correct in that, some of the functions in the request handler are not called. These are deprecated despite the fact pencilblue team didn't mark them as such. They replaced a good deal of the request handler functionality with /include/http/router.js and include/http/middleware/index.js. Plugins can register their own middleware to hijack the request pipeline.
See Advanced Routing on wiki for more info about creating your own middleware.
Using the routing framework your plugin would be able to register middleware that would be able to inspect the request and then redirect based on your specific criteria. The Router will be accessible from req.router and from there you could call req.router.redirect (Source).
Reference: #1224

HTTP Options method is not working as expected

I have a Jersey 2.x application running in tomcat. All the method implementations are working as expected, and even I am able to get WADL by navigating to http://{host}:{port}/JerseyRESTWebapp/ws/rest/application.wadl.
Everything is great so far.
Now, Out of curiosity I tried navigating to http://{host}:{port}/JerseyRESTWebapp/ws/rest/employees URL using using HTTP OPTIONS method expecting i will get 405 Method not allowed but i got the 200 OK and response body contains the WADL. Can someone let me know why is this happening? I am using POSTMAN chrome extension as REST client.
Also in the Response Allow Header, i am getting POST,GET,DELETE,OPTIONS,HEAD. I am missing PUT method here. why?
This is how the resource discovery works by default. It's implemented to follow the spec in regards to OPTIONS resource discovery
This method allows the client to determine the options and/or requirements associated with a resource, or the capabilities of a server, without implying a resource action or initiating a resource retrieval.
If you want to disable the WADL, you can by setting the property ServerProperties.WADL_FEATURE_DISABLE to true.
If you're curious about how this is implemented, check out the source for the WadlModelProcessor. It goes through all the resource models and adds an extra OPTIONS resource method. You can read more about the ModelProcessor in the Jersey docs Programmatic API for Building Resources

GWT Async to URL

I'm using GWT to develop a web app. I'm currently using AJAX calls to retrieve values from the server. I have following queries regarding to AJAX calls:
Assume: I have an app, name of which is: "Application" and the entry point class is: "entry.java"
I know: the application could be invoked as: http://localhost:8080/Application/entry.html
1. I would like to know what what is the output URL given by gwt.getmodulebaseURL()?
Assume: In the same application I have a service called "ServerValuesService" and its corresponding Async. I have corresponding serviceImpl, which has a method called List < String >search(String) at the server side.
I could retrieve the values from the server as well. However,
2. I would like to know what would be the direct URL to access this service? For Instance, I need to obtain the list of values, by just giving a URL (passing value for the String). i.e. I need to access the method search(String) and retrieve the list just by typing a url such as:
http://localhost:8080/Application/entry/serverValuesService?string="hello"
I'm sure the above URL is wrong. I need to know exact conversion between URL and the corresponding service. Is this possible at all?
Thanks in advance!
1) In your case it will give you http://localhost:8080/Application . Application is your modulename.
2) These services are actually HttpServlets and their URL's are defined in the web.xml file. But Google uses POST method to send your variables and takes care of serialization for you, what you are trying to do is send it via GET method which is as far as I know not implemented by Google RemoteServiceServlet.So I would say no its not possible unless you extend these services to work with GET methods yourself but I don't know if that is possible.
Assume: I have an app, name of which is: "Application" and the entry point class is: "entry.java"
I know: the application could be invoked as: http://localhost:8080/Application/entry.html
The url http://localhost:8080/Application/entry.html is called host page url. In this html page you load your GWT module using a script tag:
<!-- This script tag is what actually loads the GWT module. The -->
<!-- 'nocache.js' file (also called a "selection script") is -->
<!-- produced by the GWT compiler in the module output directory -->
<!-- or generated automatically in hosted mode. -->
<script language="javascript" src="calendar/calendar.nocache.js"></script>
So if you put above example in your entry.html, the module will be loaded from http://localhost:8080/Application/calendar/calendar.nocache.js making http://localhost:8080/Application/calendar/ your module base url.
I would like to know what would be the direct URL to access this
service? For Instance, I need to obtain the list of values, by just
giving a URL (passing value for the String). i.e. I need to access the
method search(String) and retrieve the list just by typing a url
GWT RPC use a custom serialization format to encode requests to the RPC Service on server. The RPC service is implemented as a subclass of RemoteServiceServlet on the server. The RemoteServiceServlet handles the http POST requests, de-serializing the request from client and invvoking appropriate service method of sub-class.
So for directly accessing the service you'll need:
1. The service URL
2. Request payload encoded in GWT's custom serialization format
3. Ability to HTTP POST the payload to the Service URL
1 and 3 are easy to acquire. You already know the URL at which your service is mapped in web.xml. And you can do post from any http client or browser plugins like this. The hard-part would be to generate request payload in GWT's custom serialization format. For simple cases, you can generate a request from your application and capture the raw payload from Firebug, Fiddler or similar tool and simply replay it using your http client.

How to invoke RESTful services from HTML forms?

We're using Grails for building RESTful services which we'll call from browser clients using HTML forms, the problem is that forms only support GET and POST, so we're not sure how to handle PUT and DELETE.
Grails template tags can help you there:
However, issuing a request with a method other than GET or POST from a regular browser is not possible without some help from Grails. When defining a form you can specify an alternative method such as DELETE:
<g:form controller="book" method="DELETE">
..
</g:form>
Grails will send a hidden parameter called _method, which will be used as the request's HTTP method. Another alternative for changing the method for non-browser clients is to use the X-HTTP-Method-Override to specify the alternative method name.
Via: http://www.grails.org/doc/latest/guide/13.%20Web%20Services.html

GWT JSONP with Post not Get

I have a web service in the form `http://....../methodName
It returns a jsonp result such as:
methodName(["a":"a", "b":"b"])
GWT provides JsonpRequestBuilder class to parse jsonp.
JsonpRequestBuilder rb = new JsonpRequestBuilder();
rb.setCallbackParam("callback");
rb.requestObject("http://...../methodName", new AsyncCallback<TestJS>(){
...
});
This structure makes a request to url :
"http://...../methodName/?callback=__gwt_jsonp_P0.onSuccess".
My web service returns a callback with methodName not with __gwt_json.....
So gwt could not create a JavaScriptObject from that response.
Also JsonpRequestBuilder works with GET not POST.
How can I achieve those: Sending requests with POST and modifying GWT's default callback name.
JSONP will NOT work with POST. Its not a GWT limitation btw.
JSONP is essentially including a javascript file from your server. So, when you make a JSONP call, a temporary tag is added to the DOM.
Now, a <script> tag can always makes a GET request. That's a browser thing, and GWT cannot do much about it.
If you want to make a cross-domain POST call, you have to chose from one of the following options (and they have nothing to do with GWT)
Use Flash plus a crossdomain.xml that allows cross domain posts
Use Cross Origin Resource Sharing, or CORS. NOTE that this is only supported in modern browsers
Use a proxy server on your domain
Unfortunatly, this isn't how JsonP works. The requests are made by adding a tag to the page, and the results are passed into a function wrapped around the data – in your case, __gwt_jsonp_P0.onSuccess.
The callback name can't be affected, at least while using JsonpRequestBuilder – the system needs to account for the fact that you could send multiple requests out at once, possibly even to different endpoints. A JsonP endpoint that doesn't allow the caller to customize the callback function name is very unusual, and even more odd is an endpoint expecting JsonP calls that expects an impossible POST.
You can implement your own JsonP client side code by using the ScriptElement type, and registering your own global callback to call into your GWT java code.
Look into the API docs for the web service, and see if there is perhaps a better way to communicate with it, perhaps by using a proxy on your own server, avoiding the cross domain issue altogether.