I've only been using ODK for 2 days now. I may be completely off my rocker. Just let me know. BTW, love the FP approach here in the backend.
1. What is the issue? Please be detailed.
A token key with a dollar sign in the middle was generated and Express route params is apparently chopping off the right side. This means it will not find the form correctly when calling GET /test/:key/projects/:projectId/forms/:id/draft/formList
2. What steps can we take to reproduce this issue?
Just installed ODK for the first time using odk-center docker-compose with an upstream nginx for SSL negotiation. Used odk-build to generate my first form and uploaded that. This created a draft testing QR code. Loaded this into ODK Collect and it fails to load the form. Server side logs show a hit to /v1/test/bOFFAKV3sJBmpvrqJS4oQIXgmIilrmIbSFj$mUwq7w5MnJereDHdbBQ6zCPaA3eF/projects/1/forms/apartments/draft/formList
3. What have you tried to fix the issue?
I used curl to reproduce the call and overcame an OpenRosa header issue by calling it like this.
curl -H "X-OpenRosa-Version: 1.0" https://my.host.name/odk/v1/test/bOFFAKV3sJBmpvrqJS4oQIXgmIilrmIbSFj$mUwq7w5MnJereDHdbBQ6zCPaA3eF/projects/1/forms/apartments/draft/formList
You will see an extra odk/ in the path because ODK is not the only service on this server. There's another nginx instance and it will strip the "odk/" from the path. I'm pretty sure this is not interfering.
I create a function called log that will print my message and print the object being passed along this pipeline.
Forms.getByProjectAndXmlFormId(params.projectId, params.id, false, Form.DraftVersion)
.then(log("brian 1"))
.then(getOrNotFound)
.then(log("brian 2"))
.then(ensureDef)
.then(log("brian 3"))
.then(checkFormToken(params.key))
.then(log("brian 4"))
.catch(Problem.translate(Problem.user.notFound, noargs(Problem.user.failedDraftAccess)))
I get a 3 but not a 4.
And I added logging here.
const checkFormToken = (token) => {
console.log(`checkFormToken(${token})`);
return rejectIf(
((form) => {
console.log(`form.def.draftToken is ${form.def.draftToken}`);
return (form.def.draftToken !== token) || isBlank(form.def.draftToken)
}),
noargs(Problem.user.notFound)
);
};
The token from the URL does not match the draft token in the form definition.
draftToken: bOFFAKV3sJBmpvrqJS4oQIXgmIilrmIbSFj$mUwq7w5MnJereDHdbBQ6zCPaA3eF
param.key: bOFFAKV3sJBmpvrqJS4oQIXgmIilrmIbSFj
Express documentation says it uses regexes to pluck out parameter values. Dollar sign has special meaning. Escaping the dollar sign works.
curl -H "X-OpenRosa-Version: 1.0" https://my.host.name/odk/v1/test/bOFFAKV3sJBmpvrqJS4oQIXgmIilrmIbSFj\$mUwq7w5MnJereDHdbBQ6zCPaA3eF/projects/1/forms/apartments/draft/formList
Not sure what you want to do here. Looks like you have 2 options:
- prevent the creation of tokens with dollar signs
- escape the dollar sign in URL.
Personally, I feel #1 is better because it should not be the job of Collect (and other apps) to deal with the limitation of Express in Central backend.
If you create a ticket and point me in the right direction, I may be able to resolve this issue.
BTW is there any logging mechanism besides morgan?