Connection timeout with HttpURLConnection in Groovy - url

I am always getting the "Error Connecting to ${url}" message?
Can anyone please show me my mistake?
def url = new URL("https://www.google.com")
HttpURLConnection connection = (HttpURLConnection) url.openConnection()
connection.setRequestMethod("GET")
// connection.setConnectTimeout(10000)
connection.connect()
if (connection.responseCode == 200 || connection.responseCode == 201) {
def returnMessage = connection.content
//print out the full response
println returnMessage
} else {
println "Error Connecting to " + url
}
| Error 2012-07-05 00:04:05,950 [http-bio-8080-exec-6] ERROR errors.GrailsExceptionResolver - ConnectException occurred when processing request: [GET] /CopperApplications/urlTracker Connection timed out: connect. Stacktrace follows: Message: Connection timed out: connec

Your code seems correct, and produces the expected(?) results on Groovy 1.7.9 with 1.6.0_33 JVM. There is likely something amiss with your network (as indicated by the connection timeout error).

Related

Jenkins unexpected exception java.nio.channels.ClosedByInterruptException when deleting a big folder from Artifactory

In my Jenkins shared lib, I’ve created a class called ArtifactManager which performs docker cleanup from Artifactory when branch is deleted.
When there is a really massive directory of docker images to delete (~50 GB), I’m getting an unexpected interrupt:
java.nio.channels.ClosedByInterruptException
at java.base/java.nio.channels.spi.AbstractInterruptibleChannel.end(AbstractInterruptibleChannel.java:199)
at java.base/sun.nio.ch.FileChannelImpl.endBlocking(FileChannelImpl.java:162)
at java.base/sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:285)
at org.jenkinsci.plugins.workflow.support.pickles.serialization.RiverWriter.<init>(RiverWriter.java:109)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:560)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:537)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgramIfPossible(CpsThreadGroup.java:520)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:444)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$400(CpsThreadGroup.java:97)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:315)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:279)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:67)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:139)
at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
at jenkins.security.ImpersonatingExecutorService$1.run(ImpersonatingExecutorService.java:68)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)
Finished: FAILURE
My code is not included in the stack trace…
The code which performs the HTTP requests is:
def deleteArtifact(String pathOnServer){
def responseCode, data
Boolean deleted = true
Logger.printInfo(steps, "Deleting $server/$pathOnServer artifact from server")
steps.withCredentials([steps.usernamePassword(credentialsId: 'artifactory_user', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME')]){
(responseCode, data) = sendApiRequest("$server/$pathOnServer", "DELETE")
}
//if !2xxSuccessful() -> Http response codes family - 1xx: Informational, 2xx: Success, 3xx: Redirection, 4xx: Client Error, 5xx: Server Error
if((responseCode / 100 as int) != 2){
deleted = false
Logger.printError(steps, "Failed to delete: `$pathOnServer` from `$server`. Status Code: $responseCode")
Logger.printError(steps, "Data: $data")
}
return deleted
}
def sendApiRequest(String query, String httpMethod, String contentType ="", String data =""){
def responseCode
def responseData
def conn = new URL("${this.protocol}://$query").openConnection()
//Trying to increase timeout
conn.setConnectTimeout(15 * 60 *60 * 1000);
conn.setReadTimeout(15 * 60 *60 * 1000);
def auth = "${steps.env.USERNAME}:${steps.env.PASSWORD}".getBytes().encodeBase64().toString()
conn.setRequestProperty("Authorization", "Basic ${auth}")
conn.setRequestMethod(httpMethod)
if(contentType) conn.setRequestProperty( "Content-Type", contentType);
if(data){
conn.setDoOutput(true)
conn.getOutputStream().write(data.getBytes("UTF-8"));
//Note: the POST will start when you try to read a value from the HttpURLConnection, such as responseCode, inputStream.text, or getHeaderField('...'). (https://stackoverflow.com/a/47489805/10025322)
}
responseCode = conn.getResponseCode()
try{
responseData = conn.getInputStream().getText()
}catch(IOException e){
responseData = e.getMessage()
}
conn = null
return [responseCode, responseData]
}
I also tried to use a different library for performing the request but still getting the exception when Artifactory responses slowly (Delete huge directory):
def sendApiRequest(String query, String httpMethod, String contentType ="", String data =""){
def responseCode
def responseData
def http = new HTTPBuilder("${this.protocol}://$query")
http.request(Method.valueOf(httpMethod)) {
headers.'Authorization' = "Basic ${steps.env.USERNAME}:${steps.env.PASSWORD}".getBytes().encodeBase64().toString()
if (contentType) {
headers.'Content-Type' = contentType
requestContentType = contentType
}
if (data) {
body = data
}
response.success = { resp, reader ->
responseCode = resp.statusLine.statusCode
responseData = reader.text
}
response.failure = { resp, reader ->
responseCode = resp.statusLine.statusCode
responseData = reader.text
}
}
echo("RESPONSE_CODE: " + responseCode.toString() + " RESPONSE_DATA: " + responseData.toString())
return [responseCode, responseData]
}
I found that the ClosedByInterruptException may occur due to the following reasons:
The thread running the code was interrupted.
The connection to the remote server was closed due to a network error.
The server explicitly closed the connection.
The read/write operation timed out.
There was an interruption or failure in the underlying I/O operations.
The JVM was shut down while the operation was in progress.
Any idea how to handle/workaround?
The provided code doesn't work due to a bug in Jenkins' core (this issue was marked as fixed in jenkins >= 2.332.1LTS or 2.335)
As a workaround you can use:
def sendApiRequest(String query, String httpMethod, String contentType ="", String data =""){
/*
Caller must wrap function call with 'withCredentials' statement
with 'USERNAME' and 'PASSWORD' environment varaiables
*/
String apiCmd = """curl -s -w '###%{http_code}' -X '${httpMethod}' \
'${this.protocol}://$query' \
${contentType ? "-H 'Content-Type: $contentType'" : ''} \
-u "\$USERNAME:\$PASSWORD" \
${data ? "-d '${data}'" : ''}"""
def response = steps.sh(returnStdout: true, script: apiCmd, label: "Send API request to Artifactory").trim()
def responseCode = response.split("###")[1]
def responseData = response.split("###")[0]
try{
responseCode = responseCode.toInteger()
} catch (NumberFormatException e) {
throw new RuntimeException("Invalid status code: `$responseCode` cannot cast to integer")
}
return [responseCode, responseData]
}

Karate afterFeature function execution works fine when run locally but fails when run through Jenkins

Karate afterFeature function execution works fine when run locally but fails when run through Jenkins, I get assertion failed: assert evaluated to false: responseStatus == 200 || responseStatus == 404. Whereas the responseStatus should either be 200 or 404.
Code Snippet
main.feature snippet
Background:
...
* def myName1 = 'karate-test-name'
* configure afterFeature = function(){ karate.call('cleanup.feature'); }
...
...
cleanup.feature
#ignore
Feature: To cleanup after main.feature execution. This Feature is not supposed to be run individually.
Background:
* url myUrl
Scenario: Delete
* print 'In "cleanup.feature", If exists delete: ' + myName1
Given path 'v1/myapi/',myName1,''
And header Content-Type = 'application/json; charset=utf-8'
And request {}
When method delete
Then assert responseStatus == 200 || responseStatus == 404
Logs from Jenkins:
The assertion for the responseStatus fails, but it does not log the actual value of the responseStatus.
23:03:15.448 [pool-1-thread-4] ERROR com.intuit.karate - assertion failed: assert evaluated to false: responseStatus == 200 || responseStatus == 404
23:03:15.450 [pool-1-thread-4] ERROR com.intuit.karate - feature call failed: cleanup.feature
arg: null
cleanup.feature:16 - assert evaluated to false: responseStatus == 200 || responseStatus == 404
23:03:15.451 [pool-1-thread-4] ERROR com.intuit.karate - javascript function call failed:
cleanup.feature:16 - assert evaluated to false: responseStatus == 200 || responseStatus == 404
23:03:15.451 [pool-1-thread-4] ERROR com.intuit.karate - failed function body: function(){ karate.call('cleanup.feature'); }
Moreover, I do not see the logs for execution of afterFeature in Jenkins, neither it is part of the Cucumber report for me to do further analysis.
Most likely an old version of Karate. Try 0.9.5
If you still can't solve this - please follow this process: https://github.com/intuit/karate/wiki/How-to-Submit-an-Issue
And also, please read this for other options: https://stackoverflow.com/a/60944060/143475

Invoking getQueueUrl() on FIFO Queue with SSE Enabled Results in 403 / All requests to this queue must use HTTPS and SigV4

I am using a SQS FIFO queue with SSE enabled. When I use a SQS client to call getQueueUrl(), an exception is thrown with the message All requests to this queue must use HTTPS and SigV4.
Using the latest version of the aws-java-sdk:
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.160</version>
</dependency>
The following code reproduces the issue:
public class SimpleSqsClient {
private static ClientConfiguration clientConfiguration() {
ClientConfiguration clientConfiguration = new ClientConfiguration();
clientConfiguration.setProxyHost("proxy.foo.com");
clientConfiguration.setProxyPort(8099);
clientConfiguration.setProxyUsername("username");
clientConfiguration.setProxyPassword("password");
clientConfiguration.setProtocol(Protocol.HTTP);
clientConfiguration.setPreemptiveBasicProxyAuth(false);
return clientConfiguration;
}
public static void main(String[] args) throws Exception {
/*
* The ProfileCredentialsProvider will return your [default] credential
* profile by reading from the credentials file located at
* (~/.aws/credentials).
*/
AWSCredentials credentials = null;
try {
credentials = new ProfileCredentialsProvider().getCredentials();
} catch (Exception e) {
throw new AmazonClientException("Cannot load the credentials from the credential profiles file. "
+ "Please make sure that your credentials file is at the correct "
+ "location (~/.aws/credentials), and is in valid format.", e);
}
AmazonSQS sqs = AmazonSQSClientBuilder.standard().withClientConfiguration(clientConfiguration())
.withCredentials(new ProfileCredentialsProvider("SOME_PROFILE"))
.withRegion(Regions.US_EAST_1).build();
System.out.println("===========================================");
System.out.println("Simple SQS Test");
System.out.println("===========================================\n");
try {
System.out.println(sqs.getQueueUrl("some-sse-enabled-queue.fifo"));
} catch (AmazonServiceException ase) {
System.out.println("Caught an AmazonServiceException, which means your request made it "
+ "to Amazon SQS, but was rejected with an error response for some reason.");
System.out.println("Error Message: " + ase.getMessage());
System.out.println("HTTP Status Code: " + ase.getStatusCode());
System.out.println("AWS Error Code: " + ase.getErrorCode());
System.out.println("Error Type: " + ase.getErrorType());
System.out.println("Request ID: " + ase.getRequestId());
} catch (AmazonClientException ace) {
System.out.println("Caught an AmazonClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with SQS, such as not "
+ "being able to access the network.");
System.out.println("Error Message: " + ace.getMessage());
}
}
}
Output:
Caught an AmazonServiceException, which means your request made it to Amazon SQS, but was rejected with an error response for some reason.
Error Message: All requests to this queue must use HTTPS and SigV4. (Service: AmazonSQS; Status Code: 403; Error Code: InvalidSecurity; Request ID: ...)
HTTP Status Code: 403
AWS Error Code: InvalidSecurity
Error Type: Client
Request ID: ...
Changing
clientConfiguration.setProtocol(Protocol.HTTP);
to
clientConfiguration.setProtocol(Protocol.HTTPS);
Resolved the issue

gatling response give me error message?

Gatling senario is
val scn = scenario("First Test Scenario").exec( Login.login )
setUp(
scn.inject(constantUsersPerSec(100) during(20 seconds) )
.protocols(httpConf)
)
object Login{
val login = exec(http("Login")
.get("/auth/login")
)
}
It give me that error message:
21:24:23.863 [WARN ] i.g.h.a.ResponseProcessor - Request 'Login' failed: j.n.ConnectException: Failed to open a socket. what does that mean?

User cancelled file download in Grails

How to properly handle a cancelled file download? The file in question is a pretty large zip file that takes a long time to build, so the user has plenty of time to hit the Cancel button on his download dialog window.
When it happens, a nasty Exception occurs (see below), which is expected, since the client broke the pipe. But how to clean it up? Where/What's the proper way to catch the Exception so that the tomcat logs are not littered with them?
Thank you.
The download code itself is pretty standard code from the textbook:
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
def getZipFile(params) {
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setHeader("Content-Disposition", "attachment; filename=\"filename.zip\"");
response.contentType = "application/zip"
def zos = new ZipOutputStream(response.outputStream)
zos = functionThatCreatesTheZipFile(zos, params) // this takes some time
zos.close()
}
Exception:
rfpmgr [2013-05-01 10:14:32.337] ERROR: web.errors.GrailsExceptionResolver IOException occurred when processing request: [GET] /rfpManager/report/downloadZipFile
Stacktrace follows:
java.io.IOException
at java.util.zip.ZipOutputStream.writeBytes(ZipOutputStream.java:617)
at java.util.zip.ZipOutputStream.writeCEN(ZipOutputStream.java:501)
at java.util.zip.ZipOutputStream.finish(ZipOutputStream.java:348)
at java.util.zip.DeflaterOutputStream.close(DeflaterOutputStream.java:238)
at java.util.zip.ZipOutputStream.close(ZipOutputStream.java:360)
at gov.usgs.eventManager.ZipService.getZipFile(ZipService.groovy:32)
at gov.usgs.eventManager.ReportController$_closure18.doCall(ReportController.groovy:738)
at gov.usgs.jdt.josso.spring.JOSSOProcessingFilter.doFilter(JOSSOProcessingFilter.java:144)
at gov.usgs.jdt.josso.agent.GenericServletSSOAgentFilter.doFilter(GenericServletSSOAgentFilter.java:431)
at java.lang.Thread.run(Thread.java:722)
rfpmgr [2013-05-01 10:14:32.354] ERROR: web.errors.GrailsExceptionResolver IllegalStateException occurred when processing request: [GET] /rfpManager/report/downloadZipFile
getOutputStream() has already been called for this response. Stacktrace follows:
org.codehaus.groovy.grails.web.pages.exceptions.GroovyPagesException: Error processing GroovyPageView: getOutputStream() has already been called for this response
at gov.usgs.jdt.josso.spring.JOSSOProcessingFilter.doFilter(JOSSOProcessingFilter.java:144)
at gov.usgs.jdt.josso.agent.GenericServletSSOAgentFilter.doFilter(GenericServletSSOAgentFilter.java:431)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.IllegalStateException: getOutputStream() has already been called for this response
at gsp_rfpManager_errorserrors_gsp.run(gsp_rfpManager_errorserrors_gsp.groovy:17)
... 3 more
This seems to work just fine:
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import org.apache.catalina.connector.ClientAbortException
def getZipFile(params) {
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Pragma", "public");
response.setHeader("Content-Disposition", "attachment; filename=\"filename.zip\"");
response.contentType = "application/zip"
try {
def zos = new ZipOutputStream(response.outputStream)
zos = functionThatCreatesTheZipFile(zos, params) // this takes some time
zos.close()
}
catch (ClientAbortException ex) {
println "user aborted download"
}
}
I can see there:
Caused by: java.lang.IllegalStateException: getOutputStream() has already been called for this response
This is common for Grails controllers when directly rendering things. Solutions:
render ( file: <InputStream>, contentType: 'image/jpeg')
//or
render ( file: <byte[]>, contentType: 'image/jpeg')
//or
GrailsWebRequest webRequest =
(GrailsWebRequest) RequestContextHolder.currentRequestAttributes()
webRequest.setRenderView(false)
That should help.

Resources