You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by sv...@apache.org on 2016/09/06 11:54:44 UTC

[02/10] brooklyn-server git commit: Adds HttpExecutor interface

Adds HttpExecutor interface

Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/776a923c
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/776a923c
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/776a923c

Branch: refs/heads/master
Commit: 776a923c229fab34039d73ab078bc264b0cb0c2f
Parents: a36b641
Author: Aled Sage <al...@gmail.com>
Authored: Tue Aug 9 14:41:37 2016 +0100
Committer: Yavor Yanchev <ya...@yanchev.com>
Committed: Fri Aug 19 19:14:09 2016 +0300

----------------------------------------------------------------------
 .../util/http/executor/Credentials.java         |  31 +++++
 .../brooklyn/util/http/executor/HttpConfig.java |  59 ++++++++++
 .../util/http/executor/HttpExecutor.java        |  19 ++++
 .../util/http/executor/HttpRequest.java         | 110 ++++++++++++++++++
 .../util/http/executor/HttpRequestImpl.java     |  71 ++++++++++++
 .../util/http/executor/HttpResponse.java        | 112 +++++++++++++++++++
 .../util/http/executor/HttpResponseImpl.java    |  61 ++++++++++
 7 files changed, 463 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/776a923c/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/Credentials.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/Credentials.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/Credentials.java
