org.zodiac.sdk.nio.http.client.ClientEntryPoint Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of zodiac-sdk-nio Show documentation
Show all versions of zodiac-sdk-nio Show documentation
Zodiac SDK NIO2(New Non-Blocking IO)
package org.zodiac.sdk.nio.http.client;
import io.vavr.control.Either;
import io.vavr.control.Try;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import org.zodiac.sdk.cli.*;
import org.zodiac.sdk.nio.http.NioHttpConstants;
import org.zodiac.sdk.nio.http.TransportProtocol;
import org.zodiac.sdk.nio.http.common.HTTPMethod;
import org.zodiac.sdk.nio.http.common.HTTPRequest;
import org.zodiac.sdk.nio.http.common.HTTPResponse;
@Command(name = NioHttpConstants.HTTPC, description = "httpc is a curl-like application but supports HTTP protocol only.")
public class ClientEntryPoint {
@SubCommand(
name = "get",
argument = @Argument(
name = "url",
format = "https://some-website.ca",
regex = "(^(https://)?\\S+$)",
description = "The URL of the request."),
description = "Get executes a HTTP GET request for a given URL.")
String get;
@SubCommand(
name = "post",
argument = @Argument(
name = "url",
format = "https://some-website.ca",
regex = "(^(https://)?\\S+$)",
description = "The URL of the request."),
description = "Post executes a HTTP POST request for a given URL with inline data or from file.")
String post;
@Flag(
name = "verbose",
alias = {"--verbose", "-v"},
required = false,
subCommands = {"get", "post"},
description = "Prints the detail of the response such as protocol, status, and headers.")
boolean verbose;
@Flag(
name = "udp",
alias = {"--udp"},
required = false,
subCommands = {"get", "post"},
description = "Uses a UDP Selective Repeat protocol instead of the default TCP protocol.")
boolean udp;
@Option(
name = "headers",
alias = {"--header", "-h"},
argument = @Argument(
name = "header",
format = "key:value",
regex = "(^[^\\s\\:]+\\s*:\\s*[^\\s\\:]+$)",
description = ""),
subCommands = {"get", "post"},
description = "Associates headers to HTTP Request with the format 'key:value'")
List headers;
@Option(
name = "data",
alias = {"--data", "-d"},
argument = @Argument(name = "data",
format = "{\"prop\": \"value\"}",
regex = "(.*)", //""(^\\{(\\s*,?\\s*\\S+:\\s*\\S+\\s*)+\\}$)",
description = ""),
subCommands = {"post"},
description = "Associates an inline data to the body HTTP POST request.")
String data;
@Option(
name = "in",
alias = {"--file", "-f"},
argument = @Argument(name = "file",
format = "/file/to/body",
regex = "(^.*$)",
description = ""),
subCommands = {"post"},
description = "Associates the content of a file to the body HTTP POST request.")
String in;
@Option(
name = "out",
alias = {"--out", "-o"},
argument = @Argument(name = "out",
format = "/file/to/output",
regex = "(^\\/[\\w\\W]+\\.txt$)",
description = ""),
subCommands = {"get", "post"},
description = "Outputs the response of the HTTP request to a file.")
String out;
@Option(
name = "path",
alias = {"--path", "-p"},
argument = @Argument(name = "path",
format = "/some/path.txt",
regex = "(.*)",
description = ""),
subCommands = {"get", "post"},
description = "Associates a path to the request when UDP is used.")
String path;
public ClientEntryPoint() {
super();
}
public ClientEntryPoint(String get, String post, boolean verbose, boolean udp, List headers, String data,
String in, String out, String path) {
this.get = get;
this.post = post;
this.verbose = verbose;
this.udp = udp;
this.headers = headers;
this.data = data;
this.in = in;
this.out = out;
this.path = path;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((data == null) ? 0 : data.hashCode());
result = prime * result + ((get == null) ? 0 : get.hashCode());
result = prime * result + ((headers == null) ? 0 : headers.hashCode());
result = prime * result + ((in == null) ? 0 : in.hashCode());
result = prime * result + ((out == null) ? 0 : out.hashCode());
result = prime * result + ((path == null) ? 0 : path.hashCode());
result = prime * result + ((post == null) ? 0 : post.hashCode());
result = prime * result + (udp ? 1231 : 1237);
result = prime * result + (verbose ? 1231 : 1237);
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
ClientEntryPoint other = (ClientEntryPoint)obj;
if (data == null) {
if (other.data != null)
return false;
} else if (!data.equals(other.data))
return false;
if (get == null) {
if (other.get != null)
return false;
} else if (!get.equals(other.get))
return false;
if (headers == null) {
if (other.headers != null)
return false;
} else if (!headers.equals(other.headers))
return false;
if (in == null) {
if (other.in != null)
return false;
} else if (!in.equals(other.in))
return false;
if (out == null) {
if (other.out != null)
return false;
} else if (!out.equals(other.out))
return false;
if (path == null) {
if (other.path != null)
return false;
} else if (!path.equals(other.path))
return false;
if (post == null) {
if (other.post != null)
return false;
} else if (!post.equals(other.post))
return false;
if (udp != other.udp)
return false;
if (verbose != other.verbose)
return false;
return true;
}
@Override
public String toString() {
return "ClientEntryPoint [get=" + get + ", post=" + post + ", verbose=" + verbose + ", udp=" + udp + ", headers="
+ headers + ", data=" + data + ", in=" + in + ", out=" + out + ", path=" + path + "]";
}
public static void entryPoint(final String[] args) {
final Parser parser = new Parser<>(ClientEntryPoint.class);
final Try> result = parser.parse(String.join(" ", args));
result
.onSuccess(success -> {
if (success.isLeft()) {
System.out.println(success.getLeft());
}
if (success.isRight()) {
exec(success.get())
.onSuccess(response -> {
String whatToPrint = "\n";
if (success.get().verbose) {
whatToPrint += response != null && response.getRequest() != null ? response.getRequest() + "\n" : "";
whatToPrint += response != null && response.getRequest() != null ? response.messageHeader() : "\n\n";
}
whatToPrint += response != null && response.getRequest() != null ? "\n\n" + response.getBody() : "\n";
if (success.get().out != null && response != null) {
byte[] whatToPrintInBytes = whatToPrint.getBytes();
Try.of(() -> Files.write(Paths.get(success.get().out), whatToPrintInBytes))
.onSuccess(nothing -> System.out.println("Output saved in " + success.get().out))
.onFailure(failure -> System.out.println(
"Something went wrong trying to save the contents of the response to the file. " + failure.getClass()
.getSimpleName() + ": " + failure.getMessage()));
} else {
System.out.println(whatToPrint);
}
})
.onFailure(failure -> {
System.err.println(failure.getMessage());
System.err.println(parser.help());
System.exit(1);
});
}
})
.onFailure(failure -> {
System.err.println(failure.getMessage());
System.err.println(parser.help());
System.exit(1);
});
}
static Try exec(final ClientEntryPoint ep) {
try {
if (ep.get == null && ep.post == null) {
throw new ParseError("At least one of the possible sub-commands and a url must be specified.");
}
String host = ep.get != null ? ep.get : ep.post;
if (ep.udp) {
if (host.startsWith("http")) {
throw new ParseError("Invalid host url, do not specify an http:// prefix in UDP mode. Use the host address with " +
"port such as 'localhost:8007'");
}
} else {
if (ep.path != null) {
throw new ParseError("Invalid option specified. Do not specify the '-p'/'--path' option while in TCP mode. Use the " +
"host path instead, such as 'http://localhost:80'");
}
if (!host.startsWith("http://") || !host.startsWith("https://")) {
host = "http://" + host;
}
}
if (ep.get != null && ep.in != null) {
throw new ParseError("Only specify both the '-f'/'--file' option when making a GET request.");
}
final HTTPRequest request = HTTPRequest.builder()
.method(ep.get != null ? HTTPMethod.GET : HTTPMethod.POST)
.url(host)
.headers(ep.headers)
.body(ep.data)
.in(ep.in)
.out(ep.out)
.path(ep.path)
.build();
return Try.of(() -> new Client(TransportProtocol.of(TransportProtocol.Type.of(ep.udp ? "UDP" : "TCP"))).request(request));
} catch (final ParseError e) {
return Try.failure(e);
} catch (final MalformedURLException e) {
return Try.failure(new HTTPRequest.RequestError("Something went wrong while trying to parse the url. \n" + e.getClass()
.getSimpleName() + ": " + e.getMessage()));
} catch (final IOException e) {
return Try.failure(new HTTPRequest.RequestError("Something went wrong while trying to read the contents of the input file. \n" + e
.getClass()
.getSimpleName() + ": " + e.getMessage()));
} catch (final HTTPRequest.RequestError e) {
return Try.failure(new HTTPRequest.RequestError("Something went wrong while processing the request. \n" + e.getClass()
.getSimpleName() + ": " + e.getMessage()));
}
}
}