jenkinsci / java-client-api

A Jenkins API client for Java
MIT License
901 stars 469 forks source link

Job.build(Map<String, String> params) results in HTTP 414 (URI too long) #352

Open NicolasRouquette opened 6 years ago

NicolasRouquette commented 6 years ago

I've had problems with requests for a parameterized job build:

org.apache.http.client.HttpResponseException: Request-URI Too Long
 at com.offbytwo.jenkins.client.validator.HttpResponseValidator.validateResponse(HttpResponseValidator.java:11)
 at com.offbytwo.jenkins.client.JenkinsHttpClient.post(JenkinsHttpClient.java:232)
 at com.offbytwo.jenkins.model.Job.build(Job.java:125)
 at com.offbytwo.jenkins.model.Job.build(Job.java:112)

Looking at the code, I noticed that Job.build encodes the job parameter/values in the URL. This can result in a very long URL that exceeds the server's max URL size.

I worked around this problem outside of the library by submitting a POST request where the job parameter/values are passed as form data instead of encoded in the url.

jlwuleo commented 5 years ago

我也碰到这个问题,请问要怎么处理呢

jlwuleo commented 5 years ago

java private void buildJob(String jenkinsUrl, String jobUrl, String username, String password, Map<String, String> params) { try {

        HttpClientBuilder builder = HttpClientBuilder.create();

        URI jobBuildUri = new URI(jobUrl + "/buildWithParameters/api/json");

        CredentialsProvider provider = new BasicCredentialsProvider();
        AuthScope scope = new AuthScope(jobBuildUri.getHost(), jobBuildUri.getPort(), "realm");
        UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
        provider.setCredentials(scope, credentials);
        builder.setDefaultCredentialsProvider(provider);

        builder.addInterceptorFirst(new PreemptiveAuth());

        client = builder.build();

        HttpPost httpPost = new HttpPost(jobBuildUri);
        List<NameValuePair> pairs = new ArrayList<NameValuePair>();

        params.forEach((key, value) -> {
            pairs.add(new BasicNameValuePair(key, value));
        });

        httpPost.setEntity(new UrlEncodedFormEntity(pairs, "utf-8"));
        httpPost.addHeader(new BasicHeader("Jenkins-Crumb", getCrumb(jenkinsUrl)));
        httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");

        client.execute(httpPost);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private String getCrumb(String jenkinsUrl) throws ClientProtocolException, IOException {

    String result = "";
    HttpGet httpGet = new HttpGet(jenkinsUrl + "/crumbIssuer/api/json");

    HttpResponse response = client.execute(httpGet);
    String jsonStr = EntityUtils.toString(response.getEntity());

    JSONObject json = JSONObject.parseObject(jsonStr);

    result = json.getString("crumb");

    return result;
}

这种方式可行

Damon1988 commented 2 months ago

参考 jlwuleo的方法,我重写了Job类的build方法

public QueueReference build(Map<String, String> params, Map<String, File> fileParams, boolean crumbFlag) throws IOException {
        // 将URL传参修改为Form表单传参
       List<NameValuePair> pairs = new ArrayList<NameValuePair>();
        params.forEach((key, value) -> {
            pairs.add(new BasicNameValuePair(key, value));
        });
        HttpResponse response = client.post_form_with_result(getUrl() + "buildWithParameters/api/json", pairs, crumbFlag);
        String location = response.getFirstHeader("Location").getValue();
        return new QueueReference(location);
}

为了解决衍生出的得到Jenkins结果的中文乱码问题,我重写了JenkinsHttpClient的post_form_with_result方法

public HttpResponse post_form_with_result(String path, List<NameValuePair> data, boolean crumbFlag) throws IOException {
        HttpPost request;
        if (data != null) {
           // 入参设置 UTF-8字符集
            UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(data, "UTF-8");
            request = new HttpPost(UrlUtils.toNoApiUri(uri, context, path));
            request.setEntity(urlEncodedFormEntity);
        } else {
            request = new HttpPost(UrlUtils.toNoApiUri(uri, context, path));
        }
        // 出参设置 UTF-8字符集
        request.addHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"));
        if (crumbFlag == true) {
            Crumb crumb = get("/crumbIssuer", Crumb.class);
            if (crumb != null) {
                request.addHeader(new BasicHeader(crumb.getCrumbRequestField(), crumb.getCrumb()));
            }
        }
        HttpResponse response = client.execute(request, localContext);
        jenkinsVersion = ResponseUtils.getJenkinsVersion(response);
        return response;
}

问题得到了解决。

weeklynote commented 2 months ago

已收到,我会尽快回复你!                      ——刘劲字