The Nexus-Backend Service acts as an intermediary between a REST Client application and a Backend REST API service. It forwards Requests from the client to the Backend Service and returns the Responses back to the client. The Nexus-Backend integrate a HttpFirewall and WAF Filter for a protection against evasion on the Http Request Headers, Request Map parameters and Json BodyRequest.
Inside a Servlet Container a Rest Controller ApiBackend and its BackendService, Secure and Replicate all the HTTP Requests to a RestApi Backend Server.
All HttpRequests methods supported: Get, Post, Post Multipart File, Put, Put Multipart File, Patch, Patch Multipart File, Delete.
- Full support Request Json Entity Object: application/json, application/x-www-form-urlencoded
- Full support MultipartRequest Resources and Map parameters, and embedded form Json Entity Object: multipart/form-data
- Full support Response in Json Entity Object: application/json
- Full support Response in ByteArray Resource file: application/octet-stream
- Full support Streaming Http Response Json Entity Object: application/octet-stream, accept header Range bytes
Tomcat Servlet Containers under Servlet version 4.x
Examples forwarded requests and responses through the Nexus-Backend Service:
REST Clients | RestApi Nexus-Backend Service | Backend Server Services |
---|---|---|
Ajax / XMLHttpRequest | http://localhost:8082/nexus-backend/api/** | https://secure.jservlet.com:9092/api/v1/service |
HttpClient | https://front.jservlet.com:80/nexus-backend/api/** | https://secure.jservlet.com:9092/api/v1/service |
FeedService | https://intra.jservlet.com:80/nexus-backend/api/** | https://10.100.100.50:9092/api/v1/service |
An Ajax Single Page Application communicate through the Rest Controller ApiBackend and its BackendService to a RestApi Backend Server.
- Implements a BackendService, ability to request typed response Object class or ParameterizedTypeReference, requested on all HTTP methods to a RestApi Backend Server.
- Implements an EntityBackend Json Object or Resource, transfer back headers, manage error HttpStatus 400, 401, 405 or 500 coming from the Backend Server.
- Implements a HttpFirewall filter protection against evasion, rejected any suspicious Requests, Headers, Parameters, and log IP address at fault.
- Implements a WAF filter protection against evasion on the Http Json BodyRequest, and log IP address at fault.
- Implements a CORS Security Request filter, Authorize request based on Origin Domains and Methods.
- Implements a Fingerprint for each Http header Request, generate a unique trackable Token APP-REQUEST-ID in the access logs.
- Implements a Method Override filter, PUT or PATCH request can be switched in POST or DELETE switched in GET with header X-HTTP-Method-Override
- Implements a Forwarded Header filter, set removeOnly at true by default, remove "Forwarded" and "X-Forwarded-*" headers.
- Implements a FormContent filter, parses form data for Http PUT, PATCH, and DELETE requests and exposes it as Servlet request parameters.
- Implements a Compressing filter Gzip compression for the Http Responses.
- Implements a CharacterEncoding filter, UTF-8 default encoding for requests.
- HTTP headers: reset all Headers, remove host or origin header.
- Basic Authentication: set any security ACL Access Control List
- Bearer Authorization: set any security Bearer Token.
- Cookie: set any security session Cookie.
- CORS: Bypass locally all CORS Security (Cross-origin resource sharing) from a Navigator, not restricted to accessing resources from the same origin through what is known as same-origin policy.
The Nexus Backend application can be configured by the following keys SpringBoot and Settings properties
SpringBoot keys application.properties:
Keys | Default value | Descriptions |
---|---|---|
nexus.api.backend.enabled | true | Activated the Nexus-Backend Service |
nexus.api.backend.filter.waf.enabled | true | Activated the WAF filter Json RequestBody |
nexus.api.backend.listener.requestid.enabled | true | Activated the Fingerprint for each Http Request |
nexus.api.backend.filter.httpoverride.enabled | true | Activated the Http Override Method |
nexus.backend.filter.forwardedHeader.enabled | true | Activated the ForwardedHeader filter |
nexus.backend.filter.gzip.enabled | true | Activated the Gzip compression filter |
spring.mvc.formcontent.filter.enabled | true | Activated the FormContent parameterMap Support |
nexus.backend.tomcat.connector.https.enable | false | Activated a Connector TLS/SSL in a Embedded Tomcat |
nexus.backend.tomcat.accesslog.valve.enable | false | Activated an Accesslog in a Embedded Tomcat |
- -Dspring.config.location=/your/config/dir/
- -Dspring.config.name=spring.properties
The Nexus-Backend Url Server and miscellaneous options can be configured by the following keys Settings
Settings keys settings.properties:
Keys | Default value | Example value | Descriptions |
---|---|---|---|
nexus.backend.url | https://postman-echo.com | https://nexus6.jservlet.com/api | The API Backend Server targeted |
nexus.backend.uri.alive | /get | /health/info | The endpoint alive Backend Server |
nexus.backend.http.response.truncated | false | true | Truncated the Json output in the logs |
nexus.backend.http.response.truncated.maxLength | 1000 | 100 | MaxLength truncated |
WAF | |||
nexus.api.backend.filter.waf.reactive.mode | STRICT | PASSIVE | Default Strict HttpFirewall + Json RequestBody |
nexus.api.backend.filter.waf.deepscan.cookie | false | true | Activated Deep Scan Cookie |
Headers | |||
nexus.backend.header.remove | false | true | Remove all Headers |
nexus.backend.header.host.remove | false | false | Remove just host Header |
nexus.backend.header.origin.remove | false | false | Remove just origin Header |
nexus.backend.header.cookie | - | XSession=0XX1YY2ZZ3XX4YY5ZZ6XX | Set a Cookie Request Header |
nexus.backend.header.bearer | - | eyJhbGciO | Activated Bearer Authorization request |
nexus.backend.header.user-agent | JavaNexus | Apache HttpClient/4.5 | User Agent header |
nexus.backend.header.authorization.username | - | XUsername | Activated Basic Authorization request |
nexus.backend.header.authorization.password | - | XPassword | " |
Backend Headers | |||
nexus.api.backend.transfer.headers | test | test,... | Headers list back from Backend Server |
Mapper | |||
nexus.backend.mapper.indentOutput | false | true | Indent Output Json |
Debug | |||
nexus.spring.web.security.debug | false | true | Debug the Spring FilterChain |
- ${user.home}/conf-global/config.properties
- ${user.home}/conf/config.properties
- ${user.home}/cfg/${servletContextPath}/config.properties
ApiBackend ResponseType can be now a ByteArray Resource.
Download any content in a ByteArray included commons extensions files (see MediaTypes section)
The ResourceMatchers Config can be configured on specific ByteArray Resources path and on specific Methods GET, POST, PUT, PATCH and Ant Path pattern:
Settings keys settings.properties:
Keys Methods and Keys Path pattern | Default value | Content-Type |
---|---|---|
nexus.backend.api-backend-resource.matchers.1.method | GET | |
nexus.backend.api-backend-resource.matchers.1.pattern | /api/encoding/** | text/html;charset=utf-8 |
nexus.backend.api-backend-resource.matchers.2.method | GET | |
nexus.backend.api-backend-resource.matchers.2.pattern | /api/streaming/** | application/octet-stream |
nexus.backend.api-backend-resource.matchers.3.method | GET | |
nexus.backend.api-backend-resource.matchers.3.pattern | /api/time/now | text/html;charset=utf-8 |
nexus.backend.api-backend-resource.matchers.{name}[X].method | Methods | |
nexus.backend.api-backend-resource.matchers.{name}[X].pattern | Patterns |
Http Responses are considerate as Resources, the Http header "Accept-Ranges: bytes" is injected and allow you to use
the Http header 'Range: bytes=1-100' in the request and grabbed only range of Bytes desired.
And the Http Responses didn't come back with a HttpHeader "Transfer-Encoding: chunked" cause the header Content-Length.
Noted: For configure all the Responses in Resource put an empty Method and use the path pattern=/api/**
Keys Methods and Keys Path pattern | Default value |
---|---|
nexus.backend.api-backend-resource.matchers.matchers1.method | |
nexus.backend.api-backend-resource.matchers.matchers1.pattern | /api/** |
Noted bis: For remove the Http header "Transfer-Encoding: chunked" the header Content-Length need to be calculated. enable the ShallowEtagHeader Filter in the configuration for force to calculate the header Content-Length for all the Response Json Entity Object, no more HttpHeader "Transfer-Encoding: chunked".
MediaTypes safe extensions
The Spring ContentNegotiation load the safe extensions files that can be extended. A commons MediaTypes properties file is loaded resources/mime/MediaTypes_commons.properties and can be disabled:
Settings keys settings.properties:
Default Header ContentNegotiation Strategy:
ContentNegotiation Strategy | Default value | Descriptions Strategy |
---|---|---|
Header Strategy | ||
nexus.backend.content.negotiation.ignoreAcceptHeader | false | Header Strategy Enabled |
Parameter Strategy | ||
nexus.backend.content.negotiation.favorParameter | false | Parameter Strategy Disabled |
nexus.backend.content.negotiation.parameterName | mediaType | |
Registered Extensions | ||
nexus.backend.content.negotiation.useRegisteredExtensionsOnly | true | Registered Only Enabled |
Load commons MediaTypes | ||
nexus.backend.content.negotiation.commonMediaTypes | true | Enabled |
CORS Security configuration, allow Control Request on Domains and Methods
Settings keys settings.properties:
The default Cors Configuration:
Cors Configuration | Default value | Example value | **Descriptions ** |
---|---|---|---|
nexus.backend.security.cors.credentials | false | true | Enable credentials |
nexus.backend.security.cors.allowedHttpMethods | GET,POST,PUT,HEAD,DELETE,PATCH | GET,POST,PUT | List Http Methods |
nexus.backend.security.cors.allowedOriginPatterns | Regex Patterns domains | ||
nexus.backend.security.cors.allowedOrigins | * | http://localhost:4042,http://localhost:4083 | List domains |
nexus.backend.security.cors.allowedHeaders | Authorization,Cache-Control,Content-Type | List Allowed Headers | |
nexus.backend.security.cors.exposedHeaders | Authorization | List Exposed Headers | |
nexus.backend.security.cors.maxAge | 3600 | 1800 | Max Age cached |
Noted: allowedOrigins cannot be a wildcard '*' if credentials is at true, a list of domains need to be provided.
The Nexus-Backend provides a full support MultipartRequest and Map parameters inside a form-data HttpRequest
SpringBoot keys application.properties:
Keys | Default value | Example value | Descriptions |
---|---|---|---|
spring.servlet.multipart.enabled | true | true | Enabled multipart |
spring.servlet.multipart.file-size-threshold | 10MB | 25MB | File size threshold |
spring.servlet.multipart.max-file-size | 15MB | 150MB | Max file size |
spring.servlet.multipart.max-request-size | 15MB | 150MB | Max request size |
Noted All the HttpRequests with a Content-Type multipart/form-data will be managed by a temporary BackendResource. This BackendResource can convert a MultipartFile to a temporary Resource, ready to be sent to the Backend Server.
Settings keys settings.properties:
Keys | Default value | Example value | Descriptions |
---|---|---|---|
nexus.backend.client.header.user-agent | JavaNexus | curl | User Agent Header |
nexus.backend.client.connectTimeout | 10 | 5 | Connection timeout in second |
nexus.backend.client.requestTimeout | 20 | 10 | Request timeout in second |
nexus.backend.client.socketTimeout | 10 | 5 | Socket timeout in second |
nexus.backend.client.max_connections_per_route | 20 | 30 | Max Connections per route |
nexus.backend.client.max_connections | 100 | 300 | Max Connections in the Pool |
nexus.backend.client.close_idle_connections_timeout | 0 | 0 | Close idle connections timeout |
nexus.backend.client.validate_after_inactivity | 2 | 2 | Validate after inactivity |
nexus.backend.client.requestSentRetryEnabled | false | true | Request Sent Retry Enabled |
nexus.backend.client.retryCount | 3 | 2 | Retry Count |
nexus.backend.client.redirectsEnabled | true | true | Redirects enabled |
nexus.backend.client.maxRedirects | 5 | 2 | Maximum redirections |
nexus.backend.client.authenticationEnabled | false | true | Authentication enabled |
nexus.backend.client.circularRedirectsAllowed | false | true | Circular redirections allowed |
The Nexus-Backend implements a HttpFirewall protection against evasion and rejected any suspicious Http Request on the Headers and Cookies, the Parameters, the keys and Values.
The WAF Filter implements a secure WAF protection against evasion on a Json Http RequestBody.
Un-normalized Http requests are automatically rejected by the StrictHttpFirewall, and path parameters and duplicate slashes are removed for matching purposes.
Noted the valid characters are defined in RFC 7230 and RFC 3986 are checked by the Apache Coyote http11 processor (see coyote Error parsing HTTP request header)
All the Http request with Cookies, Headers, Parameters and RequestBody will be filtered and the suspicious IP address in fault will be logged.
Settings keys settings.properties:
Keys | Default value | Descriptions |
---|---|---|
nexus.backend.security.allowedHttpMethods | GET,POST,PUT,OPTIONS,HEAD,DELETE,PATCH | Allowed Http Methods |
nexus.backend.security.allowSemicolon | false | Allowed Semi Colon |
nexus.backend.security.allowUrlEncodedSlash | false | Allow url encoded Slash |
nexus.backend.security.allowUrlEncodedDoubleSlash | false | Allow url encoded double Slash |
nexus.backend.security.allowUrlEncodedPeriod | false | Allow url encoded Period |
nexus.backend.security.allowBackSlash | false | Allow BackSlash |
nexus.backend.security.allowNull | false | Allow Null |
nexus.backend.security.allowUrlEncodedPercent | false | Allow url encoded Percent |
nexus.backend.security.allowUrlEncodedCarriageReturn | false | Allow url encoded Carriage Return |
nexus.backend.security.allowUrlEncodedLineFeed | false | Allow url encoded Line Feed |
nexus.backend.security.allowUrlEncodedParagraphSeparator | false | Allow url encoded Paragraph Separator |
nexus.backend.security.allowUrlEncodedLineSeparator | false | Allow url encoded Line Separator |
The WAF Utilities Predicates checked for potential evasion:
- XSS script injection
- SQL injection
- Google injection
- Command injection
- File injection
- Link injection
Implements a WAF Predicate for potential evasion by Headers:
- Header Names / Header Values
- Parameter Names / Parameter Values
- Hostnames
And check for Buffer Overflow evasion by the Length:
- Parameter Names 255 characters max. / Values 10.000 characters max.
- Header Names 255 characters max. / Values 7.000 characters max.
- Hostnames 255 characters max.
The WAF Reactive mode configuration:
- STRICT: Strict HttpFirewall + Json RequestBody
- PASSIVE: Strict HttpFirewall + Clean Json RequestBody and Parameters Map
- UNSAFE: Strict HttpFirewall + No check Json RequestBody!
Settings keys settings.properties: nexus.backend.client.ssl.mtls.enable at true for activated the mTLS connection
Keys | Default value | Descriptions |
---|---|---|
nexus.backend.client.ssl.mtls.enable | false | Activated the Mutual TLS |
nexus.backend.client.ssl.key-store | nexus-default.jks | Path to the Java KeyStore |
nexus.backend.client.ssl.key-store-password | changeit | The password |
nexus.backend.client.ssl.certificate.alias | key_server | The certificate alias |
nexus.backend.client.ssl.https.protocols | TLSv1.3 | The protocols |
nexus.backend.client.ssl.https.cipherSuites | TLS_AES_256_GCM_SHA384 | The Cipher Suites |
Settings keys settings.properties:
SpringBoot key nexus.backend.tomcat.connector.https.enable at true for activated the TLS/SSL protocol
Keys | Default value | Descriptions |
---|---|---|
nexus.backend.tomcat.ssl.keystore-path | /home/root/.keystore | Path to the Java KeyStore |
nexus.backend.tomcat.ssl.keystore-password | changeit | The password |
nexus.backend.tomcat.ssl.certificate.alias | key_server | The certificate alias |
nexus.backend.tomcat.ssl.https.port | 8443 | The Https port |
nexus.backend.tomcat.ssl.ajp.connector.enable | false | Start the Ajp connector |
nexus.backend.tomcat.ssl.ajp.connector.port | 8009 | The Ajp port |
nexus.backend.tomcat.ssl.ajp.connector.protocol | AJP/1.3 | AJP version 1.3 |
nexus.backend.tomcat.ssl.ajp.connector.secretRequired | false | A secret is Required |
Settings keys settings.properties:
StringBoot key nexus.backend.tomcat.accesslog.valve.enable at true for activated the Accesslogs
Keys | Default value | Descriptions |
---|---|---|
nexus.backend.tomcat.accesslog.directory | /tmp/logs/tomcat-nexus | Directory access log |
nexus.backend.tomcat.accesslog.suffix | .log | The suffix |
nexus.backend.tomcat.accesslog.encoding | UTF-8 | The suffix |
nexus.backend.tomcat.accesslog.pattern | date time x-threadname c-ip cs-method cs-uri sc-status bytes x-H(contentLength) time-taken x-H(authType) cs(Authorization) cs(User-Agent) | The pattern |
nexus.backend.tomcat.accesslog.checkExists | true | Check if file exists |
nexus.backend.tomcat.accesslog.asyncSupported | true | Support async requests |
nexus.backend.tomcat.accesslog.renameOnRotate | true | Rename on rotate |
nexus.backend.tomcat.accesslog.throwOnFailure | true | Throw on failure |
nexus.backend.tomcat.accesslog.maxDay | -1 | Max day file retention |
Noted the Full access logs are available with the CommonsRequestLoggingFilter, included the RequestBody.
Already initialized, activated by setting the logback.xml at level="DEBUG".
- Java 13
- SpringBoot 2.7.18
- Tomcat 9.0.95 & Servlet 4.0.1
- Maven 3.9.x
with the profile withoutTomcat:
mvn clean compile -P withoutTomcat
mvn clean package -P withoutTomcat
mvn clean install -P withoutTomcat
and look for the jar at target/nexus-backend-{version}.war
with the profile withTomcat:
mvn clean compile -P withTomcat
mvn clean install -P withTomcat
mvn clean package -P withTomcat
and look for the jar at target/nexus-backend-{version}.jar
mvn javadoc:javadoc
with maven:
mvn spring-boot:run -P withTomcat
By default, it uses 8082
port and the Servlet Context /nexus-backend
.
The default SpringBoot config is in /src/main/resources/application.properties
file.
The default NexusBackend config in /src/main/resources/settings.properties
file.
The Config keys and values can be modified or override by external path files, here:
- file
{user.home}/conf-global/config.properties
- file
{user.home}/conf/config.properties
- file
{user.home}/cfg/nexus-backend/config.properties
See RestControllerTest is in interaction with the MockController, run the tests with a local Tomcat running on localhost:8082/nexus-backend
The Swagger Mock-Api is only available in Dev mode, added in JVM Options: -Denvironment=development
This API implementation is used for the communication to a backend server. It provides methods for all supported http protocols on the backend side. Normally, it communicates to an API interface Backend.
- Get
- Post
- Post Multipart File
- Put
- Put Multipart File
- Patch
- Patch Multipart File
- Delete
- RestOperations should be configured with an Apache-HttpClient and a Pooling connection should be properly configured.
- HttpMessageConverter are also mandatory, StringHttp, FormHttp, ByteArrayHttp, ResourceHttp and MappingJackson2Http are the minimal.
- Typed Response parameter Class Object or a ParameterizedTypeReference are mandatory
- Object.class cannot be converted in a Resource or ByteArray directly without a minimal support Typed Response.
BackendService backendService = new BackendServiceImpl();
backendService.setBackendURL("https://internal.domain.com:9094");
backendService.setRestOperations(new RestTemplate());
backendService.setObjectMapper(new ObjectMapper());
Data data = backendService.get("/mock/v1/data", backendService.createResponseType(Data.class));
ResponseType<List<Data>> typeReference = backendService.createResponseType(new ParameterizedTypeReference<>(){});
List<Data> list = backendService.get("/mock/v1/dataList", typeReference);
Resource image = backendService.getFile("/static/images/logo-marianne.svg");
FileUtils.copyInputStreamToFile(image.getInputStream(), new File(System.getProperty("java.io.tmpdir") + "/logo-marianne.svg"));
ResponseType<List<Data>> typeReference = backendService.createResponseType(new ParameterizedTypeReference<>(){});
Object obj = backendService.doRequest("/mock/v1/dataList", HttpMethod.GET, typeReference, null, null);
System.out.println(obj);
Resource resource = backendService.doRequest("/mock/v1/datafile", HttpMethod.GET,
backendService.createResponseType(Resource.class), null, headers); // WARN mandatory typed Resource.class
String data = StreamUtils.copyToString(resource.getInputStream(), Charset.defaultCharset());
System.out.println(data);
ResponseType<byte[]> typeReference = backendService.createResponseType(byte[].class)
byte[] bytes = backendService.doRequest("/mock/v1/dataBytes", HttpMethod.GET, typeReference , null, null); // WARN mandatory typed byte[].class
System.out.println(new String(bytes, StandardCharsets.UTF_8));
- Last version 1.0.15, released at 23/10/2024 Fix missing method addCorsMappings
- Version 1.0.14, released at 14/10/2024 Support Backend Headers and Support ContentNegotiation Header Strategy for Resources
- Version 1.0.13, released at 06/10/2024 Full support Response in ByteArray Resource and Streaming Http Response Range Bytes
- Version 1.0.12, released at 02/10/2024 Fix ApiBase error Message super.getResponseEntity
- Version 1.0.11, released at 30/09/2024 Does not encode the URI template!
- Version 1.0.10, released at 29/09/2024 Add full support MultipartRequest content type multipart/form-data
- Version 1.0.9, released at 24/09/2024 Fix replicate requests ApiBackend.requestEntity
- Version 1.0.8, released at 13/08/2024 Re-encoding HttpUrl, Special Characters are re-interpreted
- Version 1.0.7, released at 03/08/2024 All is Bytes.
- Version 1.0.6, released at 14/07/2024 Clarify Byte Array deserialization.
- Version 1.0.5, released at 13/07/2024 Optimize build war/jar.
- Version 1.0.4, released at 08/07/2024.
- Version 1.0.3, released at 23/06/2024 Reinit project.
- Version 1.0.2 released at 28/04/2024.
- Version 1.0.1 released at 21/11/2022.
- Initial release 1.0.0 at 03/06/2021.
If you need help using Nexus-Backend Service feel free to drop an email or create an issue in GitHub.com (preferred).
To help Nexus-Backend / ApiBackend / BackendService development you are encouraged to
- Provide suggestion/feedback/Issue
- pull requests for new features
- Star 🌟 the project
This project is an Open Source Software released under the GPL-3.0 license.
Copyright (c) 2001-2024 JServlet.com Franck ANDRIANO.