<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">FWIW, this is the passage in RFC 2616 that restricts the use of GET for state-changing requests:<div><span class="Apple-style-span" style="font-family: Times; "><h3><a id="sec13.9">13.9</a> Side Effects of GET and HEAD</h3><p>Unless the origin server explicitly prohibits the caching of their responses, the application of GET and HEAD methods to any resources SHOULD NOT have side effects that would lead to erroneous behavior if these responses are taken from a cache. They MAY still have side effects, but a cache is not required to consider such side effects in its caching decisions. Caches are always expected to observe an origin server's explicit restrictions on caching.</p><p>We note one exception to this rule: since some applications have traditionally used GETs and HEADs with query URLs (those containing a "?" in the rel_path part) to perform operations with significant side effects, caches MUST NOT treat responses to such URIs as fresh unless the server provides an explicit expiration time. This specifically means that responses from HTTP/1.0 servers for such URIs SHOULD NOT be taken from a cache. See section <a rel="xref" href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1">9.1.1</a> for related information.</p></span></div><div><br></div><div>Reading the details of this, we <i>could </i>have written UWS to start queries using GET, but then we'd have to qualify it with "and then you must do x, y and z with the response headers to turn off caching". This is extra work for the implementor and quite unecessary because a POSTed request is naturally uncached. Creating a sub-resource is exactly what POST is for.</div><div><br></div><div>The particular caching cock-up I had in mind works like this:</div><div><br></div><div>1. You GET the job list with query-starting parameters.</div><div>2. The service starts a query and returns 303 "See other" redirecting to the new job</div><div>3. The web server tacks on some default cache-expiration because, hey, it's a GET response and we're suppose to cache those.</div><div>4. You GET the job list again with parameters for another query.</div><div>5. The web-cache sends you back the 303 for the first query and the TAP service never sees the request.</div><div><br></div><div>Maybe this only catchs you out if the queries in steps 1 and 4 are the same - i.e. same URL including query string. Not sure about the details there...meaning that it's subtle and scary and dangerous to depend on this kind of usage. On the other hand, using POST makes it 100% certain that the cache won't swallow your request.</div><div><br></div><div>In respect of job lists getting cached what sees to happen with Java is this: when you GET a response from a servlet or JSP, everything works as expected with dynamic content; you never seem to get a stale page. However, when the same servlet engine delivers a static HTML page, or a CSS stylesheet or (particularly) and XSLT for in-browser transformation then it caches like hell and you can easily miss updates. (This bit me repeatedly when I was setting up the browser-side styling of the job resources for my TAP implementation.) Something in the servlet engine seems to know when the content should be dynamic and adjusts the HTTP headers appropriately.</div><div><br></div><div>Cheers,</div><div>Guy</div><div><br></div><div><br></div><div><div><div>On 2 Nov 2009, at 16:56, Tom McGlynn wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Guy Rixon wrote:<br><blockquote type="cite">Tom,<br></blockquote><blockquote type="cite">if you want to get the job list then go ahead and do HTTP-GET. That's  part of UWS (although implementations may restrict the set of you  reported to be those owned by the caller). What you can't do is use  HTTP-GET to submit a query via UWS. If you want to use GET to do a  query then you're doing a synchronous query by definition.<br></blockquote><blockquote type="cite">Cheers,<br></blockquote><blockquote type="cite">Guy<br></blockquote><br>But I recall from earlier in this discussion some clever fellow said...<br><br><blockquote type="cite">GET responses can be cached, and the caching is out of your control as a service provider - it may be on the user's LAN (HTTP proxy) or in their client (browser cache). If you send the same query twice then via GET, <br></blockquote>> for the second request you could get the response for the first, pulled from the cache,<br><blockquote type="cite">and no new job.<br></blockquote><br>If what you said earlier is correct, then I can't rely on what I get back from a GET call.  I might be getting a cached response and not the current state of the system.  If caching is truly an issue, then there doesn't seem to be any reliable way to get the job list.<br><br>Tom<br><br><blockquote type="cite">On 2 Nov 2009, at 14:13, Tom McGlynn wrote:<br></blockquote><blockquote type="cite"><blockquote type="cite">Paul Harrison wrote:<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">Guy has already done a good job of answering most of these points - I<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">The UWS design of the two stage process is for two principal reasons<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">a) to be able to manipulate job metadata parameters before the job is<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">run - e.g. the DestructionTime - and receive the feedback from the<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">service whether it is prepared to honour such requests before  actually<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">committing the job.<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">b) to allow complete parameter namespace freedom on the job creation<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">step - i.e. if PHASE is used by UWS then it could not be a parameter<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">for the implementation protocol.<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">So if for a particular implementation using UWS there is no problem<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">with meeting that second condition, then there is no particular  reason<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">why job metadata parameters could not be included with the initial  UWS<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">job creation step if desired - this would require revision of the UWS<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">specification to include this possibility - I think that this is a<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">small enough change to be added into the document as part of the  RFC -<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">it does have a larger impact on possible service implementers however<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">- their code might not be structured to allow this change easily. For<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">a generalized UWS client the change would not be so great, all that<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">would happen is that after the initial submission a job object would<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">be returned with the PHASE=EXECUTING, and general clients should not<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">make any assumptions about state in their coding, so should probably<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">still be able to react appropriately.<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">Just as a side note to show that UWS is not so strange in this<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">multiple interaction between client and server - consider what  happens<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">when a web browser loads a web page - it does the initial get of the<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">html, then parses this html and then gets images, javascript etc.<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><blockquote type="cite">before the page is shown to the user.<br></blockquote></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">I trust the goal is not to require that UWS services need to have  the complexity of an interactive visual Web browser.  The protocol  should cater to simple applications as well.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">I'd be perfectly happy with a change that made it clear that the  request that created the job could return it in any state.  In fact,  even without the desire to be able to start jobs at creation, that  is probably needed to accommodate the situation where there is a  problem detected in creating the job but we want the user to be able  to parse the error with IVOA protocol level error handling.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">The specific text that I find problematic is in 2.1.3:<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"> PENDING: the job is accepted by the service but not yet committed  for execution by the client.  In this state the job quote can be  read and evaluated.  This is the state into which a job enters when  it is first created.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">in conjunction with<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">2.2.3.1 Creating a job.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Posting a request to the job list creates a new job (unless the  service rejects the request).<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">I would suggest something like the following changes<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">In 2.1.3 add somewhere<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">  Phases are ordered with PENDING before QUEUED, QUEUED before  EXECUTING and EXECUTING before the trio of COMPLETED, ABORTED and  ERROR.  The state of a job may change only to a later state but need  not pass through any intermediate state.  A job may be created in  any state.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Delete the last sentence in the definition of PENDING.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">-<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">I think it would be desirable to suggest how a job could be created  in the run state even if this is not required by the standard  It  would be possible to do this without polluting the parameter name  space by specifying a new URI for that.  E.g., ${jobs} creates a new  request but does not start it.  ${jobs}/run could create and start  the job if that is permitted in the given service.  However I find  the worry about pollution of the parameter name space less than  compelling, since we require certain parameters to be used in calls  to start the job running or to alter other aspects of the job.  It  would be poor practice to have phase= mean one thing in a job  creation request and mean something else in a job update request.   In effect, these parameters are reserved already.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">This discussion brought up another thing that's not really clear.  2.2.3.1 has the little parenthetical phrase "(unless the service  rejects the request)" which is neither explained, nor is the action  implied in rejection specified.  I think something like:<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">  Errors may occur in the creation of the job.  Where possible a job  should be created in the ERROR phase with a error message that  describes the problems.  If this is not possible, an HTTP 500 error  must be returned.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">would be clearer for implementation and should replace that phrase.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">Finally,  one new issue/concern.  [This probably reflects a lack of  understanding on my part but if so then perhaps it could be  clarified in the standard.]:  It doesn't seem like there is any  valid way to get the current job list.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">I can't do a GET request for  /{$jobs} because that's cacheable and  the list is dynamic.  And I can't do a POST request for it since a  post to /{$jobs} means that I'm creating a new job and I'm supposed  to be redirected to the job information for the newly created job.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">So how do I get to it?<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite">In my TAP implementation I assume that any request to create a new  job needs to have a REQUEST= parameter and if I don't see this I  return the job list.  If I do, I create the new job.  However this  doesn't seem to be literally correct.  I suppose you could say that  I'm 'rejecting' the request and since that behavior is undefined I  can do anything I want. Relying on undefined behavior doesn't seem  satisfactory.<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><span class="Apple-tab-span" style="white-space:pre">  </span>Tom<br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote><blockquote type="cite"><blockquote type="cite"><br></blockquote></blockquote></div></blockquote></div><br></div></body></html>