-
Improvement
-
Resolution: Unresolved
-
Minor
According to the documentation of the plugin, you can define custom headers for requests with a syntax like this one:
def response = httpRequest customHeaders: [[name: 'foo', value: 'bar']]
The problem arises when you try to use custom headers that use names with non-standard characters. I can't see the way to do something like this:
def response = httpRequest customHeaders: [["my-custom-header-with-hyphen-separator": "${varName}"]]
I know I can do it the hard way:
def headers = new ArrayList<jenkins.plugins.http_request.util.HttpRequestNameValuePair>() def headerName1 = 'my-custom-header-with-hyphen-separator' def varName1 = 'abc' headers.add(new jenkins.plugins.http_request.util.HttpRequestNameValuePair("${headerName1}","${varName1}"))
However I don't think that's the preferred method as it involves granting certain permissions to scripts.
Under normal circumstances, I would've expected here to use this kind of syntax:
def headers = [ "${headerName1}":"${varName1}","${headerName2}": "${varName2}" ]
Pretty much a json object with one or more key/value pairs.
So, is this possible? is there any alternative syntax that can be used right now to avoid working directly with Java classes?
[JENKINS-68154] Custom headers with special characters in their names
Assignee | Original: Janario Oliveira [ janario ] | New: Pratik [ pratik_0112 ] |
Comment |
[ [~markewaite] Sir,
I'm encountering an issue with the round-trip tests in the HTTP Request plugin. When I run the tests, they fail with a 500 server error during the configSubmit phase (for example, for URLs like {{{}http://localhost:36357/jenkins/job/test2/configSubmit{}}}). However, when I tried it on my local Jenkins instance, the pipeline runs successfully without any errors. Pipeline 1 : pipeline { agent any stages { stage('Test HTTP Request with Custom Headers and Variables') { steps { script { echo "Starting HTTP Request with custom headers using non-standard header names" // Define a variable to use in the custom header value def varName = "test-value" // Make an HTTP GET request with custom headers def response = httpRequest( url: 'https://httpbin.org/headers', // Echoes back the headers received customHeaders: [["my-custom-header-with-hyphen-separator": "${varName}"]] ) // Log the response content echo "HTTP Response Content: ${response.content}" } } } } } ] |
Comment |
[ Hi [~markewaite], [~aquesada] & [~chr1st0s] Sir,
I created a simple pipeline to test the issue - {quote}pipeline { agent any stages { stage('Test HTTP Request with Custom Headers') { steps { script { echo "Starting HTTP Request with custom headers" def response = httpRequest( url: 'https://httpbin.org/headers', customHeaders: [[name: 'foo', value: 'bar']] ) echo "HTTP Response Content: ${response.content}" } } } } } {quote} * {{I build it through mvn hpi:run but it gives console log for each build as :}} {quote}{{Started by user unknown or anonymous}} {{[Pipeline] Start of Pipeline}} {{[Pipeline] End of Pipeline}} {{Finished: SUCCESS}} {quote} * {{When I tried with my local jenkins controller with sudo systemctl start jenkins it works as expected and print the Response for all builds :}} * {{[Pipeline] echo}} {{HTTP Response Content: {}} {{ "headers": {}} {{ "Accept-Encoding": "gzip,deflate", }} {{ "Foo": "bar", }} {{ "Host": "httpbin.org", }} {{ "User-Agent": "Apache-HttpClient/4.5.14 (Java/17.0.13)", }} {{ "X-Amzn-Trace-Id": "Root=1-6780ee9b-3fbacca92b24045340f07192"}} \{\{ } }} {{}}} * {{My doubt is, what is issue with my "mvn hpi:run" jenkins controller, Am I doing in wrong way?}} * A glance of my terminal output, after running mvn hpi:run : {quote}[INFO] Configuring Jetty for project: HTTP Request Plugin [INFO] Try setting -DwildcardDNS=nip.io in a profile [INFO] ===========> Browse to: [http://localhost:8080/jenkins/] [INFO] /home/pratik@0112/GSoC/http-request-plugin/target/jetty/webapp does not yet exist, will receive /home/pratik@0112/.m2/repository/org/jenkins-ci/main/jenkins-war/2.479.1/jenkins-war-2.479.1.war [INFO] Context path = /jenkins [INFO] Tmp directory = /home/pratik@0112/GSoC/http-request-plugin/target/jetty [INFO] War = /home/pratik@0112/.m2/repository/org/jenkins-ci/main/jenkins-war/2.479.1/jenkins-war-2.479.1.war [INFO] jetty-12.0.16; built: 2024-12-09T21:02:54.535Z; git: c3f88bafb4e393f23204dc14dc57b042e84debc7; jvm 17.0.13+11-Ubuntu-2ubuntu124.04 [INFO] NO JSP Support for /jenkins, did not find org.eclipse.jetty.ee9.jsp.JettyJspServlet [INFO] Session workerName=node0 2025-01-10 09:51:20.782+0000 [id=1] INFO hudson.WebAppMain#contextInitialized: Jenkins home directory: /home/pratik@0112/GSoC/http-request-plugin/work found at: SystemProperties.getProperty("JENKINS_HOME") [INFO] Started oeje9n.ContextHandler$CoreContextHandler@239fd1ad{Jenkins v2.479.1,/jenkins,b=[file:///home/pratik@0112/GSoC/http-request-plugin/target/jetty/webapp/,a=AVAILABLE,h=oeje9n.ContextHandler$CoreContextHandler$CoreToNestedHandler@51e42a85]{STARTED}} [INFO] Started ServerConnector@3bc67aee\{HTTP/1.1, (http/1.1)} Unknown macro: \{localhost} [INFO] Started oejs.Server@68a4179f\{STARTING}[12.0.16,sto=0] @16552ms Hit <enter> to redeploy: 2025-01-10 09:51:21.591+0000 [id=36] INFO jenkins.InitReactorRunner$1#onAttained: Started initialization 2025-01-10 09:51:21.687+0000 [id=44] INFO hudson.ClassicPluginStrategy#createPluginWrapper: Plugin http_request.hpl is disabled 2025-01-10 09:51:21.786+0000 [id=47] INFO jenkins.InitReactorRunner$1#onAttained: Listed all plugins 2025-01-10 09:51:24.095+0000 [id=47] INFO jenkins.InitReactorRunner$1#onAttained: Prepared all plugins 2025-01-10 09:51:24.122+0000 [id=35] INFO jenkins.InitReactorRunner$1#onAttained: Started all plugins 2025-01-10 09:51:24.126+0000 [id=46] INFO jenkins.InitReactorRunner$1#onAttained: Augmented all extensions 2025-01-10 09:51:24.896+0000 [id=48] INFO jenkins.InitReactorRunner$1#onAttained: System config loaded 2025-01-10 09:51:24.897+0000 [id=37] INFO jenkins.InitReactorRunner$1#onAttained: System config adapted 2025-01-10 09:51:24.964+0000 [id=39] INFO jenkins.InitReactorRunner$1#onAttained: Loaded all jobs 2025-01-10 09:51:24.999+0000 [id=39] INFO jenkins.InitReactorRunner$1#onAttained: Configuration for all jobs updated 2025-01-10 09:51:25.031+0000 [id=39] INFO jenkins.model.Jenkins#setInstallState: Install state transitioning from: null to: DEVELOPMENT 2025-01-10 09:51:25.350+0000 [id=38] INFO jenkins.InitReactorRunner$1#onAttained: Completed initialization 2025-01-10 09:51:25.484+0000 [id=31] INFO hudson.lifecycle.Lifecycle#onReady: Jenkins is fully up and running {quote} ] |
Comment |
[ [~markewaite] Sir,
I'm encountering an issue with the round-trip tests in the HTTP Request plugin. When I run the tests, they fail with a 500 server error during the configSubmit phase (for example, for URLs like {{{}[http://localhost:36357/jenkins/job/test2/configSubmit]{}}}). However, when I tried it on my local Jenkins instance, the pipeline runs successfully without any errors. Additionally, I wanted to ask about adding the following pipelines and updating the code: - Pipelines : {{ }} {{ def response = httpRequest(}} {{ url: 'https://httpbin.org/headers',}} {{ customHeaders: [[name: 'foo', value: 'bar']]}} {{ )}} {{ def headerName1 = 'header'}} {{ def varName1 = 'abc'}} {{ def headerName2 = 'another-header'}} {{ def varName2 = 'xyz'}} {{ def headers = [}} {{ "${headerName1}": "${varName1}",}} {{ "${headerName2}": "${varName2}"}} {{ ]}} {{ def response = httpRequest(url:'https://httpbin.org/headers',  customHeaders: headers)}} - Updated Code for {{HttpRequestStep.java}} and {{HttpRequest.java :}} import java.util.Map; import java.util.stream.Collectors; @DataBoundSetter public void setCustomHeaders(Object customHeaders) { if (customHeaders instanceof List) { // Check if the list contains Map entries List<?> list = (List<?>) customHeaders; if (!list.isEmpty() && list.get(0) instanceof Map) { this.customHeaders = list.stream() .map(entry -> { Map<String, String> map = (Map<String, String>) entry; return new HttpRequestNameValuePair(map.get("name"), map.get("value")); } ) .collect(Collectors.toList()); } else { this.customHeaders = (List<HttpRequestNameValuePair>) customHeaders; } } else if (customHeaders instanceof Map) { this.customHeaders = ((Map<String, String>) customHeaders) .entrySet() .stream() .map(entry -> new HttpRequestNameValuePair(entry.getKey(), entry.getValue())) .collect(Collectors.toList()); } else { throw new IllegalArgumentException("Unsupported type for customHeaders: " + customHeaders.getClass()); } } - Test for customHeaders in HttpRequestRoundTripTest.java & HttpRequestStepRoundTripTest.java @Test public void configRoundtripGroup3() throws Exception { configRoundTrip(before); List<HttpRequestNameValuePair> params = new ArrayList<>(); params.add(new HttpRequestNameValuePair("param1","value1")); params.add(new HttpRequestNameValuePair("param2","value2")); RequestAction action = new RequestAction(new URL("http://www.domain.com/"),HttpMode.GET,null,params); List<RequestAction> actions = new ArrayList<>(); actions.add(action); FormAuthentication formAuth = new FormAuthentication("keyname",actions); List<FormAuthentication> formAuthList = new ArrayList<>(); formAuthList.add(formAuth); HttpRequestGlobalConfig.get().setFormAuthentications(formAuthList); configRoundTrip(before); List<HttpRequestNameValuePair> customHeaders = new ArrayList<>(); customHeaders.add(new HttpRequestNameValuePair("param1","value1")); before.setCustomHeaders(customHeaders); configRoundTrip(before); } private void configRoundTrip(HttpRequest before) throws Exception { HttpRequest after = j.configRoundtrip(before); j.assertEqualBeans(before, after, "httpMode,passBuildParameters"); j.assertEqualBeans(before, after, "url"); j.assertEqualBeans(before, after, "validResponseCodes,validResponseContent"); j.assertEqualBeans(before, after, "acceptType,contentType"); j.assertEqualBeans(before, after, "uploadFile,multipartName"); j.assertEqualBeans(before, after, "outputFile,timeout"); j.assertEqualBeans(before, after, "consoleLogResponseBody"); j.assertEqualBeans(before, after, "authentication"); // Custom header check assertEquals(before.getCustomHeaders().size(),after.getCustomHeaders().size()); for (int idx = 0; idx < before.getCustomHeaders().size(); idx++) { HttpRequestNameValuePair bnvp = before.getCustomHeaders().get(idx); HttpRequestNameValuePair anvp = after.getCustomHeaders().get(idx); assertEquals(bnvp.getName(),anvp.getName()); assertEquals(bnvp.getValue(),anvp.getValue()); } // Form authentication check List<FormAuthentication> beforeFas = HttpRequestGlobalConfig.get().getFormAuthentications(); List<FormAuthentication> afterFas = HttpRequestGlobalConfig.get().getFormAuthentications(); assertEquals(beforeFas.size(), afterFas.size()); for (int idx = 0; idx < beforeFas.size(); idx++) { FormAuthentication beforeFa = beforeFas.get(idx); FormAuthentication afterFa = afterFas.get(idx); assertEquals(beforeFa.getKeyName(), afterFa.getKeyName()); List<RequestAction> beforeActions = beforeFa.getActions(); List<RequestAction> afterActions = afterFa.getActions(); assertEquals(beforeActions.size(), afterActions.size()); for (int jdx = 0; jdx < beforeActions.size(); jdx ++) { RequestAction beforeAction = beforeActions.get(jdx); RequestAction afterAction = afterActions.get(jdx); assertEquals(beforeAction.getUrl(), afterAction.getUrl()); assertEquals(beforeAction.getMode(), afterAction.getMode()); List<HttpRequestNameValuePair> beforeParams = beforeAction.getParams(); List<HttpRequestNameValuePair> afterParams = afterAction.getParams(); assertEquals(beforeParams.size(), afterParams.size()); for (int kdx = 0; kdx < beforeParams.size(); kdx++) { HttpRequestNameValuePair beforeNvp = beforeParams.get(kdx); HttpRequestNameValuePair afterNvp = afterParams.get(kdx); assertEquals(beforeNvp.getName(), afterNvp.getName()); assertEquals(beforeNvp.getValue(), afterNvp.getValue()); } } } } } {quote}{{I wanted to know how I can integrate these updates properly. Do you think the issue could be related to the testing environment, or is there something else I should investigate further?"}} {quote} ] |
Comment |
[ [~markewaite]
Actually my one PR got merged in this plugin of "updating parent pom" but that time I was new, don't know about dependabot (he does it). But now, i am more familiar with jenkins platform. I will start on this right now, if I have come across any error further while solving, I will let you know. Please guide me that time !!! ] |
Comment |
[ [~markewaite], [~aquesada] [~chr1st0s]
After trying hard on this issue, I am able to execute pipeline with both customHeaders format mentioned in this issue on my local jenkins instance but getting below error while testing locally for 3 test cases - ``` [ERROR] Tests run: 5, Failures: 0, Errors: 3, Skipped: 0, Time elapsed: 276.0 s <<< FAILURE! -- in jenkins.plugins.http_request.HttpRequestRoundTripTest [ERROR] jenkins.plugins.http_request.HttpRequestRoundTripTest.configRoundtripGroup3 -- Time elapsed: 50.63 s <<< ERROR! org.htmlunit.FailingHttpStatusCodeException: 500 Server Error for http://localhost:45745/jenkins/job/test2/configSubmit at org.htmlunit.WebClient.throwFailingHttpStatusCodeExceptionIfNecessary(WebClient.java:749) at org.htmlunit.WebClient.loadDownloadedResponses(WebClient.java:2720) at org.htmlunit.html.HtmlFormUtil.submit(HtmlFormUtil.java:79) at org.htmlunit.html.HtmlFormUtil.submit(HtmlFormUtil.java:53) at org.jvnet.hudson.test.JenkinsRule.submit(JenkinsRule.java:1790) at org.jvnet.hudson.test.JenkinsRule.configRoundtrip(JenkinsRule.java:1447) at org.jvnet.hudson.test.JenkinsRule.configRoundtrip(JenkinsRule.java:1457) at jenkins.plugins.http_request.HttpRequestRoundTripTest.configRoundTrip(HttpRequestRoundTripTest.java:119) at jenkins.plugins.http_request.HttpRequestRoundTripTest.configRoundtripGroup3(HttpRequestRoundTripTest.java:87) at java.base/java.lang.reflect.Method.invoke(Method.java:569) at org.jvnet.hudson.test.JenkinsRule$1.evaluate(JenkinsRule.java:658) at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) at java.base/java.lang.Thread.run(Thread.java:840) ``` ] |