1.March update: There is new issue at GAE tracker related directly to OPTIONS. Feel free to star it if you want that feature to be implemented.
During work at my java project RESTfulChecker, I reached a point where I needed to send OPTIONS HTTP method from RESTfulChecker to the remote API. OPTIONS method is defined in rfc2616 along with other HTTP methods such as GET, POST, PUT etc and is vital for REST. RESTfulChecker is running at Google App Engine, which is Google's cloud based solution for hosting (not only) Java apps. However upon building OPTIONS request I ran into following exception occurring when executed on Google App Engine:
java.net.ProtocolException: OPTIONS is not one of the supported http methods: [GET, POST, HEAD, PUT, DELETE]
at com.google.apphosting.utils.security.urlfetch.URLFetchServiceStreamHandler$Connection.setRequestMethod(URLFetchServiceStreamHandler.java:142)
at tk.ludva.ConnectionTestServlet.doGet(ConnectionTestServlet.java:18)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
at com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:102)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:249)
at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:923)
at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:76)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:135)
at com.google.apphosting.runtime.JavaRuntime$RequestRunnable.run(JavaRuntime.java:422)
at com.google.tracing.TraceContext$TraceContextRunnable.runInContext(TraceContext.java:449)
at com.google.tracing.TraceContext$TraceContextRunnable$1.run(TraceContext.java:455)
at com.google.tracing.TraceContext.runInContext(TraceContext.java:695)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:333)
at com.google.tracing.TraceContext$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:325)
at com.google.tracing.TraceContext$TraceContextRunnable.run(TraceContext.java:453)
at com.google.apphosting.runtime.ThreadGroupPool$PoolEntry.run(ThreadGroupPool.java:251)
at java.lang.Thread.run(Thread.java:679)
The exception is caused by this part of my code:
URL remoteUrl = new URL(apiUrl);
HttpURLConnection conn = (HttpURLConnection) remoteUrl.openConnection();
conn.setRequestMethod("OPTIONS");
Namely by conn.setRequestMethod("OPTIONS"); We can see from Stack Trace that the exception is raised by Google's URLFetchService. As far as I know, every request sent from your GAE application have to pass through that URLFetchService so unless it supports OPTIONS we are unable to send that request from our GAE apps.
We can check googleappengine's source and this part of urlfetch can confirm us about supported methods.
I found a posts related to this problem at GAE group but at the time of writing this blogpost, it's without reply:
Limited HTTP method on urlfetch API - need OPTIONS, PROPFIND ... by Wingi.
People want WebDAV suppport, there is even ticket in GAE's bugtracker for it.
Because mentioned post is about WebDAV's methods, I added my own dedicated to OPTIONS method only: OPTIONS is not one of the supported http methods?
If you know the solution for sending OPTIONS from GAE, kindly let me know or discus in threads mentioned.
sobota 25. února 2012
středa 15. února 2012
My project: RESTfulChecker on GitHub and GAE
First lines of my RESTful test tool has been written and it is time to share it. So for my colleagues and all who is interested, the sources of my project called RESTfulChecker is available at GitHub: https://github.com/lu2/RESTfulChecker
Also the dev version of my project is currently running atGoogle App Engine at the adress: http://restfulchecker.appspot.com/ http://ludva.tk:8080/RESTfulChecker/
Please note that my project at above links is work in progress so it may contain bugs, doesn't present intended functionality, or not be operational at all. Use it at your own risk - I do not bear any responsibility if it will detonate your computer (or head).
Anyway if you have any notes related to my work let me know. I would be happy to know your opinion.
Also the dev version of my project is currently running at
Please note that my project at above links is work in progress so it may contain bugs, doesn't present intended functionality, or not be operational at all. Use it at your own risk - I do not bear any responsibility if it will detonate your computer (or head).
Anyway if you have any notes related to my work let me know. I would be happy to know your opinion.
Přihlásit se k odběru:
Příspěvky (Atom)