Skip to content

Commit

Permalink
Merge branch 'konrad-krakowiak-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
janario committed Mar 31, 2015
2 parents e00b8b6 + 93c1eb2 commit 606128d
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 88 deletions.
181 changes: 124 additions & 57 deletions src/main/java/jenkins/plugins/http_request/HttpRequest.java
Original file line number Diff line number Diff line change
@@ -1,26 +1,12 @@
package jenkins.plugins.http_request;

import static com.google.common.base.Preconditions.checkArgument;

import javax.servlet.ServletException;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import com.google.common.base.Objects;
import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.collect.Range;
import com.google.common.collect.Ranges;
import com.google.common.primitives.Ints;
import hudson.EnvVars;
import hudson.Extension;
import hudson.FilePath;
import hudson.Launcher;
import hudson.Util;
import hudson.*;
import hudson.init.InitMilestone;
import hudson.init.Initializer;
import hudson.model.AbstractBuild;
Expand All @@ -45,10 +31,23 @@
import org.apache.http.impl.client.SystemDefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import org.kohsuke.stapler.StaplerRequest;

import javax.servlet.ServletException;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import static com.google.common.base.Preconditions.checkArgument;

/**
* @author Janario Oliveira
*/
Expand All @@ -65,6 +64,7 @@ public class HttpRequest extends Builder {
private List<NameValuePair> customHeaders = new ArrayList<NameValuePair>();
private final Integer timeout;
private String validResponseCodes;
private String validResponseContent;

/**
* @deprecated only to deserialize and serialize in a new form
Expand All @@ -77,15 +77,16 @@ public HttpRequest(String url, HttpMode httpMode, String authentication, MimeTyp
MimeType acceptType, String outputFile, Boolean returnCodeBuildRelevant,
Boolean consoleLogResponseBody, Boolean passBuildParameters,
List<NameValuePair> customHeaders, Integer timeout,
String validResponseCodes)
throws URISyntaxException {
String validResponseCodes, String validResponseContent)
throws URISyntaxException {
this.url = url;
this.contentType = contentType;
this.acceptType = acceptType;
this.outputFile = outputFile;
this.httpMode = httpMode;
this.customHeaders = customHeaders;
this.validResponseCodes = validResponseCodes;
this.validResponseContent = validResponseContent;
this.authentication = Util.fixEmpty(authentication);
this.consoleLogResponseBody = consoleLogResponseBody;
this.passBuildParameters = passBuildParameters;
Expand Down Expand Up @@ -165,42 +166,29 @@ public String getValidResponseCodes() {
return validResponseCodes;
}

public String getValidResponseContent() {
return validResponseContent;
}

@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException {
defineDefaultConfigurations();

final PrintStream logger = listener.getLogger();
logger.println("HttpMode: " + httpMode);

final DefaultHttpClient httpclient = new SystemDefaultHttpClient();
final HttpContext context = new BasicHttpContext();

final EnvVars envVars = build.getEnvironment(listener);
final List<NameValuePair> params = createParameters(build, logger, envVars);
String evaluatedUrl = evaluate(url, build.getBuildVariableResolver(), envVars);
logger.println(String.format("URL: %s", evaluatedUrl));

final RequestAction requestAction = new RequestAction(new URL(evaluatedUrl), httpMode, params);
final HttpClientUtil clientUtil = new HttpClientUtil();
if (outputFile != null && !outputFile.isEmpty()) {
FilePath outputFilePath = build.getWorkspace().child(outputFile);
clientUtil.setOutputFile(outputFilePath);
}
final HttpRequestBase httpRequestBase = clientUtil.createRequestBase(requestAction);

if (contentType != MimeType.NOT_SET) {
httpRequestBase.setHeader("Content-type", contentType.getValue());
logger.println("Content-type: " + contentType);
}

if (acceptType != MimeType.NOT_SET){
httpRequestBase.setHeader("Accept", acceptType.getValue());
logger.println("Accept: " + acceptType);
}

for (NameValuePair header : customHeaders) {
httpRequestBase.addHeader(header.getName(), header.getValue());
}
DefaultHttpClient httpclient = new SystemDefaultHttpClient();
RequestAction requestAction = new RequestAction(new URL(evaluatedUrl), httpMode, params);
HttpClientUtil clientUtil = new HttpClientUtil();
HttpRequestBase httpRequestBase = getHttpRequestBase(logger, requestAction, clientUtil);
HttpContext context = new BasicHttpContext();

if (authentication != null) {
final Authenticator auth = getDescriptor().getAuthentication(authentication);
Expand All @@ -211,22 +199,80 @@ public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListen
logger.println("Using authentication: " + auth.getKeyName());
auth.authenticate(httpclient, context, httpRequestBase, logger, timeout);
}
final HttpResponse response = clientUtil.execute(httpclient, context, httpRequestBase, logger, timeout);

try {
ResponseContentSupplier responseContentSupplier = new ResponseContentSupplier(response);
logResponse(build, logger, responseContentSupplier);

final HttpResponse execute = clientUtil.execute(httpclient, context, httpRequestBase, logger, consoleLogResponseBody, timeout);
return responseCodeIsValid(response, logger) && contentIsValid(responseContentSupplier, logger);
} finally {
EntityUtils.consume(response.getEntity());
}
}

boolean successCode = false;
private boolean contentIsValid(ResponseContentSupplier responseContentSupplier, PrintStream logger) {
if (Strings.isNullOrEmpty(validResponseContent)) {
return true;
}

String response = responseContentSupplier.get();
if (!response.contains(validResponseContent)) {
logger.println("Fail: Response with length " + response.length() + " doesn't contain '" + validResponseContent + "'");
return false;
}
return true;
}

private boolean responseCodeIsValid(HttpResponse response, PrintStream logger) {
List<Range<Integer>> ranges = getDescriptor().parseToRange(validResponseCodes);
for (Range<Integer> range : ranges) {
if (range.contains(execute.getStatusLine().getStatusCode())) {
if (range.contains(response.getStatusLine().getStatusCode())) {
logger.println("Success code from " + range);
successCode = true;
break;
return true;
}
}
logger.println("Fail: Any code list (" + ranges + ") match the returned code " + response.getStatusLine().getStatusCode());
return false;

}

private void logResponse(AbstractBuild<?, ?> build, PrintStream logger, ResponseContentSupplier responseContentSupplier) throws IOException, InterruptedException {
FilePath outputFilePath = getOutputFilePath(build);
if (consoleLogResponseBody || outputFilePath != null) {
if (consoleLogResponseBody) {
logger.println("Response: \n" + responseContentSupplier.get());
}
if (outputFilePath != null && responseContentSupplier.get() != null) {
outputFilePath.write().write(responseContentSupplier.get().getBytes());
}
}
}

private HttpRequestBase getHttpRequestBase(PrintStream logger, RequestAction requestAction, HttpClientUtil clientUtil) throws IOException {
HttpRequestBase httpRequestBase = clientUtil.createRequestBase(requestAction);

if (contentType != MimeType.NOT_SET) {
httpRequestBase.setHeader("Content-type", contentType.getValue());
logger.println("Content-type: " + contentType);
}

if (acceptType != MimeType.NOT_SET) {
httpRequestBase.setHeader("Accept", acceptType.getValue());
logger.println("Accept: " + acceptType);
}
if (!successCode) {
logger.println("Fail: Any code list (" + ranges + ") match the returned code " + execute.getStatusLine().getStatusCode());

for (NameValuePair header : customHeaders) {
httpRequestBase.addHeader(header.getName(), header.getValue());
}
return successCode;
return httpRequestBase;
}

private FilePath getOutputFilePath(AbstractBuild<?, ?> build) {
if (outputFile != null && !outputFile.isEmpty()) {
return build.getWorkspace().child(outputFile);
}
return null;
}

private List<NameValuePair> createParameters(
Expand Down Expand Up @@ -268,19 +314,19 @@ public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
private List<BasicDigestAuthentication> basicDigestAuthentications = new ArrayList<BasicDigestAuthentication>();
private List<FormAuthentication> formAuthentications = new ArrayList<FormAuthentication>();
private boolean defaultReturnCodeBuildRelevant = true;
private boolean defaultLogResponseBody = true;
private boolean defaultLogResponseBody = true;

public DescriptorImpl() {
load();
}

public boolean isDefaultLogResponseBody() {
return defaultLogResponseBody;
}
public boolean isDefaultLogResponseBody() {
return defaultLogResponseBody;
}

public void setDefaultLogResponseBody(boolean defaultLogResponseBody) {
this.defaultLogResponseBody = defaultLogResponseBody;
}
public void setDefaultLogResponseBody(boolean defaultLogResponseBody) {
this.defaultLogResponseBody = defaultLogResponseBody;
}

public HttpMode getDefaultHttpMode() {
return defaultHttpMode;
Expand Down Expand Up @@ -420,7 +466,7 @@ List<Range<Integer>> parseToRange(String value) {
String[] fromTo = code.trim().split(":");
checkArgument(fromTo.length <= 2, "Code %s should be an interval from:to or a single value", code);
Integer from = Ints.tryParse(fromTo[0]);
checkArgument(from !=null , "Invalid number %s", fromTo[0]);
checkArgument(from != null, "Invalid number %s", fromTo[0]);

Integer to = from;
if (fromTo.length != 1) {
Expand Down Expand Up @@ -448,4 +494,25 @@ public FormValidation doCheckValidResponseCodes(@QueryParameter String value) {
return FormValidation.ok();
}
}

private class ResponseContentSupplier implements Supplier<String> {

private String content;
private final HttpResponse response;

private ResponseContentSupplier(HttpResponse response) {
this.response = response;
}

public String get() {
try {
if (content == null) {
content = EntityUtils.toString(response.getEntity());
}
return content;
} catch (IOException e) {
return null;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public void authenticate(DefaultHttpClient client, HttpContext context,
for (RequestAction requestAction : actions) {
final HttpRequestBase method = clientUtil.createRequestBase(requestAction);

final HttpResponse execute = clientUtil.execute(client, context, method, logger, true, timeout);
final HttpResponse execute = clientUtil.execute(client, context, method, logger, timeout);
//from 400(client error) to 599(server error)
if ((execute.getStatusLine().getStatusCode() >= 400
&& execute.getStatusLine().getStatusCode() <= 599)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,23 @@
package jenkins.plugins.http_request.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;

import hudson.FilePath;
import jenkins.plugins.http_request.HttpMode;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.methods.*;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import java.io.*;
import java.net.URI;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;

/**
* @author Janario Oliveira
Expand Down Expand Up @@ -111,7 +101,7 @@ public HttpDelete makeDelete(RequestAction requestAction) throws UnsupportedEnco
}

public HttpResponse execute(DefaultHttpClient client, HttpContext context, HttpRequestBase method,
PrintStream logger, boolean consolLogResponseBody, Integer timeout) throws IOException, InterruptedException {
PrintStream logger, Integer timeout) throws IOException, InterruptedException {
doSecurity(client, method.getURI());

logger.println("Sending request to url: " + method.getURI());
Expand All @@ -126,17 +116,6 @@ public HttpResponse execute(DefaultHttpClient client, HttpContext context, HttpR
final HttpResponse httpResponse = client.execute(method, context);
logger.println("Response Code: " + httpResponse.getStatusLine());

if (consolLogResponseBody || outputFilePath != null) {
String httpData = EntityUtils.toString(httpResponse.getEntity());
if (consolLogResponseBody) {
logger.println("Response: \n" + httpData);
}
if (outputFilePath != null) {
outputFilePath.write().write(httpData.getBytes());
}
}
EntityUtils.consume(httpResponse.getEntity());

return httpResponse;
}

Expand All @@ -157,7 +136,7 @@ public boolean isTrusted(X509Certificate[] chain,
final int port = uri.getPort() < 0 ? 443 : uri.getPort();
schemeRegistry.register(new Scheme(uri.getScheme(), port, ssf));
} catch (Exception ex) {
throw new IOException("Error unknow", ex);
throw new IOException("Error unknown", ex);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
<f:entry field="validResponseCodes" title="Response codes expected">
<f:textbox />
</f:entry>
<f:entry field="validResponseContent" title="Response content expected">
<f:textbox />
</f:entry>
<f:entry field="acceptType" title="Accept">
<f:select />
</f:entry>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div>
If set response must contain this string to mark an execution as <b>success</b>.<br/>
</div>

0 comments on commit 606128d

Please sign in to comment.