new file mode 100644
index 0000000..2ca1c8a
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/Credentials.java
@@ -0,0 +1,31 @@
+package org.apache.brooklyn.util.http.executor;
+
+import com.google.common.annotations.Beta;
+
+@Beta
+public class Credentials {
+
+    private Credentials() {}
+    
+    public static BasicAuth basic(String username, String password) {
+        return new BasicAuth(username, password);
+    }
+    
+    public static class BasicAuth {
+        private final String username;
+        private final String password;
+
+        protected BasicAuth(String username, String password) {
+            this.username = username;
+            this.password = password;
+        }
+        
+        public String username() {
+            return username;
+        }
+        
+        public String password() {
+            return password;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/776a923c/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpConfig.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpConfig.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpConfig.java
new file mode 100644
index 0000000..d0f5369
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpConfig.java
@@ -0,0 +1,59 @@
+package org.apache.brooklyn.util.http.executor;
+
+import com.google.common.annotations.Beta;
+
+@Beta
+public class HttpConfig {
+
+    @Beta
+    public static class Builder {
+        private boolean laxRedirect;
+        private boolean trustAll;
+        private boolean trustSelfSigned;
+        
+        public Builder laxRedirect(boolean val) {
+            laxRedirect = val;
+            return this;
+        }
+        
+        public Builder trustAll(boolean val) {
+            trustAll = val;
+            return this;
+        }
+        
+        public Builder trustSelfSigned(boolean val) {
+            trustSelfSigned = val;
+            return this;
+        }
+        
+        public HttpConfig build() {
+            return new HttpConfig(this);
+        }
+    }
+    
+    public static Builder builder() {
+        return new Builder();
+    }
+    
+    private final boolean laxRedirect;
+    private final boolean trustAll;
+    private final boolean trustSelfSigned;
+
+    protected HttpConfig(Builder builder) {
+        laxRedirect = builder.laxRedirect;
+        trustAll = builder.trustAll;
+        trustSelfSigned = builder.trustSelfSigned;
+    }
+    
+    public boolean laxRedirect() {
+        return laxRedirect;
+    }
+    
+    public boolean trustAll() {
+        return trustAll;
+    }
+    
+    public boolean trustSelfSigned() {
+        return trustSelfSigned;
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/776a923c/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpExecutor.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpExecutor.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpExecutor.java
new file mode 100644
index 0000000..96891e4
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpExecutor.java
@@ -0,0 +1,19 @@
+package org.apache.brooklyn.util.http.executor;
+
+import java.io.IOException;
+
+/**
+ * An abstraction for executing HTTP requests, allowing an appropriate implementation to be chosen.
+ */
+public interface HttpExecutor {
+    
+    /**
+     * Synchronously send the request, and return its response.
+     * 
+     * To avoid leaking resources callers must close the response's content (or the response itself).
+     *  
+     * @throws IOException if a problem occurred talking to the server.
+     * @throws RuntimeException (and subclasses) if an unexpected error occurs creating the request.
+     */
+    HttpResponse execute(HttpRequest request) throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/776a923c/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpRequest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpRequest.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpRequest.java
new file mode 100644
index 0000000..e110854
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpRequest.java
@@ -0,0 +1,110 @@
+package org.apache.brooklyn.util.http.executor;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+
+@Beta
+public interface HttpRequest {
+    
+    // TODO Should we use InputStream for body (rather than byte[]). That would mean we don't have
+    // to hold the entire body in-memory, which might be important for really big payloads!
+    
+    @Beta
+    public static class Builder {
+        protected boolean isHttps;
+        protected URI uri;
+        protected String method;
+        protected byte[] body;
+        protected Multimap<String, String> headers = ArrayListMultimap.<String, String>create();
+        protected Credentials.BasicAuth credentials;
+        protected HttpConfig config;
+
+        public Builder isHttps(boolean val) {
+            isHttps = val;
+            return this;
+        }
+        
+        public Builder uri(URI val) {
+            uri = checkNotNull(val, "uri");
+            return this;
+        }
+
+        public Builder method(String val) {
+            method = checkNotNull(val, "method");
+            return this;
+        }
+
+        /**
+         * This val must not be modified after being passed in - the object will be used while executing the request. 
+         */
+        public Builder body(@Nullable byte[] val) {
+            body = val;
+            return this;
+        }
+        
+        public Builder headers(Multimap<String, String> val) {
+            headers.putAll(checkNotNull(val, "headers"));
+            return this;
+        }
+
+        public Builder headers(Map<String, String> val) {
+            if (checkNotNull(val, "headers").keySet().contains(null)) {
+                throw new NullPointerException("Headers must not contain null key");
+            }
+            for (Map.Entry<String, String> entry : val.entrySet()) {
+                header(entry.getKey(), entry.getValue());
+            }
+            return this;
+        }
+
+        public Builder header(String key, String val) {
+            headers.put(checkNotNull(key, "key"), val);
+            return this;
+        }
+
+        public Builder credentials(@Nullable Credentials.BasicAuth val) {
+            credentials = val;
+            return this;
+        }
+
+        public Builder config(@Nullable HttpConfig val) {
+            config = val;
+            return this;
+        }
+
+        public HttpRequest build() {
+            return new HttpRequestImpl(this);
+        }
+    }
+    
+    boolean isHttps();
+    
+    URI uri();
+
+    String method();
+
+    /**
+     * The payload of the request, or null if no payload (e.g. for GET requests). 
+     */
+    @Nullable
+    byte[] body();
+    
+    Multimap<String, String> headers();
+
+    @Nullable
+    Credentials.BasicAuth credentials();
+
+    /**
+     * Additional optional configuration to customize how the call is done.
+     */
+    @Nullable
+    HttpConfig config();
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/776a923c/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpRequestImpl.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpRequestImpl.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpRequestImpl.java
new file mode 100644
index 0000000..b3c21d2
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpRequestImpl.java
@@ -0,0 +1,71 @@
+package org.apache.brooklyn.util.http.executor;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.net.URI;
+
+import org.apache.brooklyn.util.http.executor.Credentials.BasicAuth;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+
+/**
+ * A (mostly) immutable http request. However, (for efficiency reasons) we do not copy the body.
+ */
+@Beta
+public class HttpRequestImpl implements HttpRequest {
+
+    protected final boolean isHttps;
+    protected final URI uri;
+    protected final String method;
+    protected final byte[] body;
+    protected final Multimap<String, String> headers;
+    protected final Credentials.BasicAuth credentials;
+    protected final HttpConfig config;
+
+    protected HttpRequestImpl(HttpRequest.Builder builder) {
+        this.isHttps = builder.isHttps;
+        this.uri = checkNotNull(builder.uri, "uri");
+        this.method = checkNotNull(builder.method, "method");
+        this.body = builder.body;
+        this.headers = Multimaps.unmodifiableMultimap(ArrayListMultimap.create(checkNotNull(builder.headers, "headers")));
+        this.credentials = builder.credentials;
+        this.config = builder.config;
+    }
+    
+    @Override
+    public boolean isHttps() {
+        return isHttps;
+    }
+    @Override
+    public URI uri() {
+        return uri;
+    }
+    
+    @Override
+    public String method() {
+        return method;
+    }
+    
+    @Override
+    public byte[] body() {
+        return body;
+    }
+    
+    @Override
+    public Multimap<String, String> headers() {
+        return headers;
+    }
+    
+    @Override
+    public BasicAuth credentials() {
+        return credentials;
+    }
+    
+    @Override
+    public HttpConfig config() {
+        return config;
+    }
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/776a923c/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpResponse.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpResponse.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpResponse.java
new file mode 100644
index 0000000..18fb5e8
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpResponse.java
@@ -0,0 +1,112 @@
+package org.apache.brooklyn.util.http.executor;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.Closeable;
+import java.io.InputStream;
+import java.util.Map;
+
+import javax.annotation.Nullable;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+
+/**
+ * An HTTP response. Instances of this class are not immutable: the response body is a 
+ * one-shot value that may be consumed only once and then closed. All other properties 
+ * are immutable.
+ * 
+ * This class implements {@link Closeable}. Closing it simply closes its response streams (if any).
+ */
+@Beta
+public interface HttpResponse extends Closeable {
+    
+    @Beta
+    public static class Builder {
+        protected int code;
+        protected String reasonPhrase;
+        protected Multimap<String, String> headers = ArrayListMultimap.<String, String>create();
+        protected long contentLength = -1;
+        protected InputStream content;
+
+        public Builder code(int val) {
+            code = val;
+            return this;
+        }
+        
+        public Builder reasonPhrase(@Nullable String val) {
+            reasonPhrase = val;
+            return this;
+        }
+
+        public Builder headers(Multimap<String, String> val) {
+            headers.putAll(headers);
+            return this;
+        }
+
+        public Builder headers(Map<String, String> val) {
+            if (checkNotNull(val, "headers").keySet().contains(null)) {
+                throw new NullPointerException("Headers must not contain null key");
+            }
+            for (Map.Entry<String, String> entry : val.entrySet()) {
+                header(entry.getKey(), entry.getValue());
+            }
+            return this;
+        }
+
+        public Builder header(String key, String val) {
+            headers.put(key, val);
+            return this;
+        }
+
+        public Builder content(@Nullable InputStream val) {
+            if (val != null) {
+                contentLength = -1;
+                content = val;
+            }
+            return this;
+        }
+        
+        public Builder content(@Nullable byte[] val) {
+            if (val != null) {
+                contentLength = val.length;
+                content = new ByteArrayInputStream(val);
+            }
+            return this;
+        }
+        
+        public HttpResponse build() {
+            return new HttpResponseImpl(this);
+        }
+    }
+
+    /**
+     * The HTTP status code.
+     */
+    public int code();
+
+    /**
+     * The HTTP reason phrase.
+     */
+    @Nullable
+    public String reasonPhrase();
+
+    public Multimap<String, String> headers();
+    
+    /**
+     * The length of the content, if known.
+     *
+     * @return  the number of bytes of the content, or a negative number if unknown. If the 
+     *          content length is known but exceeds {@link java.lang.Long#MAX_VALUE Long.MAX_VALUE},
+     *          a negative number is returned.
+     */
+    public long getContentLength();
+
+    /**
+     * The response body, or null if no body.
+     * @return
+     */
+    public InputStream getContent();
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/776a923c/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpResponseImpl.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpResponseImpl.java b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpResponseImpl.java
new file mode 100644
index 0000000..59c4acd
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/http/executor/HttpResponseImpl.java
@@ -0,0 +1,61 @@
+package org.apache.brooklyn.util.http.executor;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.brooklyn.util.stream.Streams;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.Multimap;
+
+@Beta
+public class HttpResponseImpl implements HttpResponse {
+
+    private final int code;
+    private final String reasonPhrase;
+    private final Multimap<String, String> headers;
+    private final long contentLength;
+    private final InputStream content;
+
+    protected HttpResponseImpl(HttpResponse.Builder builder) {
+        code = builder.code;
+        reasonPhrase = builder.reasonPhrase;
+        headers = checkNotNull(builder.headers, "headers");
+        contentLength = builder.contentLength;
+        content = builder.content;
+    }
+    
+    @Override
+    public void close() throws IOException {
+        if (content != null) {
+            Streams.closeQuietly(content);
+        }
+    }
+
+    @Override
+    public int code() {
+        return code;
+    }
+
+    @Override
+    public String reasonPhrase() {
+        return reasonPhrase;
+    }
+
+    @Override
+    public Multimap<String, String> headers() {
+        return headers;
+    }
+
+    @Override
+    public long getContentLength() {
+        return contentLength;
+    }
+
+    @Override
+    public InputStream getContent() {
+        return content;
+    }
+}