Collect submission to custom PHP script - "Invalid status code on Head request"

Hi:

I'm trying to write a custom handler for Collect form submission in PHP.
I already have a the Collect form list/download working from my PHP
backend, but I'm having problems with the form submission handler.

(The form I'm using was designed with Build, and submits fine in Aggregate
on the Appstore.)

When I submit a completed form to my PHP script, the Collect client (1.09
and 1.2) reports:

"Invalid status code on Head request"

When I hit the submission URL with a browser (GET), the response headers are:
-----------------------------------------------------HTTP/1.1 200 OK
Server: Apache
X-Powered-By: PHP/5.2.17
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Content-Language: en
X-OpenRosa-Version: 1.0
X-OpenRosa-Accept-Content-Length: 2000000
Last-Modified: Wed, 11 Jul 2012 14:57:23 GMT
Content-Length: 0
Connection: close
Content-Type: text/xml; charset=utf-8

··· Date: Wed, 11 Jul 2012 14:57:23 GMT -----------------------------------------------------

A look at the Collect source code
(http://code.google.com/p/opendatakit/source/browse/src/org/odk/collect/android/tasks/InstanceUploaderTask.java?repo=collect&r=b46f3b677310b2a1001cd76ee2b92cae082c73d7)
seems to suggest that line 226 rejects any 200-299 response codes as
invalid - but as far as I understand it, 200 means OK, so I can't see why
it's detected as an error.

Can anyone help me see what I'm missing?

Thanks
nik

The primary problem is that if you are using WiFi, there can be
intermediate network login screens that may return 200's to the app. If
ODK Collect considered these to be successful responses, it might
erroneously report something as submitted when it, in fact, never reached
the ODK Aggregate server. So ODK Collect never considers a 200 to be a
successful submission response.

So we do several things:

The server returns a 204 (no content) upon receiving the HEAD request. We
return 204 because the response code to submission upload is dependent upon
the body of the submission request and we just don't know what to return
without that body (the HEAD request ODK Collect sends has no content body
-- it is just the URL without any POST content).

Upon receiving the POST containing the filled-in form, the server returns
either a 201 (created) or a 202 (accepted).

201 is returned if the filled-in form is saved and visible in the main
processing workflow of the server. This is returned even if the filled-in
form had been previously successfully uploaded to the server and is already
visible within that workflow (the upload outcome is idempotent).

202 is returned if the filled-in form is saved but is otherwise not in the
main processing workflow of the server. This occurs in some servers if the
form is unknown to the server, but it has logic that can accept and save
the submission documents proactively and communicate to the server
administrator that these submissions are available but lack a form
definition and therefore cannot be processed. ODK Aggregate never returns
202.

The server interactions and message formats are codified, without the
rationale, here: https://bitbucket.org/javarosa/javarosa/wiki/OpenRosaAPI

Mitch

··· On Wed, Jul 11, 2012 at 8:44 AM, blitheringeejit wrote:

Hi:

I'm trying to write a custom handler for Collect form submission in PHP.
I already have a the Collect form list/download working from my PHP
backend, but I'm having problems with the form submission handler.

(The form I'm using was designed with Build, and submits fine in Aggregate
on the Appstore.)

When I submit a completed form to my PHP script, the Collect client (1.09
and 1.2) reports:

"Invalid status code on Head request"

When I hit the submission URL with a browser (GET), the response headers are:
-----------------------------------------------------HTTP/1.1 200 OK
Date: Wed, 11 Jul 2012 14:57:23 GMT
Server: Apache
X-Powered-By: PHP/5.2.17
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Content-Language: en
X-OpenRosa-Version: 1.0
X-OpenRosa-Accept-Content-Length: 2000000
Last-Modified: Wed, 11 Jul 2012 14:57:23 GMT
Content-Length: 0
Connection: close
Content-Type: text/xml; charset=utf-8

A look at the Collect source code (
http://code.google.com/p/opendatakit/source/browse/src/org/odk/collect/android/tasks/InstanceUploaderTask.java?repo=collect&r=b46f3b677310b2a1001cd76ee2b92cae082c73d7)
seems to suggest that line 226 rejects any 200-299 response codes as
invalid - but as far as I understand it, 200 means OK, so I can't see why
it's detected as an error.

Can anyone help me see what I'm missing?

Thanks
nik

--
Mitch Sundt
Software Engineer
University of Washington
mitchellsundt@gmail.com

Mitch/Waylon: thanks for your comments, much appreciated.

Since I'm a lightweight PHP script kiddie (albeit a kiddie of 50-odd
years!), and definitely not a grownup Java programmer, it's more practical
for me to make my server app jump through whatever hoops the client needs
than it is for me to try to customise the client. :slight_smile: So your response code
strategy is safe with me - it looks as though I can issue the response
headers the client needs from PHP, even though I can't stop HTTPD issuing
its own 200 response code as well.

More generally, I wasn't able to find any guidance on setting up a PHP
backend for the Collect client, (apart from one post about PHPCake, which
I'm not using) - do you have any such docs available?

I'm now having some success with the form upload handler, via the usual
trial/error/cussing process. If you don't have a PHP howto, do you think
would it be of interest to the community if I put together a brief
explanation of a working handler?

BTW re your new release - 1.2 (1010) works nicely for me on Android 2.3.3
(HTC Wildfire).

Thanks
Nik

I am having the same problem bro.i successfully created xform parser and form uploader.all in php .all of them are working fine,except the submission.
if you find out any solution please help me...And also i am having the same error at the submission("Invalid status code on Head request").

Is this with ODK Aggregate, or a different server?

··· On Mon, May 13, 2013 at 12:38 AM, wrote:

On Wednesday, July 11, 2012 8:44:09 AM UTC-7, blitheringeejit wrote:

Hi:

I'm trying to write a custom handler for Collect form submission in PHP.
I already have a the Collect form list/download working from my PHP
backend, but I'm having problems with the form submission handler.

(The form I'm using was designed with Build, and submits fine in
Aggregate on the Appstore.)

When I submit a completed form to my PHP script, the Collect client
(1.09 and 1.2) reports:
"Invalid status code on Head request"

When I hit the submission URL with a browser (GET), the response headers
are:

HTTP/1.1 200 OK
Date: Wed, 11 Jul 2012 14:57:23 GMT
Server: Apache
X-Powered-By: PHP/5.2.17
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Cache-Control: no-cache, must-revalidate
Pragma: no-cache
Content-Language: en
X-OpenRosa-Version: 1.0
X-OpenRosa-Accept-Content-Length: 2000000
Last-Modified: Wed, 11 Jul 2012 14:57:23 GMT
Content-Length: 0
Connection: close
Content-Type: text/xml; charset=utf-8

A look at the Collect source code (
http://code.google.com/p/opendatakit/source/browse/src/org/odk/collect/android/tasks/InstanceUploaderTask.java?repo=collect&r=b46f3b677310b2a1001cd76ee2b92cae082c73d7)
seems to suggest that line 226 rejects any 200-299 response codes as
invalid - but as far as I understand it, 200 means OK, so I can't see why
it's detected as an error.

Can anyone help me see what I'm missing?

Thanks

I am also Running into same issue...Cannot get the Submission working
gives the same error "Invalid status code on Head request"

--
You received this message because you are subscribed to the Google Groups
"ODK Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to opendatakit-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

--
Mitch Sundt
Software Engineer
University of Washington
mitchellsundt@gmail.com

Hope this might help someone, a totally minimal PHP server to catch files
from ODK collect, no error checking but it works...

<?php $resp=201; if( $_SERVER['REQUEST_METHOD']==="HEAD") $resp=204; elseif( $_SERVER['REQUEST_METHOD']==="POST") { foreach( $_FILES as $file) { move_uploaded_file( $file['tmp_name'], '/tmp/uploaded_files/'.$file['name']); } } header( "X-OpenRosa-Version: 1.0"); header( "X-OpenRosa-Accept-Content-Length: 2000000"); header( "Date: ".date('r'), false, $resp); ?> Thanks

Mitch: thanks for your clear and concise explanation.

It's unfortunate that those working in my situation (PHP on a hosted
server where we have little control over the httpd config) might
struggle to make the server play nicely with your client response
status code strategy. I realise you're concentrating on providing an
end-to-end solution, but it would be nice to have some ability to
configure the client - for example, to accept 200 responses rather
than always assuming they might be erroneous and refusing to play
further. (Of course I can change the client source, but it doesn't
help that I'm a newbie at Java!)

What difference does it make when I change the server option in the
client? I've tried two different versions of Collect - the Market
version (1.1.7) has two "Server protocol" options, Aggregate and
OpenRosa, while v1.2 (1010) has three "Server Platform" options, for
Aggregate, Google Forms, and Other.

Is there a detailed explanation anywhere of how these different server
settings actually affect client/server interaction?

Thanks
Nik

We have no docs on working with PHP, though others in the past have hit
this same return-code issue with PHP servers. I flee from PHP, so I don't
know what their fix was (there was an earlier question on the list).

In general, if you are setting up a system to take responses and inject
them into another system, I would integrate the systems at a different
level -- just have ODK Collect talk to a Tomcat ODK Aggregate. Pick your
database server of choice (MySQL or PostgreSQL), then set up database
triggers to copy data out of the database tables defined by ODK Aggregate
and inject them into whatever tables your other app uses. You need to set
up the database triggers for each new form you add, which is a hassle, but
you can leverage the access control, data parsing and data checking
features of ODK Aggregate without writing those all yourself.

This isolates all the XForms parsing, etc. logic in ODK Aggregate, you can
work directly off the parsed data in the database tables, and you don't
have to worry about the evolution of the communications between ODK Collect
and the server (as slow as those changes might be).

Mitch

··· On Fri, Jul 13, 2012 at 4:02 AM, blitheringeejit wrote:

Mitch/Waylon: thanks for your comments, much appreciated.

Since I'm a lightweight PHP script kiddie (albeit a kiddie of 50-odd
years!), and definitely not a grownup Java programmer, it's more practical
for me to make my server app jump through whatever hoops the client needs
than it is for me to try to customise the client. :slight_smile: So your response code
strategy is safe with me - it looks as though I can issue the response
headers the client needs from PHP, even though I can't stop HTTPD issuing
its own 200 response code as well.

More generally, I wasn't able to find any guidance on setting up a PHP
backend for the Collect client, (apart from one post about PHPCake, which
I'm not using) - do you have any such docs available?

I'm now having some success with the form upload handler, via the usual
trial/error/cussing process. If you don't have a PHP howto, do you think
would it be of interest to the community if I put together a brief
explanation of a working handler?

BTW re your new release - 1.2 (1010) works nicely for me on Android 2.3.3
(HTC Wildfire).

Thanks
Nik

--
Mitch Sundt
Software Engineer
University of Washington
mitchellsundt@gmail.com

Hi Guys,

I know this could feel abit insane especially commenting on a issue 2 years old.

My boss insists of having ODK on a php server. I have tried googling following the threads here, but i still havent found a way out in getting a PHP ODK server, does anyone have a working solution or can point me into some directions on creating one.

Thanks.

··· On Thursday, March 13, 2014 at 3:39:00 PM UTC+3, John Cass wrote: > Hope this might help someone, a totally minimal PHP server to catch files from ODK collect, no error checking but it works... > > > > <?php > > > $resp=201; > > > if( $_SERVER['REQUEST_METHOD']==="HEAD") $resp=204; > elseif( $_SERVER['REQUEST_METHOD']==="POST") > { > foreach( $_FILES as $file) > { > move_uploaded_file( $file['tmp_name'], '/tmp/uploaded_files/'.$file['name']); > } > } > > > header( "X-OpenRosa-Version: 1.0"); > header( "X-OpenRosa-Accept-Content-Length: 2000000"); > header( "Date: ".date('r'), false, $resp); > > > ?> > > Thanks >

Google Forms -- uses OAuth to communicate to a google server. The Google
server was in beta a while back, but I am unclear of its current status.
Aggregate -- assumes the form discovery URL is the server URL plus
/formList and the form submission url is the server URL plus /submission
OpenRosa -- same as Aggregate, but you can edit and change these URL paths

Mitch

··· On Thu, Jul 12, 2012 at 8:32 AM, blitheringeejit wrote:

Mitch: thanks for your clear and concise explanation.

It's unfortunate that those working in my situation (PHP on a hosted
server where we have little control over the httpd config) might
struggle to make the server play nicely with your client response
status code strategy. I realise you're concentrating on providing an
end-to-end solution, but it would be nice to have some ability to
configure the client - for example, to accept 200 responses rather
than always assuming they might be erroneous and refusing to play
further. (Of course I can change the client source, but it doesn't
help that I'm a newbie at Java!)

What difference does it make when I change the server option in the
client? I've tried two different versions of Collect - the Market
version (1.1.7) has two "Server protocol" options, Aggregate and
OpenRosa, while v1.2 (1010) has three "Server Platform" options, for
Aggregate, Google Forms, and Other.

Is there a detailed explanation anywhere of how these different server
settings actually affect client/server interaction?

Thanks
Nik

--
Mitch Sundt
Software Engineer
University of Washington
mitchellsundt@gmail.com

Unfortunately, there is not a detailed description. They all execute
the exact same protocol except Google Forms which I don't remember off
the top of my head the differences but the Google Forms server is
unavailable to many users currently.

I encourage you to think carefully about your 200 response code
carefully as if you are using wifi in a variety of places you need
something to confirm receipt or you might lose data. Therefore to
ensure you get all data you need some sort of confirmation which would
require java skills to replace the response code with another useful
confirmation. ODk is an open source project so customizations are
encouraged. However, if you are trying to get rid of safeguards that
prevent problems make sure you have a plan in place to make sure the
problem it's solving is not going to be a problem in your particular
deployment. I am only saying this because we get emails from people
who make customizations that cause problems and then they panic in a
month when bad stuff happens and send frantic emails that ODK is
broken and when we try to help them and it turns out their
customizations caused them problems.

Cheers,
Waylon

··· On Thu, Jul 12, 2012 at 8:32 AM, blitheringeejit wrote: > Mitch: thanks for your clear and concise explanation. > > It's unfortunate that those working in my situation (PHP on a hosted > server where we have little control over the httpd config) might > struggle to make the server play nicely with your client response > status code strategy. I realise you're concentrating on providing an > end-to-end solution, but it would be nice to have some ability to > configure the client - for example, to accept 200 responses rather > than always assuming they might be erroneous and refusing to play > further. (Of course I can change the client source, but it doesn't > help that I'm a newbie at Java!) > > What difference does it make when I change the server option in the > client? I've tried two different versions of Collect - the Market > version (1.1.7) has two "Server protocol" options, Aggregate and > OpenRosa, while v1.2 (1010) has three "Server Platform" options, for > Aggregate, Google Forms, and Other. > > Is there a detailed explanation anywhere of how these different server > settings actually affect client/server interaction? > > Thanks > Nik

What you say makes perfect sense, of course. I understand that most
properly-educated programmers flee from PHP, for very good reasons - better
reasons, probably, than those which make me flee from Java. :slight_smile:

But I suspect there are potential users who don't have a simple or cheap
way of using Tomcat, and prefer the type of quick and dirty solution that
PHP is so good at (or at least so widely used for). In this particular
instance, I want to add Collect data capture to a web service which is
already running on a non-Tomcat server, and which it would be impossibly
disruptive to move.

So... I have Collect downloading forms from my server, and submitting form
data and media files to a PHP backend. I'm happy to share the workarounds
if you think it would be useful to the community, but if you'd rather keep
the community space free of PHP and its associated evils, I quite
understand.

And thanks again for your input, and to the whole team for producing ODK.
My project is a commercial one, albeit in a small way, so I'll make sure
there's a donation coming your way if the client bites.

Best,
Nik

Yaw's link is great, as long as you're happy using usernames and passwords
entered on the Android device. My customised version uses the device ID
(IMEI or MAC) to identify the device instead. If that approach would work
better for you, and you need any pointers, post back here and I'll help if
I can.

Nik

··· On Wednesday, 9 March 2016 18:36:20 UTC, mutu...@gmail.com wrote: > > > Hi Guys, > > I know this could feel abit insane especially commenting on a issue 2 > years old. > > My boss insists of having ODK on a php server. I have tried googling > following the threads here, but i still havent found a way out in getting a > PHP ODK server, does anyone have a working solution or can point me into > some directions on creating one. > > Thanks. > > > > On Thursday, March 13, 2014 at 3:39:00 PM UTC+3, John Cass wrote: > > Hope this might help someone, a totally minimal PHP server to catch > files from ODK collect, no error checking but it works... > > > > > > > > <?php > > > > > > $resp=201; > > > > > > if( $_SERVER['REQUEST_METHOD']==="HEAD") $resp=204; > > elseif( $_SERVER['REQUEST_METHOD']==="POST") > > { > > foreach( $_FILES as $file) > > { > > move_uploaded_file( $file['tmp_name'], > '/tmp/uploaded_files/'.$file['name']); > > } > > } > > > > > > header( "X-OpenRosa-Version: 1.0"); > > header( "X-OpenRosa-Accept-Content-Length: 2000000"); > > header( "Date: ".date('r'), false, $resp); > > > > > > ?> > > > > Thanks > > > > >

Try http://guillaume.larocque.space/2016/Intercept-odk-collect-submissions/

Yaw

··· -- Need ODK consultants? Nafundi provides form design, server setup, in-field training, and software development for ODK. Go to https://nafundi.com to get started.

On Wed, Mar 9, 2016 at 12:53 PM, muturiken@gmail.com wrote:

Hi Guys,

I know this could feel abit insane especially commenting on a issue 2 years old.

My boss insists of having ODK on a php server. I have tried googling following the threads here, but i still havent found a way out in getting a PHP ODK server, does anyone have a working solution or can point me into some directions on creating one.

Thanks.

On Thursday, March 13, 2014 at 3:39:00 PM UTC+3, John Cass wrote:

Hope this might help someone, a totally minimal PHP server to catch files from ODK collect, no error checking but it works...

<?php $resp=201; if( $_SERVER['REQUEST_METHOD']==="HEAD") $resp=204; elseif( $_SERVER['REQUEST_METHOD']==="POST") { foreach( $_FILES as $file) { move_uploaded_file( $file['tmp_name'], '/tmp/uploaded_files/'.$file['name']); } } header( "X-OpenRosa-Version: 1.0"); header( "X-OpenRosa-Accept-Content-Length: 2000000"); header( "Date: ".date('r'), false, $resp); ?> Thanks

--
You received this message because you are subscribed to the Google Groups "ODK Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to opendatakit-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

If the difference is just the option to change the paths and urls, then the
best bet is presumably to try to make my server comply with OpenRosa, and
choose the client option for Other or OpenRosa (depending on the version).

Is there any particular reason why you chose to drop the OpenRosa
nomenclature for the user-configurable server in Collect v1.2? Does it
depend less on receiving correct OpenRosa headers and the OpenRosaResponse
server response than v1.1 did?

Thanks
Nik

Dear All,

Yeah i know, it sound insane but my client wants a PHP ODK Aggregate. Tried to follow a few tutorials (http://guillaume.larocque.space/2016/Intercept-odk-collect-submissions/) invain.
Read through the OpenRosaAPI (https://bitbucket.org/javarosa/javarosa/wiki/OpenRosaAPI).

I was able to set it up and my small server can actually serve the forms and fill in data. But now i cant seem to get it working on submission. It throws me the Error. Invalid status code on HEad request. If you have a web proxy, you may need to,login to your network. I have no proxies set up on my server.

anyone who has done it or who can solve this for me?

http://178.62.32.219/odk/formList/
http://178.62.32.219/odk/submission/

My credentials are guest - guest or admin - mypass

Code to the files is here

Yes.

The 1.1.7 wording was incorrect. Aggregate is OpenRosa compliant if the
client supplies the OpenRosa version header on the request (per OpenRosa
standards). If that header is missing, it falls back to
pre-standardization response (Aggregate 0.9.x) when talking to ODK Collect
versions prior to 1.1.7.

So having "Aggregate" and "OpenRosa" wasn't right. Since ODK Collect 1.1.7
and 1.2 both issue OpenRosa requests (only), the change to "Aggregate" and
"Other" was appropriate.

Mitch

··· On Thu, Jul 12, 2012 at 9:41 AM, blitheringeejit wrote:

If the difference is just the option to change the paths and urls, then
the best bet is presumably to try to make my server comply with OpenRosa,
and choose the client option for Other or OpenRosa (depending on the
version).

Is there any particular reason why you chose to drop the OpenRosa
nomenclature for the user-configurable server in Collect v1.2? Does it
depend less on receiving correct OpenRosa headers and the OpenRosaResponse
server response than v1.1 did?

Thanks
Nik

--
Mitch Sundt
Software Engineer
University of Washington
mitchellsundt@gmail.com

On submission, the HEAD request is expected to get a 201 response. You are
likely sending a 200 response.

··· On Mon, Aug 8, 2016 at 3:33 AM, wrote:

Dear All,

Yeah i know, it sound insane but my client wants a PHP ODK Aggregate.
Tried to follow a few tutorials (http://guillaume.larocque.
space/2016/Intercept-odk-collect-submissions/) invain.
Read through the OpenRosaAPI (https://bitbucket.org/
javarosa/javarosa/wiki/OpenRosaAPI).

I was able to set it up and my small server can actually serve the forms
and fill in data. But now i cant seem to get it working on submission. It
throws me the Error. Invalid status code on HEad request. If you have a web
proxy, you may need to,login to your network. I have no proxies set up on
my server.

anyone who has done it or who can solve this for me?

http://178.62.32.219/odk/formList/
http://178.62.32.219/odk/submission/

My credentials are guest - guest or admin - mypass

Code to the files is here
https://gist.github.com/ken-muturi/063860f7912e3c5c4c0c8dea0e04e2a3
https://gist.github.com/ken-muturi/0f880e2cb1d19558e94ab05fc08797a6
https://gist.github.com/ken-muturi/568caa0f4198d7479f4d7ada89b5e20d
https://gist.github.com/ken-muturi/0fb7283282f4f29157ee05f4c6f9e4b2

--
You received this message because you are subscribed to the Google Groups
"ODK Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an
email to opendatakit-developers+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

--
Mitch Sundt
Software Engineer
University of Washington
mitchellsundt@gmail.com

Hi,
in my case, I am sending 204 for HEAD and 201 for POST but it replays with 301

(formname - Error: Moved Permanently (301) at serverpath.

Hi there,

If you'd like help, you're going to have to provide a lot more context
about what your high-level goals are, what your implementation does,
what you've tried, etc.

Yaw

··· On Sat, Apr 15, 2017 at 4:17 AM, wrote: > Hi, > in my case, I am sending 204 for HEAD and 201 for POST but it replays with 301 > > (formname - Error: Moved Permanently (301) at serverpath. > > -- > You received this message because you are subscribed to the Google Groups "ODK Developers" group. > To unsubscribe from this group and stop receiving emails from it, send an email to opendatakit-developers+unsubscribe@googlegroups.com. > For more options, visit https://groups.google.com/d/optout.