Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ THE SOFTWARE.
<commons-fileupload2.version>2.0.0-M4</commons-fileupload2.version>
<groovy.version>2.4.21</groovy.version>
<jelly.version>1.1-jenkins-20250731</jelly.version>
<stapler.version>2036.v69a_e0454da_b_9</stapler.version>
<stapler.version>2044.vda_77a_f49cf7e</stapler.version>
</properties>

<dependencyManagement>
Expand Down
25 changes: 24 additions & 1 deletion core/src/main/java/hudson/Functions.java
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@
import jenkins.model.details.DetailFactory;
import jenkins.model.details.DetailGroup;
import jenkins.util.SystemProperties;
import net.sf.json.JSONArray;
import org.apache.commons.jelly.JellyContext;
import org.apache.commons.jelly.JellyTagException;
import org.apache.commons.jelly.Script;
Expand Down Expand Up @@ -2355,7 +2356,29 @@ public static String createRenderOnDemandProxy(JellyContext context, String attr
*/
@Restricted(NoExternalUse.class)
public static StaplerRequest2.RenderOnDemandParameters createRenderOnDemandProxyParameters(JellyContext context, String attributesToCapture) {
return Stapler.getCurrentRequest2().createJavaScriptProxyParameters(new RenderOnDemandClosure(context, attributesToCapture));

final StaplerRequest2 request = Stapler.getCurrentRequest2();
final StaplerRequest2.RenderOnDemandParameters parameters = request.createJavaScriptProxyParameters(new RenderOnDemandClosure(context, attributesToCapture));

Object attribute = request.getAttribute("renderOnDemandProxies");
if (attribute instanceof List list) {
list.add(parameters.releaseUrl);
} else {
attribute = new ArrayList<>(List.of(parameters.releaseUrl));
}
request.setAttribute("renderOnDemandProxies", attribute);
return parameters;
}

@Restricted(NoExternalUse.class)
public static JSONArray getRenderOnDemandProxyReleaseURLs() {
final StaplerRequest2 request = Stapler.getCurrentRequest2();
Object attribute = request.getAttribute("renderOnDemandProxies");
JSONArray urls = new JSONArray();
if (attribute instanceof List list) {
urls.addAll(list);
}
return urls;
}

public static String getCurrentDescriptorByNameUrl() {
Expand Down
22 changes: 22 additions & 0 deletions core/src/main/java/hudson/widgets/RenderOnDemandClosure.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,15 @@

package hudson.widgets;

import hudson.Extension;
import hudson.Util;
import hudson.model.Descriptor;
import hudson.security.csrf.CrumbExclusion;
import hudson.util.PackedMap;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -135,5 +140,22 @@
};
}

/**
* In JS, navigator.sendBeacon() is used to send the unload request, and always sends POST.
*
* @see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon">MDN: sendBeacon</a>
*/
@Extension
public static class ReleaseBoundObjectsCrumbExclusion extends CrumbExclusion {
@Override
public boolean process(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request.getPathInfo().startsWith("/$stapler/bound/release/")) {

Check warning on line 152 in core/src/main/java/hudson/widgets/RenderOnDemandClosure.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 152 is only partially covered, one branch is missing
chain.doFilter(request, response);
return true;

Check warning on line 154 in core/src/main/java/hudson/widgets/RenderOnDemandClosure.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 153-154 are not covered by tests
}
return false;
}
}

private static final Logger LOGGER = Logger.getLogger(RenderOnDemandClosure.class.getName());
}
1 change: 1 addition & 0 deletions core/src/main/resources/lib/layout/layout.jelly
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ THE SOFTWARE.
</div>
</footer>
</j:if>
<div id="render-on-demand-proxies-release" class="jenkins-!-display-contents" data-proxies="${h.getRenderOnDemandProxyReleaseURLs()}"/>
</body>
</html>
</l:view>
Expand Down
1 change: 1 addition & 0 deletions core/src/main/resources/lib/layout/renderOnDemand.jelly
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ THE SOFTWARE.
<x:attribute name="class">render-on-demand ${attrs.clazz}</x:attribute>
<x:attribute name="data-proxy-method">${parameters.proxyMethod}</x:attribute>
<x:attribute name="data-proxy-url">${parameters.url}</x:attribute>
<x:attribute name="data-release-url">${parameters.releaseUrl}</x:attribute>
<x:attribute name="data-proxy-crumb">${parameters.crumb}</x:attribute>
<x:attribute name="data-proxy-url-names">${parameters.urlNames}</x:attribute>
</x:element>
Expand Down
9 changes: 9 additions & 0 deletions war/src/main/webapp/scripts/hudson-behavior.js
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,15 @@ function renderOnDemand(e, callback, noBehaviour) {
});
}

window.addEventListener("pagehide", function () {
let element = document.querySelector("#render-on-demand-proxies-release");
let jsonString = element.dataset.proxies;
let json = JSON.parse(jsonString);
json.forEach(function (url) {
navigator.sendBeacon(url);
});
});

/**
* Finds all the script tags
*/
Expand Down
Loading