Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/main/java/org/juv25d/Pipeline.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ public void addFilter(Filter filter) {
}

public void setPlugin(Plugin plugin) {
if (plugin == null) {
throw new IllegalArgumentException("Plugin cannot be null");
}
this.plugin = plugin;
}

Expand All @@ -31,4 +34,12 @@ public void init() {
public void destroy() {
filters.forEach(Filter::destroy);
}

public List<Filter> getFilters() {
return filters;
}
Comment thread
fmazmz marked this conversation as resolved.

public Plugin getPlugin() {
return plugin;
}
}
46 changes: 33 additions & 13 deletions src/main/java/org/juv25d/http/HttpResponse.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,57 @@

import java.util.*;

/**
* Represents an HTTP Response.
* Changed to be mutable to allow Filters and Plugins in the Pipeline
* to modify status, headers, and body during processing.
*/
Comment thread
LinusWestling marked this conversation as resolved.
public class HttpResponse {

private final int statusCode;
private final String statusText;
private final Map<String, String> headers;
private final byte[] body;
private int statusCode;
private String statusText;
private Map<String, String> headers;
private byte[] body;

public HttpResponse(){}

public HttpResponse(int statusCode, String statusText, Map<String, String> headers, byte[] body) {
Objects.requireNonNull(statusText, "statusText must not be null");
Objects.requireNonNull(headers, "headers must not be null");
Objects.requireNonNull(body, "body must not be null");
this.statusCode = statusCode;
this.statusText = statusText;
this.headers = Collections.unmodifiableMap(new LinkedHashMap<>(headers));
this.body = body.clone();
this.headers = new LinkedHashMap<>(headers);
this.body = body != null ? body.clone() : new byte[0];
}
Comment thread
LinusWestling marked this conversation as resolved.

public int statusCode(){
public int statusCode() {
return statusCode;
}

public String statusText(){
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}

public String statusText() {
return statusText;
}

public void setStatusText(String statusText) {
Objects.requireNonNull(statusText, "statusText must not be null");
this.statusText = statusText;
}
Comment thread
LinusWestling marked this conversation as resolved.

public Map<String, String> headers() {
return headers;
}

public byte[] body(){
return body.clone();
public void setHeader(String name, String value) {
headers.put(name, value);
}
Comment thread
fmazmz marked this conversation as resolved.

public byte[] body() {
return body != null ? body.clone() : new byte[0];
}

public void setBody(byte[] body) {
this.body = body != null ? body.clone() : new byte[0];
}
}
15 changes: 15 additions & 0 deletions src/main/java/org/juv25d/plugin/NotFoundPlugin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.juv25d.plugin;

import org.juv25d.http.HttpRequest;
import org.juv25d.http.HttpResponse;

import java.io.IOException;

public class NotFoundPlugin implements Plugin {
@Override
public void handle(HttpRequest req, HttpResponse res) throws IOException {
res.setStatusCode(404);
res.setStatusText("Not Found");
res.setBody("404 - Resource Not Found".getBytes());
}
}
25 changes: 25 additions & 0 deletions src/test/java/org/juv25d/PipelineTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.juv25d;

import org.junit.jupiter.api.Test;
import org.juv25d.plugin.HelloPlugin;

import static org.junit.jupiter.api.Assertions.*;

class PipelineTest {

@Test
void throwsExceptionWhenSettingNullPlugin() {
Pipeline pipeline = new Pipeline();
assertThrows(IllegalArgumentException.class, () -> pipeline.setPlugin(null));
}

@Test
void customPluginIsUsed() {
Pipeline pipeline = new Pipeline();
HelloPlugin hello = new HelloPlugin();

pipeline.setPlugin(hello);

assertEquals(hello, pipeline.getPlugin());
}
Comment thread
fmazmz marked this conversation as resolved.
}
5 changes: 3 additions & 2 deletions src/test/java/org/juv25d/filter/LoggingFilterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import java.io.IOException;

import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.*;

class LoggingFilterTest {
Expand Down Expand Up @@ -42,9 +43,9 @@ void logsHttpMethodAndPath() throws IOException {
filter.doFilter(req, res, chain);

String output = out.toString();
assert output.contains("GET /test");
assertTrue(output.contains("GET /test"), "Output should contain logged method and path");
} finally {
System.setOut(originalOut);
}
}
}
}
26 changes: 26 additions & 0 deletions src/test/java/org/juv25d/plugin/NotFoundPluginTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.juv25d.plugin;

import org.juv25d.http.HttpRequest;
import org.juv25d.http.HttpResponse;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;

class NotFoundPluginTest {

@Test
void sets404StatusAndBody() throws IOException {
NotFoundPlugin plugin = new NotFoundPlugin();
HttpRequest req = new HttpRequest("GET", "/unknown", null, "HTTP/1.1", Map.of(), new byte[0]);
HttpResponse res = new HttpResponse();

plugin.handle(req, res);

assertEquals(404, res.statusCode());
assertEquals("Not Found", res.statusText());
assertArrayEquals("404 - Resource Not Found".getBytes(), res.body());
}
}