There is 1 comment.
 
 
XWiki Platform / cid:jira-generated-image-avatar-7145a405-0ff1-4693-871e-0dc67d98d2c7 XWIKI-24871 In Progress

A scheduler job can generate URLs based on a previously captured HTTP request instead of the wiki descriptor

 
View issue   ยท   Add comment
 

1 comment

 
cid:jira-generated-image-avatar-d8b6e331-e53e-4e02-8766-b7980d37a8d4 Thomas Mortagne on 18/Sep/26 11:32
 

Follow-up, since the problem was reported on 17.10.13 with the job created and registered from the UI.

17.10.13 behaves like master here

The whole chain is functionally identical between the xwiki-platform-17.10.13 tag and master, only log messages and code style differ:

  • HttpServletRequestStub#daemon is initialized to true in both
  • XWikiServletRequestStub(XWikiRequest) copies the flag only when the source request is itself a stub, in both
  • XWikiServletURLFactory#init and #getOriginalURL are unchanged (pattern matching rewrite and log messages only)
  • XWiki#getServerURL(String, XWikiContext) and XWiki#isDaemon(XWikiRequest) are unchanged (getWikiPort signature and the protocol branch rewrite only)
  • SchedulerPlugin#prepareJobStubContext is unchanged

So the result of the test above also applies to 17.10.13: scheduling a job through the Scheduler UI gives the job a daemon request stub, and the job generates its URLs from the wiki descriptor.

Two candidates for what was observed

  1. The scheduling which ended up in the Quartz scheduler was not the one done from the UI. The JobDetail holds the context built the last time the job was scheduled, and it is rebuilt by any restart (SchedulerPlugin#restoreExistingJobs), by the creation of the job document from an import or an extension installation (SchedulerPlugin#onDocumentEvent then register), or by a script calling the scheduler API.
  2. The daemon flag is not involved at all, and the fallback of the URL factory is what produces the bad URL: when XWiki#getServerURL(wikiId, xcontext) returns null (no descriptor found for the wiki id of the job context), XWikiServletURLFactory#getServerURL falls back to getOriginalURL, which returns this.originalURL, i.e. HttpServletUtils.getSourceBaseURL(capturedRequest). That produces exactly http://xwiki/xwiki/bin/view/... (plain HTTP, internal host of the reverse proxy) while the descriptor declares xwiki.atelier-medias.org with SSL. In that case setDaemon(true) in prepareJobStubContext would change nothing.

Telling them apart on the affected instance

Scheduling and triggering the following job the same way the failing job was scheduled writes the answer in Sandbox.SchedulerURLDiagnostic: it dumps the request the job context holds, its daemon flag, the captured base URL, the wiki ids of the job context, what the descriptor and the URL factory each return, and the resulting external URL.

// XWIKI-24871 diagnostic: what does a scheduled job actually use to generate its URLs?
// Paste this in the "Job Script" field of a scheduler job, schedule and trigger it exactly the way
// the failing job was, then read the page named below.
def OUTPUT_PAGE = 'Sandbox.SchedulerURLDiagnostic'

def report = new StringBuilder()
def safe = { String label, Closure value ->
    try {
        report << label << ': ' << String.valueOf(value()) << '\n'
    } catch (Throwable t) {
        report << label << ': FAILED (' << t << ')\n'
    }
}

def request = xcontext.getRequest()
def inner = request?.getHttpServletRequest()
def stubClass = com.xpn.xwiki.web.XWikiServletRequestStub

safe('context request class') { request?.getClass()?.getName() }
safe('inner request class') { inner?.getClass()?.getName() }
safe('inner request is a stub') { stubClass.isInstance(inner) }
safe('daemon flag') { stubClass.isInstance(inner) ? inner.isDaemon() : 'n/a (not a stub, so treated as NOT daemon)' }
safe('captured request base URL') { org.xwiki.container.servlet.HttpServletUtils.getSourceBaseURL(request) }
safe('context wiki id') { xcontext.getWikiId() }
safe('context original wiki id') { xcontext.getOriginalWikiId() }
safe('main wiki id') { xcontext.getMainXWiki() }
safe('descriptor URL (XWiki#getServerURL)') { xcontext.getWiki().getServerURL(xcontext.getWikiId(), xcontext) }
safe('URL factory class') { xcontext.getURLFactory()?.getClass()?.getName() }
safe('URL factory server URL') { xcontext.getURLFactory().getServerURL(xcontext) }
safe('generated external URL') { xwiki.getDocument('Main.WebHome').getExternalURL() }

def out = xwiki.getDocument(OUTPUT_PAGE)
out.setContent('{{{' + report.toString() + '}}}')
out.save('XWIKI-24871 diagnostic')