Form Submission API
This API contains the OpenRosa standard API for submitting data to an OpenRosa compliant server and receiving a response from the server about the submission. This API is designed to provide a base level of interoperability between OpenRosa clients and servers while enabling application-specific extensions as well.
OpenRosa servers must be able to receive XForms which are submitted by clients over HTTP. There are 3 major categories of requirements for submission which must be fulfilled: channel, content, and correctness.
OpenRosa servers MUST provide an HTTP URL capable of accepting HTTP POST's. Access controls, firewalls and geographic or networking restrictions MAY limit the origins and/or clients that can access the server.
The server MUST support HTTP 1.1 chunked transfer encoding for receiving the POST content. There is no minimum set of standards for timeouts, maximum content length, or other http configurations, but servers are encouraged to support lenient connections and the largest possible content size, since many of the connections will be from flaky channels and in environments where splitting content up is impractical.
For maximum compatibility with J2ME clients, it is recommended that a server SHOULD NOT issue redirects. Note that using digest authentication and https when communicating with a server does not require any redirects -- you can have authentication and secure transport without redirects.
OpenRosa submissions (and responses) MUST provide headers conforming to the OpenRosa Request standard.
Successful server responses MUST include an X-OpenRosa-Accept-Content-Length header in addition to the required OpenRosaRequest response headers. The X-OpenRosa-Accept-Content-Length header specifies this server's recommended maximum size for a POST body, in bytes.
Servers SHOULD include this header in their error responses. However, clients MUST NOT rely on the presence of this header (or any OpenRosa header) in every error response (e.g., overly-large requests sent to Google's AppEngine will be rejected prior to being sent to any server, and will therefore not contain this (or any) OpenRosa header).
OpenRosa submissions are POSTed to servers as a multipart MIME Envelope with at least 1 part (the xml content of the form itself). Each of these parts should adhere to the following requirements
- Content Type: multipart/form-data
- Contains Exactly 1 XForm Part
- Contains 0 or More Additional Parts
- Content Type: text/xml
- Name: xml_submission_file
- Content Type: arbitrary
- Name: matches an appropriate element inside of the XForm Element's XML.
Servers MAY be more permissive than this specification (allowing multipart/mixed for the mime envelope, for instance), but MUST be capable of recognizing and properly receiving submissions in this format.
Extended Transmission Considerations
If the client is capable of negotiating authenticated and/or secure transmissions to the server, it is recommended that the client first attempt a HEAD request to the server to negotiate the authentication and channel security prior to the first POST of the data, regardless of any channel security stated in the <submission> block of the form. This ensures that submitted data is not inadvertently sent in the clear on that first request due to the client device possessing an out-of-date form definition with an inaccurate <submission> block. Issuing a HEAD request first also reduces overall transmission bandwidth in instances where client authentication occurs. Most authentication handshake protocols require the complete re-POST of the original request after the authentication is complete. By delaying the POST of the data until after the authentication has been negotiated on the HEAD request, overall transmission bandwidth is reduced.
The client, upon receiving the HEAD response, can check that the response contains the X-OpenRosa-Version header to indicate that the host is an OpenRosa server (as opposed to a network login screen or proxy page). In this way, the server can change the scheme from http: to https: or update the submission page URL without a wasted redirect during the actual submission process. The client can also use the value of the X-OpenRosa-Accept-Content-Length header to inform itself of how big a POST body should be sent to this server. ODK Collect also requires a 204 (No Content) status code in the HEAD response.
If a full POST of the form's xml submission and its additional parts (e.g., captured image, audio or video clips) would exceed the size specified in the X-OpenRosa-Accept-Content-Length header (the "maxSize"), it is recommended that the client split the POST into multiple individual POST requests, each containing the form's xml submission and one or more additional parts such that each partial POST request is no greater than maxSize; if a single additional part is greater than maxSize, the POST should contain the form's xml submission and that single additional part. Regardless of whether the client observes and honors the X-OpenRosa-Accept-Content-Length header, a compliant server with give its best effort to accept submissions of any length.
The X-OpenRosa-Accept-Content-Length header is provided to avoid failures that may otherwise arise due to restrictions on the overall size of HTTP messages, or due to physical or virtual memory configurations of the server.
The form's xml submission is sent on each POST so that a client can avoid having any knowledge about the content of the files it is shipping around. Doing so also places the fewest restrictions on how the server handles the submission.
Rationale for sending the form's xml submission
To avoid sending the form's xml submission, you would need to inspect the submission and send up its identifiying information -- i.e., the instanceID. By avoiding inspection of the submission, a much simpler Ajax-enabled webpage could conform to this API.
On the server, having just the instanceID sent on subsequent POSTs might not be sufficient to process the request -- sending only this information would burden those server implementations with maintaining a mapping from the instanceID to the natural key for this data. Not sending the form's xml submission in subsequent POSTs biases against some server designs.
Finally, since most xml submission documents are smaller than 2K bytes, and if you have a 10M byte threshold for splitting a submission across multiple POST requests (a reasonable lower limit), you're burning only 0.02% of your bandwidth with the retransmission.
The server MUST consume an entire HTTP POST in conformance with that protocol. Once a POST is received, the range and structure of the server's response is specified below.
Server Response Format
The server response format will be XML formatted, and the response body will be an OpenRosa Response.
Example response (see the above link for more information on this):
<OpenRosaResponse xmlns="http://openrosa.org/http/response"> <message>Form Received! You've submitted 5 forms today</message> </OpenRosaResponse>
If the server is RESTful, the server MAY return an HTTP URL (using the standard HTTP Location header) where the form can be found.
A form should not be assumed to be submitted until a 201 or 202 response code is received with an OpenRosaResponse envelope body.
Server Status Codes
Server status codes will be the same as [http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html standard http codes]. These use the general classification:
- 201-202 - Successfully received by server.
- 4XX - Client Error
- 5XX - Server Error
NOTE: I don't think "1XX - informational" or "3XX - redirection" should apply to these posts, but they may down the road. Some common interpretations of codes are below, but more could apply.
|200||UNUSED||Since the request is a post, a 200 response is not a sign of a successful submission. Many intermediate proxies will return a 200 response for gateway pages on WI-FI, etc, so receiving a 200 shouldn't be assumed to be meaningful|
|201||Form Received||Everything went great. Thanks for submitting|
|202||Accepted||We got and saved your data, but may not have fully processed it (e.g. couldn't match it to a schema). You should not try to resubmit.|
|204||No Content||Status returned in response to a HEAD request.|
|401||Unauthorized||Phone tried to post something it didn't have permission to post|
|403||Forbidden||You're not allowed to post there. Ever.|
|404||Not Found||Unknown url endpoint, domain, or other|
|413||Request too large||The request body is too large for the server to process|
|500||Internal Server Error||Something went awry on the server and we're not sure what it was|