Skip to content

Commit

Permalink
Fix #5131: avoid 404 when loading draft
Browse files Browse the repository at this point in the history
When loading the form definition, to pass, in addition to the
`Orbeon-For-Document-Id` header, a `Orbeon-For-Document-IsDraft` header,
so when we do the `HEAD` to get the version of the form data, we know
whether to put `data` or `draft` in the path.
  • Loading branch information
avernet committed Dec 26, 2021
1 parent 8d2e165 commit 3847f0e
Show file tree
Hide file tree
Showing 6 changed files with 33 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,15 @@ private[persistence] object HttpCall {
import Version._

val timeoutHeader = timeout.map(t => Headers.Timeout -> List(Headers.TimeoutValuePrefix + t.toString))
val versionHeader = version match {
case Unspecified => None
case Next => Some(OrbeonFormDefinitionVersion -> List("next"))
case Specific(version) => Some(OrbeonFormDefinitionVersion -> List(version.toString))
case ForDocument(documentId) => Some(OrbeonForDocumentId -> List(documentId))
val versionHeaders = version match {
case Unspecified => Nil
case Next => List(OrbeonFormDefinitionVersion -> List("next"))
case Specific(version) => List(OrbeonFormDefinitionVersion -> List(version.toString))
case ForDocument(documentId, isDraft) => List(OrbeonForDocumentId -> List(documentId),
OrbeonForDocumentIsDraft -> List(isDraft.toString))
}
val stageHeader = stage.map(_.name).map(StageHeader.HeaderName -> List(_))
val headers = (timeoutHeader.toList ++ versionHeader.toList ++ stageHeader.toList).toMap
val headers = (timeoutHeader.toList ++ versionHeaders ++ stageHeader.toList).toMap

Connection.buildConnectionHeadersCapitalizedIfNeeded(
url = new URI(documentURL),
Expand Down
12 changes: 8 additions & 4 deletions form-runner/jvm/src/main/resources/apps/fr/detail/read-form.xpl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
<!-- NOTE: We used to use oxf:url-generator, then switched to oxf:xforms-submission for more header support. We use
oxf:url-generator again as it is much faster and is enough now that the persistence proxy is in place. -->
<p:processor name="oxf:url-generator">
<p:input name="config" href="#instance" transform="oxf:unsafe-xslt">
<p:input name="config" href="#instance" transform="oxf:unsafe-xslt" debug="XXX URL generator config">
<config xsl:version="2.0">

<xsl:variable name="params" select="/*"/>
Expand All @@ -52,6 +52,12 @@
<name>Orbeon-For-Document-Id</name>
<value><xsl:value-of select="$params/document"/></value>
</header>
<xsl:if test="p:non-blank($params/draft)">
<header>
<name>Orbeon-For-Document-IsDraft</name>
<value><xsl:value-of select="$params/draft"/></value>
</header>
</xsl:if>
</xsl:if>
<xsl:if test="not($use-document-id) and $specific-form-version-requested">
<header>
Expand All @@ -69,9 +75,7 @@
$params/app,
'/',
$params/form,
'/form/form.xhtml',
(: document is available e.g. when editing or viewing a document :)
if ($use-document-id) then concat('?document=', $params/document) else ''
'/form/form.xhtml'
)"/>
<url>
<xsl:value-of select="p:rewrite-service-uri($resource, true())"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ object RelationalCommon {
def requestedFormVersion(req: RequestCommon): Int =

req.version match {
case Unspecified => Private.latest(req.app, req.form).getOrElse(1)
case Next => Private.latest(req.app, req.form).map(_ + 1).getOrElse(1)
case Specific(v) => v
case ForDocument(docId) =>
FormRunner.readDocumentFormVersion(req.app, req.form, docId)
case Unspecified => Private.latest(req.app, req.form).getOrElse(1)
case Next => Private.latest(req.app, req.form).map(_ + 1).getOrElse(1)
case Specific(v) => v
case ForDocument(docId, isDraft) =>
FormRunner.readDocumentFormVersion(req.app, req.form, docId, isDraft)
.getOrElse(throw HttpStatusCodeException(StatusCode.NotFound))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ trait RequestResponse extends Common {
val version =
Version(
documentId = headerValue(OrbeonForDocumentIdLower),
version = headerValue(OrbeonFormDefinitionVersionLower)
isDraft = headerValue(OrbeonForDocumentIsDraftLower),
version = headerValue(OrbeonFormDefinitionVersionLower),
)

val requestPath = httpRequest.getRequestPath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -479,9 +479,10 @@ trait FormRunnerPersistence {
def readDocumentFormVersion(
appName : String,
formName : String,
documentId : String
documentId : String,
isDraft : Boolean
): Option[Int] = {
val path = createFormDataBasePath(appName, formName, isDraft = false, documentId) + "data.xml"
val path = createFormDataBasePath(appName, formName, isDraft, documentId) + "data.xml"
val headers = readHeaders(path, Map.empty)
headers.get(Version.OrbeonFormDefinitionVersion).map(_.head).map(_.toInt)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@ sealed trait Version

object Version {

case object Unspecified extends Version
case object Next extends Version
case class Specific (version: Int) extends Version
case class ForDocument(documentId: String) extends Version
case object Unspecified extends Version
case object Next extends Version
case class Specific (version: Int) extends Version
case class ForDocument(documentId: String, isDraft: Boolean) extends Version

val OrbeonForDocumentId : String = "Orbeon-For-Document-Id"
val OrbeonForDocumentIsDraft : String = "Orbeon-For-Document-IsDraft"
val OrbeonFormDefinitionVersion : String = "Orbeon-Form-Definition-Version"
val OrbeonForDocumentIdLower : String = OrbeonForDocumentId.toLowerCase
val OrbeonForDocumentIsDraftLower : String = OrbeonForDocumentIsDraft.toLowerCase
val OrbeonFormDefinitionVersionLower : String = OrbeonFormDefinitionVersion.toLowerCase

def apply(documentId: Option[String], version: Option[String]): Version =
def apply(documentId: Option[String], isDraft: Option[String], version: Option[String]): Version =
documentId match {
case Some(id) => ForDocument(id)
case Some(id) => ForDocument(id, isDraft.exists(_.toBoolean))
case None =>
version match {
case None => Unspecified
Expand Down

0 comments on commit 3847f0e

Please sign in to comment.