Skip to content

Feat 128 metric info not complete#24

Closed
Tyreviel wants to merge 55 commits intomainfrom
feat-128-metric-info
Closed

Feat 128 metric info not complete#24
Tyreviel wants to merge 55 commits intomainfrom
feat-128-metric-info

Conversation

@Tyreviel
Copy link

@Tyreviel Tyreviel commented Feb 26, 2026

Closes issue #128

Made changes to ensure that the server's version and commit information are correctly reported when building and running via Docker

Summary by CodeRabbit

  • New Features

    • Java HTTP Server application with static file serving, routing, and middleware pipeline support
    • Web-based user interface with dynamic content rendering
    • IP-based access control (whitelist/blacklist)
    • Rate limiting with configurable requests per minute
    • CORS and security headers configuration
    • HTTP redirect rules for URL remapping
    • Health check and metrics endpoints for monitoring
    • HTTP proxy routing to upstream services
    • Request logging and timing filters
  • Infrastructure

    • Docker containerization with multi-architecture builds (AMD64, ARM64)
    • GitHub Actions CI/CD pipeline with automated testing and Docker image publishing
    • Comprehensive configuration via YAML (server settings, proxies, rate limits)
  • Documentation

    • Project README with architecture overview and usage instructions
    • Architectural decision records for design rationale

fmazmz and others added 30 commits February 6, 2026 08:44
* chore: Update POM to Java 25 and rename artifactId/groupId

* update folder name from example to juv25d

---------

Co-authored-by: WHITEROSE <firasmoussa60@gmail.com>
* http parser

* Bunny fixes. (only using input stream to recieve requests)

* Bunny review improvements

* Improved http parser ReadLine helper method to eliminate dependency on mark() and reset(). Implemented handleClient() using socket as a try-with-resources to avoid memory leakage in case of exception thrown by httpparser-methods.

* NumberFormatException fix on line 53 -> 60

