Commit d98f5993 authored by Mohamad Bashar Desoki's avatar Mohamad Bashar Desoki

Simple HTTP Server and Client

parents
# Network Communication
## Simple HTTP Server and Client
*Some useful links*
* [HttpServer Class](https://docs.oracle.com/javase/8/docs/jre/api/net/httpserver/spec/com/sun/net/httpserver/HttpServer.html)
* [HttpClient Class](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpClient.html)
* [HttpRequest Class](https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/HttpRequest.html)
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>httpclient</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
\ No newline at end of file
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class Aggregator {
private WebClient webClient;
public Aggregator() {
this.webClient = new WebClient();
}
/*send task to list of workers*/
public List<String> sendTasksToWorkers(List<String> workersAddresses, List<String> tasks) {
/*
Add your code here
*/
throw new UnsupportedOperationException();
}
/*send task to list of workers*/
public List<String> sendTasksToWorkers(List<String> workersAddresses, List<String> tasks, String headers) {
/*
Add your code here
*/
throw new UnsupportedOperationException();
}
}
import java.util.Arrays;
import java.util.List;
public class Application {
private static final String WORKER_ADDRESS_1 = "http://localhost:8080/task";
private static final String WORKER_ADDRESS_2 = "http://localhost:8081/task";
public static void main(String[] args) {
Aggregator aggregator = new Aggregator();
String task1 = "10,200";
String task2 = "123456789,100000000000000,700000002342343";
String headers = "X-Debug: true";
List<String> results = aggregator.sendTasksToWorkers(Arrays.asList(WORKER_ADDRESS_1, WORKER_ADDRESS_2),
Arrays.asList(task1, task2));
for (String result : results) {
System.out.println(result);
}
List<String> resultsWithHeaders = aggregator.sendTasksToWorkers(Arrays.asList(WORKER_ADDRESS_1, WORKER_ADDRESS_2),
Arrays.asList(task1, task2), headers);
for (String result : resultsWithHeaders) {
System.out.println(result);
}
}
}
import java.net.http.HttpClient;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class WebClient {
private HttpClient client;
/* instantiate web client */
/* Read more about Builder pattern https://en.wikipedia.org/wiki/Builder_pattern*/
public WebClient() {
this.client = HttpClient.newBuilder().version(HttpClient.Version.HTTP_2).build();
}
/* send task (post http request) asynchronously */
public CompletableFuture<String> sendTask(String url, byte[] requestPayload) {
/*
Add your code here
*/
throw new UnsupportedOperationException();
}
/* send task (post http request) asynchronously with custom headers*/
public CompletableFuture<String> sendTask(String url, byte[] requestPayload, String headers) {
/*
Add your code here
*/
throw new UnsupportedOperationException();
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>httpserver</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>9</source>
<target>9</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
import com.sun.net.httpserver.*;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.concurrent.Executors;
import java.util.logging.Logger;
public class WebServer {
static final Logger logger = Logger.getLogger("WebServer");
private static final String TASK_ENDPOINT = "/task";
private static final String Status_ENDPOINT = "/status";
private final int port;
private HttpServer server;
public WebServer(int port) {
this.port = port;
}
public static void main(String[] args) {
int serverPort = 8080;
if (args.length == 1) {
serverPort = Integer.parseInt(args[0]);
}
WebServer webServer = new WebServer(serverPort);
webServer.startServer();
System.out.println("Server is listening on port " + serverPort);
}
public void startServer() {
try {
this.server = HttpServer.create(new InetSocketAddress(port), 0);
} catch (IOException e) {
throw new RuntimeException(e);
}
HttpContext statusContext = server.createContext(Status_ENDPOINT);
HttpContext taskContext = server.createContext(TASK_ENDPOINT);
statusContext.setHandler(this::handleStatusCheckRequest);
taskContext.setHandler(this::handleTaskRequest);
server.setExecutor(Executors.newFixedThreadPool(8));
server.start();
}
private void handleTaskRequest(HttpExchange exchange) throws IOException {
if (!exchange.getRequestMethod().equalsIgnoreCase("post")) {
exchange.close();
return;
}
Headers headers = exchange.getRequestHeaders();
if (headers.containsKey("X-Test") && headers.get("X-Test").get(0).equalsIgnoreCase("true")) {
String dummyResp = "123\n";
sendResponse(dummyResp.getBytes(), exchange);
return;
}
boolean isDebugMode = false;
if (headers.containsKey("X-Debug") && headers.get("X-Debug").get(0).equalsIgnoreCase("true")) {
isDebugMode = true;
}
long startTime = System.nanoTime();
byte[] requestBytes = exchange.getRequestBody().readAllBytes();
byte[] responseBytes = calculateResponse(requestBytes);
long finishTime = System.nanoTime();
if (isDebugMode) {
String debugMessage = String.format("Operation took %d ns", finishTime - startTime);
exchange.getResponseHeaders().put("X-Debug-Info", Arrays.asList(debugMessage));
}
sendResponse(responseBytes, exchange);
}
private byte[] calculateResponse(byte[] requestBytes) {
String bodyString = new String(requestBytes);
String[] stringNumbers = bodyString.split(",");
BigInteger result = BigInteger.ONE;
for (String number : stringNumbers) {
BigInteger bigInteger = new BigInteger(number);
result = result.multiply(bigInteger);
}
return String.format("Result of the multiplication is %s\n", result).getBytes();
}
private void handleStatusCheckRequest(HttpExchange exchange) throws IOException {
if (!exchange.getRequestMethod().equalsIgnoreCase("get")) {
exchange.close();
return;
}
String responseMessage = "Server is alive\n";
sendResponse(responseMessage.getBytes(), exchange);
}
private void sendResponse(byte[] responseBytes, HttpExchange exchange) throws IOException {
exchange.sendResponseHeaders(200, responseBytes.length);
OutputStream outputStream = exchange.getResponseBody();
outputStream.write(responseBytes);
outputStream.flush();
outputStream.close();
exchange.close();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment