Tuesday, August 21, 2012

Two leaky designs related to URL length limit

I discuss two cases of leaky design in this post. This first is Google Calendar, and the second is eBay POST caching.

Google Calendar

If you are using Google Calendar, you might have seen the broken droid with 414 code like this.

The reason for 414 is that the request URI is so long that the server refuses to handle. The maximum length of URL allowed by a server depends on its implementation. No matter it is 255 bytes or 2k characters or even 4k characters, it will reach the limit when URL is used to encoding a complicate request query parameters.

In the case of Google Calendar, when a user clicks the link to add events in GMail. An HTTP GET request is sent to Calender server with the details of the events encoded in the URL. For normal event often represented in iCalendar format, the URL can provide enough room for the data. Some event message might attach other extra text inside, when GMail tries to encode those into the request URI to Calendar, 414 might happen.

A possible solution can be a modified version of GMail that ensure a proper length of the URL with important information encoded inside. However, that is not a right solution. It is because the interface design between GMail and Google Calendar is not RESTful or simply does not follow the HTTP specification. HTTP GET is for retrieving the representation of a resource not for creating a new resource. A side effect of such a design is a duplicate even will be created every time a user clicks the same link and issues the same HTTP GET request.

A straightforward fix is to use POST to create a new event, and the details in the original email can then be easily included in the message body. 414 will never happen. In order to prevent creation of duplicated event, the server might need to verify if it is the same event that already existed on the same time slot.

If, in some cases, the designer really want to create a new resource by a GET request, the request URI should be able to identify the resource to be created. That is, instead return a 404, the server creates a new resource based on the request URI, and then returns the representation of that resource. For a server serves many concurrent clients that might request that URL at the same time, special care needs to be taken to prevent creation of duplication resource on the server and also holds the following requests until the resource representation is available. I developed such a service by using a Servlet Filter to do these tasks with Jetty continuation.

eBay POST caching

In this post, eBay engineer described their careful design of caching POST messages for eBay search. Two major motivation of this design is 1) to leverage the performance and scalability benefits of HTTP caching, and 2) to avoid the length limitation of HTTP request URI. I think the design is leaky because it might introduce extra special header to the message and very naturally not all the intermediaries can understand those headers and help the caching. The forward and reverse proxies in the diagram might only be the customized deployment of eBay.

As Akara Sucharitakul pointed out in his comment, a 303 can be used for the initial POST request,and then caching will work with the following GET. However, this does not reduce the round-trip time. My thought is to generate the MD5 key on the client via JavaScript, and then GET the resource identified by the key. If the user is lucky to be the first to issue such a request, a 404 will be returned, and then the client will do the real POST to create that resource on the server.

Thursday, October 13, 2011

Landscape table or image in LaTeX

A thumb rule for landscape table or image in LaTeX:
  1. If you are using latex+dvips+ps2pdf, use the sidewaystable or sidewaysfigure or just sideway environment in rotating package.
  2. If you are on pdflatex, use the landscape environment in pdflscape package instead. sideway prodices a sideway table/figure, but has problem to produce a right landscape view of the page in the pdf file.
For the second option, you might also need the afterpage package to have a properly floating page for the landscape table/figure without a half-blank page before it. The environment is like
\afterpage{
\clearpage
\thispagestyle{plain}
\begin{landscape}
\begin{table}[htp]
% your table here
\end{table}
\end{landscape}
\clearpage
}

Wednesday, March 9, 2011

Authentication in embedded Jetty 7 server

A change in Jetty security from 6 to 7 is the introduction of LoginService, which was designed to replace UserRealm based approach. The usage of LoginService can be seen in the example SecuredHelloHandler and the test case of SecuredContentExchangeTest . Basically, the LoginService needs to be attached to a SecurityHander, and the SecurityHandler needs to wrap the handler that needs the authentication service. This can be done by either
securityHandler.setHandler(yourHandler);

or

ServletContextHandler theContext = new ServletContextHandler(handlerContainer, contextPath, sessionHandler, securityHandler, servletHandler, errorHandler);


Thursday, February 10, 2011

Aptana Studio 2.0.5 on Ubuntu 10.04

Aptana Studio 2.0.5 used to work well in my Ubuntu 9.04. It started to split out error message related to xulrunner after I updated Ubuntu to 10.04. When I removed the Apatana and its workspace, it even stopped to show the messages and silently crashed. After digging and trying for almost an afternoon, I fixed the problem by adding this line to the AptanaStudio.ini file:
-Dorg.eclipse.swt.browser.XULRunnerPath=/usr/lib/xulrunner-1.9.2.13
You might change the path to whatever on your system. Note that there is a /usr/lib/xulrunner directory on my system, but that does not contain or link to the real literary files. I did not try if export the $MOZILLA_FIVE_HOME to the real xulrunner lib path will also work.

Tuesday, August 10, 2010

Eclipse Java test case cannot be found in a project?

Eclipse said "No tests found with test runner 'JUnit 4'". The answer in JUnit FAQ does not fix my case. And the answers on stackoverflow did not help as well. Later I figured out that the reason of the problem was that I did not properly organize the test cases in my project.

The Junit FAQ has a good suggestion. I have a default src directory for the source and a test directory for the test cases. In order to let the runner find the test case, the test directory has to be a Source Folder, not just a directory created in the project directory.

Thursday, April 22, 2010

Enable java in Firefox 3.0 on Ubuntu 9.04

I assume you have install the JVM or SDK already. If not, see this document for reference. Maybe you also need to use the update-alternatives tool to choose the latest version as the default. Then what you need to do is to ln the libjavaplugin_oji.so plugin in the mozilla plugins directory. Creating a link in the firefox plugins directory in your system won't work. You might use the following commands to locate the plugin and create the link.
locate libjavaplugin_oji.so
sudo ln -s {the latest java}/jre/plugin/i386/ns7/libjavaplugin_oji.so /usr/lib/mozilla/plugins/libjavaplugin_oji.so
Restart your firefox and you should be able to see java in the Add-ons list.

Thursday, February 11, 2010

dygraphs plot x-axis labels align with grids

Recently, I learned to use the dygraphs JS library for 2d chart. Dygraphs is designed to
display dense data sets and enable users to explore and interpret them.

I like it more than Flot, another JS ploting library.

One problem I found was that the x-axis labels do not align with the grids in FireFox, while it is fine in Chrome. The fix is quite simple, just never use align = center in the
where the plot is embedded. A note from the author of dygraphs.
dygraphs are not happy when placed inside a tag. This applies to the CSS text-align property as well. If you want to center a Dygraph, put it inside a table with align = center set.