* chore: Update POM to Java 25 and rename artifactId/groupId (#11)

* chore: Update POM to Java 25 and rename artifactId/groupId

* update folder name from example to juv25d

---------

Co-authored-by: WHITEROSE <firasmoussa60@gmail.com>

* resolve conflicts

---------

Co-authored-by: Kristina <kristina0x7@gmail.com>
Co-authored-by: WHITEROSE <firasmoussa60@gmail.com>
* Add ServerLogging.java as separate class for logging. Implement said class in SocketServer.java to return logging information upon opening socket and user connecting to server.

* Update ServerLogging.java to include a static initializer block and an empty utility class to prevent instantiation.

* Update ServerLogging.java to reference same class in getLogger argument.

* Update ServerLogging.java to check if handler has already been instantiated and allow for log level to be set by args in JVM (default level 'INFO' if no args provided).

* normalize logging statements to be consistent

* remove unused imports

* Update SockerServer.java to properly log server socket errors.

---------

Co-authored-by: Mats Rönnqvist <mats.f.ronnqvist@gmail.com>
Co-authored-by: WHITEROSE <firasmoussa60@gmail.com>
* update POM with pitest

* add junit plugin dependency
Rebased 4 commits in this PR.
…#27)

* Fix PiTest by defining argLine and removing invalid Mockito javaagent

* self close argline
…edicated ConnectionHandler. (#28)

* Rename SocketServer to Server
Move HTTP request handling logic to a dedicated ConnectionHandler.

* Convert createSocket to an instance method named start().

* Replace console prints with Logger in ConnectionHandler

* Fixed typo in ConnectionHandler

* refactor Server and ConnectionHandler:
- Inject Logger inside of constructor
- Inject handlerFactory into the Server that handles creation of a new ConnectionHandler on each request
- Remove HttpParser from Server as it is not handling the parsing of a request

* accept ConnectionHandlerFactory and not a specific implementation

* normalize handlerFactory name

---------

Co-authored-by: WHITEROSE <firasmoussa60@gmail.com>
…tests. (#34)

* Add testing for ServerLogging.java. Configure ServerLogging.java to improve its testability.

* Update logger_shouldNotAddDuplicateHandlers test to properly test non-inclusion of duplicates.

* Update ServerLogging.java to guard against invalid level string entries in configure method (logger.parse => setLevel).
* http parser

* Bunny fixes. (only using input stream to recieve requests)

* Bunny review improvements

* Improved http parser ReadLine helper method to eliminate dependency on mark() and reset(). Implemented handleClient() using socket as a try-with-resources to avoid memory leakage in case of exception thrown by httpparser-methods.

* NumberFormatException fix on line 53 -> 60

* Added foundation for Filters and Plugins. Added FilterChain to use created filters, and a Pipeline class to handle the workflow (Client → Filters → Plugin → Response → Client). Modified SocketServer handleClient() to use FilterChain. Added example code in App.java for Pipeline usage. TODO: Initialize HttpResponse class

* Fixing build fail

* add init and destroy to filter interface

* add methods to pipeline class

* Add servlet-style filter pipeline with lifecycle support

* add documentation about temporary server impl

* test: verify filters execute in order and plugin is called last

* test: add coverage for filter blocking, lifecycle init, and empty pipeline

* add loggingfiltertest

* fix: construct HttpResponse with required arguments

* fix: construct HttpResponse with required arguments

* Update FilterChainImpl tests to use full HttpResponse constructor to ensure compatibility with future implementations

* remove duplicated class

---------

Co-authored-by: Kristina M <kristina0x7@gmail.com>
Co-authored-by: WHITEROSE <firasmoussa60@gmail.com>
… ADR process for the team (#35)

- Add TEMPLATE for writing future ADRs
                                      - Add ADR-001 documenting static file serving architecture

                                      Closes #16
…39)

* feat: make HttpResponse mutable and implement NotFoundPlugin default

- Updated HttpResponse to be mutable to allow filters and plugins to modify responses.
- Implemented NotFoundPlugin as a default fallback for the Pipeline.
- Added null safety check in Pipeline.setPlugin.
- Added unit tests for Pipeline default behavior and NotFoundPlugin.

* ran mvn spotless:apply to fix violations

* Rabbit comment fixes

* Review fixes

* Final buggfixes for this PR (again)
* Implement static file handler with security and tests

Core Implementation:
- Add StaticFileHandler for serving files from /resources/static/
- Add MimeTypeResolver for Content-Type detection
- Add security validation to prevent path traversal attacks

Testing:
- Add MimeTypeResolverTest (15 test cases)
- Add StaticFileHandlerTest (20+ test cases)
- All tests passing

Example Files:
- Add index.html demo page with gradient styling
- Add styles.css for professional styling
- Add app.js for JavaScript functionality demo

Note: Integration with Server/ConnectionHandler will be added
after PR #28 merges to avoid conflicts.

Foundation work for #18

* Introduce ADR structure and first ADR - Add ADR README explaining the ADR process for the team
                                     - Add TEMPLATE for writing future ADRs
                                      - Add ADR-001 documenting static file serving architecture

                                      Closes #16

* Rename SocketServer to Server Move HTTP request handling logic to a dedicated ConnectionHandler. (#28)

* Rename SocketServer to Server
Move HTTP request handling logic to a dedicated ConnectionHandler.

* Convert createSocket to an instance method named start().

* Replace console prints with Logger in ConnectionHandler

* Fixed typo in ConnectionHandler

* refactor Server and ConnectionHandler:
- Inject Logger inside of constructor
- Inject handlerFactory into the Server that handles creation of a new ConnectionHandler on each request
- Remove HttpParser from Server as it is not handling the parsing of a request

* accept ConnectionHandlerFactory and not a specific implementation

* normalize handlerFactory name

---------

Co-authored-by: WHITEROSE <firasmoussa60@gmail.com>

* Add testing for ServerLogging.java. Configure ServerLogging.java for tests. (#34)

* Add testing for ServerLogging.java. Configure ServerLogging.java to improve its testability.

* Update logger_shouldNotAddDuplicateHandlers test to properly test non-inclusion of duplicates.

* Update ServerLogging.java to guard against invalid level string entries in configure method (logger.parse => setLevel).

* feature/FilterPlugin (#17)

* http parser

* Bunny fixes. (only using input stream to recieve requests)

* Bunny review improvements

* Improved http parser ReadLine helper method to eliminate dependency on mark() and reset(). Implemented handleClient() using socket as a try-with-resources to avoid memory leakage in case of exception thrown by httpparser-methods.

* NumberFormatException fix on line 53 -> 60

* Added foundation for Filters and Plugins. Added FilterChain to use created filters, and a Pipeline class to handle the workflow (Client → Filters → Plugin → Response → Client). Modified SocketServer handleClient() to use FilterChain. Added example code in App.java for Pipeline usage. TODO: Initialize HttpResponse class

* Fixing build fail

* add init and destroy to filter interface

* add methods to pipeline class

* Add servlet-style filter pipeline with lifecycle support

* add documentation about temporary server impl

* test: verify filters execute in order and plugin is called last

* test: add coverage for filter blocking, lifecycle init, and empty pipeline

* add loggingfiltertest

* fix: construct HttpResponse with required arguments

* fix: construct HttpResponse with required arguments

* Update FilterChainImpl tests to use full HttpResponse constructor to ensure compatibility with future implementations

* remove duplicated class

---------

Co-authored-by: Kristina M <kristina0x7@gmail.com>
Co-authored-by: WHITEROSE <firasmoussa60@gmail.com>

* Add charset=utf-8 to text-based Content-Type headers

* Integrate StaticFileHandler with Pipeline architecture

* Refactor  to use immutable fields and clean up unused setters; update  with usage notes for future integration.

* Enhance StaticFilesPlugin to properly handle headers with map iteration; simplify and clarify class documentation.

* Update tests to verify Content-Type headers include charset=utf-8

* connect StaticFilesPlugin

---------

Co-authored-by: johanbriger <johanbriger@gmail.com>
Co-authored-by: WHITEROSE <firasmoussa60@gmail.com>
Co-authored-by: Mats Rönnqvist <203552386+bamsemats@users.noreply.github.com>
Co-authored-by: Linus Westling <141355850+LinusWestling@users.noreply.github.com>
Co-authored-by: Kristina M <kristina0x7@gmail.com>
* bump pom version for release

* revert pom version

* fix: docker release workflow to run on tag push

* fix: update tag ref in docker release workflow

* fix: update temurine version in DockerFile to match pom version 25

* fix: configure maven-jar-plugin to find the main class for manifest
* Add test for valid GET request and fix key case-sensitivity in header parsing

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Verify empty request throws exception

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Verify malformed request throws exception

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Verify valid query string

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Verify null and empty requests throws exception

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Verify malformed header line in get request throws exception

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Verify valid post request

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Verify invalid or negative content length throws exception

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Add test documentation and improve test readability for HttpParser

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Update tests and ensure UTF-8 handling; use case-insensitive headers in HttpParser

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Refactor: Introduce constant for "Content-Length" header in HttpParser

---------

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>
…ons (#52)

* add application properties and a ConfigLoader to load set configurations

* integrate ConfigLoader into ServerLogging to read logging.level

* inject Server port from ConfigLoader into constructor
* test: add global filter execution test

* feat: implement global filter support with ordering

* test: add route specific filter test

* feat: add route specific filter matching logic

* update main comments with upcoming filter impl

* chore: run spotless:apply to fix unused imports and formatting

* bunny-fix

* refactor: optimize route filter lookup with Map structure

* small fix

* fix: make global filter cache thread-safe and immutable

* implement the correct plugins so server works as intended and move comments to a doc

---------

Co-authored-by: WHITEROSE <firasmoussa60@gmail.com>
* Add IP filter skeleton with placeholder IP

* Add IP filter and support client IP in HttpRequest

* Add remote IP to HttpRequest in ConnectionHandler

* Configured IP filter whitelist for localhost

* Enable IP filter with open access for development

* Update tests for HttpRequest remote IP failed

* Document IP filter configuration in App

* Resolved merge conflict in App pipeline configuration
…eadme.md (#63)

* Update index.html to include a nav bar at the top, styles.css for adjustments to frontend aspects, add readme.html to host readme.md, basic javascript for loading markdown language content.

* Update frontend logic to avoid errors loading data from readme.md. Smoothed out transitions between sites from navigation.

* Update minor bugs and duplicate css code lines.

* Update minor bugs and duplicate css code lines.

* Update for sanitization of readme.md through DOMPurify. Added dependency min.js and its callback in index.html and readme.html. Removed superfluous markdown.js.
* Add Maven Shade Plugin for building a fat JAR; update README with detailed project overview and usage instructions

* Update project version to 1.0.2-beta in pom.xml

* Update README to reflect fat JAR packaging using Maven Shade Plugin

* fix: specify final jar name so the DockerBuild picks the correct one, rollback pom version

* rollback POM version to original

* update README with dynamic tag and correct port number

* update README with the dynamic specified jar file generated from maven-shaded

---------

Co-authored-by: WHITEROSE <firasmoussa60@gmail.com>
* Refactor plugin handling by introducing `Router` abstraction; added `SimpleRouter` implementation. Updated pipeline and tests to support new routing system.

* Refactor plugin handling by introducing `Router` abstraction; added `SimpleRouter` implementation. Updated pipeline and tests to support new routing system.

* Improve wildcard routing in `SimpleRouter` with longest-prefix match logic; add test coverage for specific and wildcard match scenarios.
* feat: add filter scope annotations (@global, @route)

* Rename paths() to value() in @route for cleaner usage
* add testcontainers dependency to pom.xml

* adds 2 simple integration tests usiing Testcontainers to AppIT.java

* changes from *.jar to app.jar in JAR path in Dockerfile to avoid copy conflict

* changes AppIT.java according to code rabbit suggestion
* Add Bucket4j dependency to pom.xml for rate-limiting support

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Introduce RateLimitingFilter with Bucket4j for per-IP request throttling

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Work In Progress: Implement per-IP rate-limiting logic in RateLimitingFilter using Bucket4j and add response handling for rate limit exceeded

* Finalize and integrate RateLimitingFilter with improved logging, validation, and server cleanup. Add to App pipeline and configure properties.

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Add unit tests for RateLimitingFilter to verify per-IP request handling, rate limit enforcement, and cleanup behavior

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Refactor RateLimitingFilter and tests: simplify comments in filter, improve test method naming, and add validation test

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Add Javadoc to RateLimitingFilter and its tests for improved clarity and documentation

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Remove StaticFilesPlugin from the App pipeline configuration

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Make RateLimitingFilter configuration dynamic and improve response handling in tests

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Add rate-limiting configuration to ConfigLoader and update App pipeline to use dynamic values

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Increase rate-limiting burst capacity to 100 in configuration properties

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Add configurable flag to enable/disable rate-limiting in App pipeline and ConfigLoader

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

---------

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>
annikaholmqvist94 and others added 25 commits February 18, 2026 11:01
* Add `RedirectRule` class to handle URL redirection logic with support for exact and wildcard path matching

* Add `RedirectFilter` to handle HTTP URL redirection logic using configurable rules

* WIP: Save current work

* Fix HttpResponse empty constructor to initialize fields

Initialize headers map and body array in empty constructor to prevent
NullPointerException when setHeader() or setBody() are called.

Before:
  HttpResponse() {}  // headers = null, body = null

After:
  HttpResponse() {
      this.headers = new LinkedHashMap<>();
      this.body = new byte[0];
  }

This fix is required for RedirectFilter and any other code that creates
empty HttpResponse objects and modifies them using setters.

Fixes crashes in RedirectFilterTest.

* Improve wildcard matching in `RedirectRule` by using `Pattern.quote` for safer and more precise regex generation.

* Update `RedirectFilterTest` to include client IP address in test request creation

---------

Co-authored-by: Kristina M <kristina0x7@gmail.com>
* remove sourcemapping url comment from the JS file

* remove stack trace from the 404 log message to console
* Add SecurityHeadersFilter for hardened HTTP responses

* Add SecurityHeadersFilter for hardened HTTP responses

* Changed X-XSS-Protection value to recommended 0,

* address code review feedback from CodeRabbit

* Add @global annotation to SecurityHeadersFilter for automatic registration

* Removed line of code in App.java
#76)

* Added IpFilterTest class with unit test verifying IpFilter allows whitelisted IPs.

* Fix IpFilterTest to verify response interaction instead of mock state

* Added unit test for blocking IP that is not in the whitelist, results in 403 Forbidden response.

Fixed HttpResponse construtors to always initialize headers and body to prevent NPE when filters call setHeader or setBody.

* Update IpFilter whitelist allow test to use real HttpResponse

* Assert expected status code in IpFilter whitelist allow test
* test(config-loader): add test skeleton for ConfigLoader

* test(config-loader): add initial test for loading config

* refactor(config-loader): extract configuration loading to InputStream constructor

* test(config-loader): verify values are loaded from yaml input

* test(config-loader): add test for default values when server keys missing

* test(config-loader): add null-input error handling test

* refactor(config-loader): add safe map casting and robust value parsing

* fix: handle missing server config and keep original exception cause

* fix(config-loader): handle empty yaml config safely

* fix (config-loader): add default log level for consistent config values

* Add missing curly bracket.

* fix(config-loader): address review rabbit comments and improve tests

---------

Co-authored-by: Simon Forsberg <simon.co.forsberg@gmail.com>
Co-authored-by: mattknatt <mattiashagstrommusic@gmail.com>
…sponse defaults (#87)

* fix(httpresponse): add safe defaults, null-safe headers and defensive body handling

* test(httpresponse): verify default values and null-safe behaviour

* refactor(httpresponse): enforce non-null statusText in constructor

* implement securityheadersfilter to harden http responses (#91)

* Add SecurityHeadersFilter for hardened HTTP responses

* Add SecurityHeadersFilter for hardened HTTP responses

* Changed X-XSS-Protection value to recommended 0,

* address code review feedback from CodeRabbit

* Add @global annotation to SecurityHeadersFilter for automatic registration

* Removed line of code in App.java

* Added IpFilterTest class with unit test verifying IpFilter allows whi… (#76)

* Added IpFilterTest class with unit test verifying IpFilter allows whitelisted IPs.

* Fix IpFilterTest to verify response interaction instead of mock state

* Added unit test for blocking IP that is not in the whitelist, results in 403 Forbidden response.

Fixed HttpResponse construtors to always initialize headers and body to prevent NPE when filters call setHeader or setBody.

* Update IpFilter whitelist allow test to use real HttpResponse

* Assert expected status code in IpFilter whitelist allow test

* Refactor ConfigLoader to accept InputStream and add unit tests (#72)

* test(config-loader): add test skeleton for ConfigLoader

* test(config-loader): add initial test for loading config

* refactor(config-loader): extract configuration loading to InputStream constructor

* test(config-loader): verify values are loaded from yaml input

* test(config-loader): add test for default values when server keys missing

* test(config-loader): add null-input error handling test

* refactor(config-loader): add safe map casting and robust value parsing

* fix: handle missing server config and keep original exception cause

* fix(config-loader): handle empty yaml config safely

* fix (config-loader): add default log level for consistent config values

* Add missing curly bracket.

* fix(config-loader): address review rabbit comments and improve tests

---------

Co-authored-by: Simon Forsberg <simon.co.forsberg@gmail.com>
Co-authored-by: mattknatt <mattiashagstrommusic@gmail.com>

---------

Co-authored-by: KM <kristina0x7@gmail.com>
Co-authored-by: johanbriger <johanbriger@gmail.com>
Co-authored-by: SandraNelj <229708855+SandraNelj@users.noreply.github.com>
Co-authored-by: Simon Forsberg <simon.co.forsberg@gmail.com>
Co-authored-by: mattknatt <mattiashagstrommusic@gmail.com>
…ader. (#110)

* Align rate-limiting configuration with Server and Logging in ConfigLoader.
* applied order filter annotations to existing filters

* put secfilter first

* fixed orders
* Add HealthCheckPlugin for server status endpoint

* Add HealthCheckPlugin for server status endpoint

* Refactor HealthCheckPlugin to use SERVER_NAME constant and optimize response handling

* Add build metadata, memory stats, and response time to HealthCheckPlugin responses

Integrate `build.properties` for versioning and metadata. Enhance `/health` endpoint with response time, memory usage, and build details. Add UI widget for health status and dynamic frontend updates.

* Add build metadata, memory stats, and response time to HealthCheckPlugin responses

Integrate `build.properties` for versioning and metadata. Enhance `/health` endpoint with response time, memory usage, and build details. Add UI widget for health status and dynamic frontend updates.

* Adjust time units and improve UI/UX for health status display

Refine response time calculations from milliseconds to microseconds. Update button interaction styles and enhance accuracy of frontend health status presentation.

* Refactor HealthCheckPlugin for improved metadata handling and error resilience; update resource filtering and enhance accessibility for health status UI

* Migrate HealthCheckPlugin functionalities to MetricPlugin and update related routes, tests, and UI for enhanced monitoring capabilities.

* Migrate HealthCheckPlugin functionalities to MetricPlugin and update related routes, tests, and UI for enhanced monitoring capabilities.

* Update response time unit from milliseconds to microseconds across backend and frontend

* Update MetricPlugin with improved logging, adjusted response time unit, and frontend status enhancements
* Added TimingFilter to measure request duration and log ms

* Added TimingFilter to measure request duration and log ms

---------

Co-authored-by: Kristina <kristina0x7@gmail.com>
…log messages from code handling that request (#97)

* Added LogContext and ServerLogFormatter, amended ServerLogging to use new formatter.

* Minor change to ConnectionHandler to generate and set connection ID, and LoggingFilter to use the logger, ensuring connection ID is included in the logs

* created a test, ConnectionIdLoggingTest, to verify that the connection ID is correctly included in the logs

* Updated LoggingFilterTest to check the java.util.logging.Logger instead of System.out, reflecting recent changes to LoggingFilter

* Updated LoggingFilterTest to check the java.util.logging.Logger instead of System.out, reflecting recent changes to LoggingFilter (#95)

* Apply Spotless formatting to resolve CI failure (#95)

* Include stack traces in log output as suggested by code review (#95)
…108)

* Add ETag support to StaticFileHandler with caching for static files

- Implemented ETag generation using SHA-256 for stronger caching.
- Added `Cache-Control` header with a short max-age for development convenience.
- Improved handling of conditional requests with `If-None-Match` to return 304 responses.
- Included tests for ETag and caching behavior validation.

* Fixed Rabbit suggestions
Enhance ETag comparison with support for weak tags and improve error handling for missing SHA-256.

* Fixed Rabbit suggestions

Improve ETag handling by adding null checks for opaqueTag parsing
…able default response (#99)

* allow using both white and blacklist at the same time with a configurable default response

Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>

* removed 2arg constructor to clarify default behaviour

Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>

* merging took to long, resolving conflicts

Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>

* merging took to long, resolving conflicts

Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>

---------

Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
* feat(di): impl dependency injection container

* feat: impl a filterconfig

* feat: impl a filterfactory

* feat: impl a filterregistry

* refactor: remove match logic from pipeline

* feat: impl a ClassScanner

* feat: impl a FilterScanner

* refactor: pipeline

* feat: impl a bootstrap and routerconfig

* refactor: filters and App for DI-based automatic registration

* Log initialized filters in execution order at server startup

* rabbit-fixes

* fix container and classscanner

* Update src/main/java/org/juv25d/filter/FilterScanner.java

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Revert "Update src/main/java/org/juv25d/filter/FilterScanner.java"

This reverts commit d6d096f.

* rabbit-fixed2

* merged main

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* add ProxyRoute that will map a base route to its respective upstream host URL

* register ProxyRoutes from application properties inside ConfigLoader

* register ProxyPlugin for each ProxyRoute and log request

* proxy request to upstream and relay the response back to the client

* copy only non restricted Http headers

* add HttpStatus enum to get status texts from the status code and log proxy response

* handle connect and timeout exceptions and log warning message to console

* dont log exception stack trace to console

* add javadoc in ProxyRoute with a simple example

* test handle offline upstream domain

* test non exisiting upstream resource path

* test successful response with JSON data

* test that the upstream URL gets correctly built

* dont log empty query string

* test restricted headers filter from being proxied

* test different proxy response scenarios

* catch InterruptedException explicitly
* split app into layers for more efficent building

Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>

* rabbit suggestion

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* removing redundant splitting, skipping maven-shade as we aren't using the .jar

Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>

---------

Signed-off-by: Jesper Larsson <jesper.larsson@iths.se>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
* Update RateLimitingFilter to return HTML response for rate-limiting errors and adjust related tests

* Ignore macOS .DS_Store files

* Show 429 message automatically when rate limit is exceeded, redirect client to start page when bucket is filled

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Add Cache-Control: no-store to the 429 response, remove handle /rate-limited redirect in metric.js

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

---------

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>
* Add ArchUnit dependency

* Create ArchitectureTest

* Create initial ArchRule

* Update connectionHandlerAccessRule test

* Add class description

* Create pipelineAccessRule

* Create filterChainRule

* Create routerRule

* Update filterChainRule and pipelineAccessRule

* Create pluginRule and update docs

* Update README.md Architecture Overview

* Update pom.xml

* refactor: migrate ArchUnit tests from @archtest to explicit ClassFileImporter setup

* Update pipelineAccessRule to include DefaultConnectionHandlerFactory

* Update pipelineAccessRule to include new Bootstrap class

* Update pipelineAccessRule. Remove TODO decouple Server from Pipeline

* Create httpResponseWriterAccessRule
* Create destroy method

* Create stop method

* Add stop method to ShutdownHook

* Add try/catch/finally to shutdownhook
…ntification behind proxies (#131)

* Add ForwardedHeaderFilter

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Add ForwardedHeaderFilterTest, verify request is passed when header is blank, verify IP is set when containing X-Forwarded-For header

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Verify request is passed when header is blank

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Refactor test class

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Add java docs

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Changes by mattiashagstrom

* Verify that other request fields are properly forwarded

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Add trusted proxies to config loader, refactor ForwardedHeaderFilter too look for trusted proxies in config loader

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

* Edit filter to handle trusted proxies, update tests to match, add documentation

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>

---------

Co-authored-by: Mattias Hagström <mattiashagstrommusic@gmail.com>
* Add ADR for IP-based request filtering

* Fixed spelling
* Add CORS filter to enable cross-origin requests

* Make HttpResponse mutable to support CORS and response-modifying filters

HttpResponse was immutable, which prevented filters from adding headers
or modifying status/body. Since our filter chain relies on mutating the
shared response object, immutability blocked correct CORS implementation.

Added setter methods and removed unmodifiable headers wrapper.
HttpResponseWriter remains unaffected.

* Add unit tests for CORS filter functionality

* Add tests for CORS filter handling of origin headers and preflight requests

* Make HttpResponse mutable and update CORS filter to set status and headers correctly

* Enhance CORS filter to manage 'Vary' header and fix 'Access-Control-Allow-Headers' setting

* Add default constructor to HttpResponse for easier instantiation

* Refactor CORS filter tests to use mock requests and responses
@coderabbitai
Copy link

coderabbitai bot commented Feb 26, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5f18f91 and e04dcc9.

⛔ Files ignored due to path filters (3)
  • src/main/resources/static/images/tech-bg.jpg is excluded by !**/*.jpg
  • src/main/resources/static/js/marked.min.js is excluded by !**/*.min.js
  • src/main/resources/static/js/purify.min.js is excluded by !**/*.min.js
📒 Files selected for processing (107)
  • .dockerignore
  • .editorconfig
  • .github/workflows/ci.yml
  • .github/workflows/docker-release.yml
  • .gitignore
  • .mvn/wrapper/maven-wrapper.properties
  • Dockerfile
  • README.md
  • build.properties
  • docs/adr/ADR-001-static-file-serving-architecture.md
  • docs/adr/ADR-002-ip-based-request-filtering.md
  • docs/adr/README.md
  • docs/adr/TEMPLATE.md
  • docs/notes/pipeline-usage.md
  • mvnw
  • mvnw.cmd
  • pom.xml
  • src/main/java/org/example/App.java
  • src/main/java/org/juv25d/App.java
  • src/main/java/org/juv25d/Bootstrap.java
  • src/main/java/org/juv25d/ConnectionHandler.java
  • src/main/java/org/juv25d/ConnectionHandlerFactory.java
  • src/main/java/org/juv25d/DefaultConnectionHandlerFactory.java
  • src/main/java/org/juv25d/Pipeline.java
  • src/main/java/org/juv25d/Server.java
  • src/main/java/org/juv25d/config/FilterConfig.java
  • src/main/java/org/juv25d/config/IpFilterConfig.java
  • src/main/java/org/juv25d/config/RateLimitConfig.java
  • src/main/java/org/juv25d/config/RedirectConfig.java
  • src/main/java/org/juv25d/di/Container.java
  • src/main/java/org/juv25d/di/Inject.java
  • src/main/java/org/juv25d/filter/ClassScanner.java
  • src/main/java/org/juv25d/filter/CorsFilter.java
  • src/main/java/org/juv25d/filter/Filter.java
  • src/main/java/org/juv25d/filter/FilterChain.java
  • src/main/java/org/juv25d/filter/FilterChainImpl.java
  • src/main/java/org/juv25d/filter/FilterFactory.java
  • src/main/java/org/juv25d/filter/FilterMatcher.java
  • src/main/java/org/juv25d/filter/FilterRegistration.java
  • src/main/java/org/juv25d/filter/FilterRegistry.java
  • src/main/java/org/juv25d/filter/FilterScanner.java
  • src/main/java/org/juv25d/filter/ForwardedHeaderFilter.java
  • src/main/java/org/juv25d/filter/IpFilter.java
  • src/main/java/org/juv25d/filter/LoggingFilter.java
  • src/main/java/org/juv25d/filter/RateLimitingFilter.java
  • src/main/java/org/juv25d/filter/RedirectFilter.java
  • src/main/java/org/juv25d/filter/RedirectRule.java
  • src/main/java/org/juv25d/filter/SecurityHeadersFilter.java
  • src/main/java/org/juv25d/filter/TimingFilter.java
  • src/main/java/org/juv25d/filter/annotation/Global.java
  • src/main/java/org/juv25d/filter/annotation/Route.java
  • src/main/java/org/juv25d/handler/MimeTypeResolver.java
  • src/main/java/org/juv25d/handler/StaticFileHandler.java
  • src/main/java/org/juv25d/http/HttpParser.java
  • src/main/java/org/juv25d/http/HttpRequest.java
  • src/main/java/org/juv25d/http/HttpResponse.java
  • src/main/java/org/juv25d/http/HttpResponseWriter.java
  • src/main/java/org/juv25d/http/HttpStatus.java
  • src/main/java/org/juv25d/logging/LogContext.java
  • src/main/java/org/juv25d/logging/ServerLogFormatter.java
  • src/main/java/org/juv25d/logging/ServerLogging.java
  • src/main/java/org/juv25d/plugin/HealthCheckPlugin.java
  • src/main/java/org/juv25d/plugin/HelloPlugin.java
  • src/main/java/org/juv25d/plugin/MetricPlugin.java
  • src/main/java/org/juv25d/plugin/NotFoundPlugin.java
  • src/main/java/org/juv25d/plugin/Plugin.java
  • src/main/java/org/juv25d/plugin/StaticFilesPlugin.java
  • src/main/java/org/juv25d/proxy/ProxyPlugin.java
  • src/main/java/org/juv25d/proxy/ProxyRoute.java
  • src/main/java/org/juv25d/router/Router.java
  • src/main/java/org/juv25d/router/RouterConfig.java
  • src/main/java/org/juv25d/router/SimpleRouter.java
  • src/main/java/org/juv25d/util/ConfigLoader.java
  • src/main/resources-filtered/build.properties
  • src/main/resources/application-properties.yml
  • src/main/resources/static/README.md
  • src/main/resources/static/css/styles.css
  • src/main/resources/static/index.html
  • src/main/resources/static/js/app.js
  • src/main/resources/static/js/metric.js
  • src/main/resources/static/readme.html
  • src/test/java/org/example/AppIT.java
  • src/test/java/org/juv25d/AppIT.java
  • src/test/java/org/juv25d/AppTest.java
  • src/test/java/org/juv25d/ArchitectureTest.java
  • src/test/java/org/juv25d/PipelineTest.java
  • src/test/java/org/juv25d/di/ContainerTest.java
  • src/test/java/org/juv25d/filter/CorsFilterTest.java
  • src/test/java/org/juv25d/filter/FilterChainImplTest.java
  • src/test/java/org/juv25d/filter/FilterRegistryTest.java
  • src/test/java/org/juv25d/filter/ForwardedHeaderFilterTest.java
  • src/test/java/org/juv25d/filter/IpFilterTest.java
  • src/test/java/org/juv25d/filter/LoggingFilterTest.java
  • src/test/java/org/juv25d/filter/RateLimitingFilterTest.java
  • src/test/java/org/juv25d/filter/RedirectFilterTest.java
  • src/test/java/org/juv25d/handler/MimeTypeResolverTest.java
  • src/test/java/org/juv25d/handler/StaticFileHandlerTest.java
  • src/test/java/org/juv25d/http/HttpParserTest.java
  • src/test/java/org/juv25d/http/HttpResponseTest.java
  • src/test/java/org/juv25d/http/HttpResponseWriterTest.java
  • src/test/java/org/juv25d/logging/ConnectionIdLoggingTest.java
  • src/test/java/org/juv25d/logging/ServerLoggingTest.java
  • src/test/java/org/juv25d/plugin/MetricPluginTest.java
  • src/test/java/org/juv25d/plugin/NotFoundPluginTest.java
  • src/test/java/org/juv25d/proxy/ProxyPluginTest.java
  • src/test/java/org/juv25d/router/SimpleRouterTest.java
  • src/test/java/org/juv25d/util/ConfigLoaderTest.java

📝 Walkthrough

Walkthrough

This PR introduces a complete Java HTTP server framework with a multi-layered architecture: a core server accepting connections via a pipeline of filters, routing requests to plugins, and supporting static file serving and proxying. Includes dependency injection, comprehensive configuration, rate limiting, CORS, security headers, and extensive test coverage with Docker deployment support.

Changes

Cohort / File(s) Summary
Configuration & Build
.dockerignore, .editorconfig, .gitignore, pom.xml, .mvn/wrapper/maven-wrapper.properties, mvnw, mvnw.cmd, build.properties, src/main/resources/application-properties.yml, src/main/resources-filtered/build.properties
Added Maven wrapper scripts, Docker/editor configuration, build properties, application configuration (YAML), and updated pom.xml with new dependencies (ArchUnit, SnakeYAML, Bucket4j, Testcontainers, Spotless, PIT mutation testing, BuildNumber).
CI/CD Pipelines
.github/workflows/ci.yml, .github/workflows/docker-release.yml
Added GitHub Actions workflows for continuous integration (tests, spotless checks) and Docker image publishing to GHCR with multi-arch support (amd64, arm64).
Core Server
src/main/java/org/juv25d/Server.java, src/main/java/org/juv25d/ConnectionHandler.java, src/main/java/org/juv25d/ConnectionHandlerFactory.java, src/main/java/org/juv25d/DefaultConnectionHandlerFactory.java
Introduced server listening loop with virtual thread–based connection handling, factory pattern for handler creation, and per-connection request/response processing.
HTTP Abstractions
src/main/java/org/juv25d/http/HttpParser.java, src/main/java/org/juv25d/http/HttpRequest.java, src/main/java/org/juv25d/http/HttpResponse.java, src/main/java/org/juv25d/http/HttpResponseWriter.java, src/main/java/org/juv25d/http/HttpStatus.java
Implemented HTTP request parsing (from InputStream), immutable HttpRequest record, mutable HttpResponse for filter modifications, response serialization to OutputStream, and HTTP status enum with bidirectional mapping.
Dependency Injection
src/main/java/org/juv25d/di/Container.java, src/main/java/org/juv25d/di/Inject.java
Built a full-featured DI container supporting constructor-based injection, interface-to-implementation bindings, circular dependency detection, and per-thread locking for safe concurrent bean creation.
Filter Pipeline
src/main/java/org/juv25d/filter/Filter.java, src/main/java/org/juv25d/filter/FilterChain.java, src/main/java/org/juv25d/filter/FilterChainImpl.java, src/main/java/org/juv25d/filter/FilterRegistry.java, src/main/java/org/juv25d/filter/FilterMatcher.java, src/main/java/org/juv25d/filter/FilterFactory.java, src/main/java/org/juv25d/filter/FilterScanner.java, src/main/java/org/juv25d/filter/ClassScanner.java
Implemented filter interface, chain execution, registry for global/route-scoped filters, automatic discovery/instantiation via annotations, and pattern-based route matching.
Global Filters
src/main/java/org/juv25d/filter/LoggingFilter.java, src/main/java/org/juv25d/filter/SecurityHeadersFilter.java, src/main/java/org/juv25d/filter/IpFilter.java, src/main/java/org/juv25d/filter/TimingFilter.java, src/main/java/org/juv25d/filter/RateLimitingFilter.java, src/main/java/org/juv25d/filter/CorsFilter.java, src/main/java/org/juv25d/filter/ForwardedHeaderFilter.java
Added 7 global filters: logging, security headers, IP-based access control, request timing, token-bucket rate limiting (Bucket4j), CORS with origin validation, and X-Forwarded-For IP resolution.
Route & Redirect Filters
src/main/java/org/juv25d/filter/RedirectFilter.java, src/main/java/org/juv25d/filter/RedirectRule.java
Implemented route-based redirects with wildcard pattern matching and configurable HTTP status codes (301/302).
Filter Annotations
src/main/java/org/juv25d/filter/annotation/Global.java, src/main/java/org/juv25d/filter/annotation/Route.java
Added @Global and @Route annotations for declarative filter registration with ordering.
Router & Plugin System
src/main/java/org/juv25d/router/Router.java, src/main/java/org/juv25d/router/SimpleRouter.java, src/main/java/org/juv25d/plugin/Plugin.java, src/main/java/org/juv25d/plugin/HealthCheckPlugin.java, src/main/java/org/juv25d/plugin/MetricPlugin.java, src/main/java/org/juv25d/plugin/NotFoundPlugin.java, src/main/java/org/juv25d/plugin/HelloPlugin.java, src/main/java/org/juv25d/plugin/StaticFilesPlugin.java
Implemented router interface and SimpleRouter with exact/wildcard path matching, Plugin interface, and 5 plugin implementations for health checks, metrics, 404 handling, and static files.
Static Files & MIME
src/main/java/org/juv25d/handler/StaticFileHandler.java, src/main/java/org/juv25d/handler/MimeTypeResolver.java
Added static file serving from classpath with directory traversal protection, ETag-based caching (304 Not Modified), and MIME type resolution.
Proxy Support
src/main/java/org/juv25d/proxy/ProxyRoute.java, src/main/java/org/juv25d/proxy/ProxyPlugin.java
Implemented HTTP proxying with configurable upstream routes, header filtering, and error handling (ConnectException → 502, HttpTimeoutException → 504).
Configuration
src/main/java/org/juv25d/config/FilterConfig.java, src/main/java/org/juv25d/config/IpFilterConfig.java, src/main/java/org/juv25d/config/RateLimitConfig.java, src/main/java/org/juv25d/config/RedirectConfig.java, src/main/java/org/juv25d/util/ConfigLoader.java
Added configuration classes for filters, IP rules, rate limiting, redirects; ConfigLoader singleton parsing YAML with SnakeYAML and falling back to defaults.
Logging
src/main/java/org/juv25d/logging/ServerLogging.java, src/main/java/org/juv25d/logging/ServerLogFormatter.java, src/main/java/org/juv25d/logging/LogContext.java
Implemented Java logging setup with custom formatter (includes connection ID via ThreadLocal), per-thread context tracking, and multi-source log-level configuration (system property → environment variable → config file).
Bootstrap & Pipeline
src/main/java/org/juv25d/Pipeline.java, src/main/java/org/juv25d/Bootstrap.java, src/main/java/org/juv25d/router/RouterConfig.java, src/main/java/org/juv25d/App.java
Added Pipeline orchestrating filters and routing, Bootstrap initializing filter registry and pipeline, RouterConfig wiring plugins, and App entry point bootstrapping the entire system.
Documentation
README.md, docs/adr/README.md, docs/adr/TEMPLATE.md, docs/adr/ADR-001-static-file-serving-architecture.md, docs/adr/ADR-002-ip-based-request-filtering.md, docs/notes/pipeline-usage.md
Added comprehensive README, ADR framework with template, and two ADRs documenting static file serving and IP filtering architectures.
Frontend Assets
src/main/resources/static/index.html, src/main/resources/static/readme.html, src/main/resources/static/css/styles.css, src/main/resources/static/js/app.js, src/main/resources/static/js/metric.js, src/main/resources/static/README.md
Added responsive HTML pages, modern CSS with grid/animation, and JavaScript for client-side routing, markdown rendering, and metrics polling.
Dockerfile
Dockerfile
Implemented multi-stage Docker build (Maven build → Alpine JRE runtime) with GIT_COMMIT argument for image metadata.
Test Suite
src/test/java/org/juv25d/AppIT.java, src/test/java/org/juv25d/AppTest.java, src/test/java/org/juv25d/ArchitectureTest.java, src/test/java/org/juv25d/PipelineTest.java, src/test/java/org/juv25d/di/ContainerTest.java, src/test/java/org/juv25d/filter/*.java (9 files), src/test/java/org/juv25d/handler/*.java (2 files), src/test/java/org/juv25d/http/*.java (4 files), src/test/java/org/juv25d/logging/*.java (2 files), src/test/java/org/juv25d/plugin/*.java (3 files), src/test/java/org/juv25d/proxy/ProxyPluginTest.java, src/test/java/org/juv25d/router/SimpleRouterTest.java, src/test/java/org/juv25d/util/ConfigLoaderTest.java
Added 40+ test files including integration tests with Testcontainers (Docker-based), unit tests with Mockito, architecture validation via ArchUnit, and coverage of DI container, filters, HTTP parsing, routing, plugins, proxy, configuration, and logging.

Sequence Diagram(s)

sequenceDiagram
    actor Client
    participant Server
    participant ConnHandler as ConnectionHandler
    participant Pipeline
    participant FilterChain
    participant Router
    participant Plugin
    participant HttpWriter as HttpResponseWriter

    Client->>Server: TCP Connection
    Server->>ConnHandler: create(Socket)
    activate ConnHandler
    ConnHandler->>ConnHandler: parse HTTP request
    ConnHandler->>Pipeline: createChain(HttpRequest)
    Pipeline->>FilterChain: new FilterChainImpl(filters, router)
    activate FilterChain
    FilterChain->>FilterChain: doFilter() - iterate filters
    Note over FilterChain: Filter 1 (Logging)
    Note over FilterChain: Filter 2 (SecurityHeaders)
    Note over FilterChain: Filter N (...)
    FilterChain->>Router: resolve(HttpRequest)
    activate Router
    Router->>Plugin: (exact/wildcard match)
    deactivate Router
    Plugin->>Plugin: handle(request, response)
    deactivate FilterChain
    ConnHandler->>HttpWriter: write(OutputStream, response)
    activate HttpWriter
    HttpWriter->>HttpWriter: serialize status, headers, body
    HttpWriter->>Client: HTTP Response
    deactivate HttpWriter
    deactivate ConnHandler
Loading

Estimated Code Review Effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly Related Issues

  • Issue #74: The PR implements IpFilter with whitelist/blacklist access control and corresponding IpFilterTest suite, directly addressing the requested IP-based filtering feature and unit test coverage.

Poem

🐰 A server hops into the frame,
With filters dancing in the chain,
Routes and plugins take their place,
Static files served with grace.
From Docker's nest to tests galore,
Java HTTP dreams evermore! 🚀

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Tyreviel Tyreviel closed this Feb 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.