Use bindAddress from Settings for UI, API and P2P.

This commit is contained in:
catbref 2019-08-14 15:11:20 +01:00
parent 8a0d93f304
commit e631e69fa1
3 changed files with 141 additions and 127 deletions

View File

@ -2,6 +2,9 @@ package org.qora.api;
import io.swagger.v3.jaxrs2.integration.resources.OpenApiResource;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import org.eclipse.jetty.rewrite.handler.RedirectPatternRule;
import org.eclipse.jetty.rewrite.handler.RewriteHandler;
import org.eclipse.jetty.server.CustomRequestLog;
@ -23,93 +26,93 @@ import org.qora.settings.Settings;
public class ApiService {
private final Server server;
private final ResourceConfig config;
public ApiService() {
config = new ResourceConfig();
config.packages("org.qora.api.resource");
config.register(OpenApiResource.class);
config.register(ApiDefinition.class);
config.register(AnnotationPostProcessor.class);
// Create RPC server
this.server = new Server(Settings.getInstance().getApiPort());
// Error handler
ErrorHandler errorHandler = new ApiErrorHandler();
this.server.setErrorHandler(errorHandler);
// Request logging
if (Settings.getInstance().isApiLoggingEnabled()) {
RequestLogWriter logWriter = new RequestLogWriter("API-requests.log");
logWriter.setAppend(true);
logWriter.setTimeZone("UTC");
RequestLog requestLog = new CustomRequestLog(logWriter, CustomRequestLog.EXTENDED_NCSA_FORMAT);
server.setRequestLog(requestLog);
}
// IP address based access control
InetAccessHandler accessHandler = new InetAccessHandler();
for (String pattern : Settings.getInstance().getApiWhitelist()) {
accessHandler.include(pattern);
}
this.server.setHandler(accessHandler);
// URL rewriting
RewriteHandler rewriteHandler = new RewriteHandler();
accessHandler.setHandler(rewriteHandler);
// Context
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
context.setContextPath("/");
rewriteHandler.setHandler(context);
// Cross-origin resource sharing
FilterHolder corsFilterHolder = new FilterHolder(CrossOriginFilter.class);
corsFilterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
corsFilterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET, POST, DELETE");
corsFilterHolder.setInitParameter(CrossOriginFilter.CHAIN_PREFLIGHT_PARAM, "false");
context.addFilter(corsFilterHolder, "/*", null);
// API servlet
ServletContainer container = new ServletContainer(config);
ServletHolder apiServlet = new ServletHolder(container);
apiServlet.setInitOrder(1);
context.addServlet(apiServlet, "/*");
// Swagger-UI static content
ClassLoader loader = this.getClass().getClassLoader();
ServletHolder swaggerUIServlet = new ServletHolder("static-swagger-ui", DefaultServlet.class);
swaggerUIServlet.setInitParameter("resourceBase", loader.getResource("resources/swagger-ui/").toString());
swaggerUIServlet.setInitParameter("dirAllowed", "true");
swaggerUIServlet.setInitParameter("pathInfoOnly", "true");
context.addServlet(swaggerUIServlet, "/api-documentation/*");
rewriteHandler.addRule(new RedirectPatternRule("", "/api-documentation/")); // redirect to Swagger UI start page
rewriteHandler.addRule(new RedirectPatternRule("/api-documentation", "/api-documentation/")); // redirect to Swagger UI start page
}
// XXX: replace singleton pattern by dependency injection?
private static ApiService instance;
private final ResourceConfig config;
private Server server;
private ApiService() {
this.config = new ResourceConfig();
this.config.packages("org.qora.api.resource");
this.config.register(OpenApiResource.class);
this.config.register(ApiDefinition.class);
this.config.register(AnnotationPostProcessor.class);
}
public static ApiService getInstance() {
if (instance == null) {
if (instance == null)
instance = new ApiService();
}
return instance;
}
public Iterable<Class<?>> getResources() {
// return resources;
return config.getClasses();
return this.config.getClasses();
}
public void start() {
try {
// Create API server
InetAddress bindAddr = InetAddress.getByName(Settings.getInstance().getBindAddress());
InetSocketAddress endpoint = new InetSocketAddress(bindAddr, Settings.getInstance().getApiPort());
this.server = new Server(endpoint);
// Error handler
ErrorHandler errorHandler = new ApiErrorHandler();
this.server.setErrorHandler(errorHandler);
// Request logging
if (Settings.getInstance().isApiLoggingEnabled()) {
RequestLogWriter logWriter = new RequestLogWriter("API-requests.log");
logWriter.setAppend(true);
logWriter.setTimeZone("UTC");
RequestLog requestLog = new CustomRequestLog(logWriter, CustomRequestLog.EXTENDED_NCSA_FORMAT);
this.server.setRequestLog(requestLog);
}
// IP address based access control
InetAccessHandler accessHandler = new InetAccessHandler();
for (String pattern : Settings.getInstance().getApiWhitelist()) {
accessHandler.include(pattern);
}
this.server.setHandler(accessHandler);
// URL rewriting
RewriteHandler rewriteHandler = new RewriteHandler();
accessHandler.setHandler(rewriteHandler);
// Context
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
context.setContextPath("/");
rewriteHandler.setHandler(context);
// Cross-origin resource sharing
FilterHolder corsFilterHolder = new FilterHolder(CrossOriginFilter.class);
corsFilterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
corsFilterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET, POST, DELETE");
corsFilterHolder.setInitParameter(CrossOriginFilter.CHAIN_PREFLIGHT_PARAM, "false");
context.addFilter(corsFilterHolder, "/*", null);
// API servlet
ServletContainer container = new ServletContainer(this.config);
ServletHolder apiServlet = new ServletHolder(container);
apiServlet.setInitOrder(1);
context.addServlet(apiServlet, "/*");
// Swagger-UI static content
ClassLoader loader = this.getClass().getClassLoader();
ServletHolder swaggerUIServlet = new ServletHolder("static-swagger-ui", DefaultServlet.class);
swaggerUIServlet.setInitParameter("resourceBase", loader.getResource("resources/swagger-ui/").toString());
swaggerUIServlet.setInitParameter("dirAllowed", "true");
swaggerUIServlet.setInitParameter("pathInfoOnly", "true");
context.addServlet(swaggerUIServlet, "/api-documentation/*");
rewriteHandler.addRule(new RedirectPatternRule("", "/api-documentation/")); // redirect to Swagger UI start page
rewriteHandler.addRule(new RedirectPatternRule("/api-documentation", "/api-documentation/")); // redirect to Swagger UI start page
// Start server
server.start();
this.server.start();
} catch (Exception e) {
// Failed to start
throw new RuntimeException("Failed to start API", e);
@ -119,9 +122,12 @@ public class ApiService {
public void stop() {
try {
// Stop server
server.stop();
this.server.stop();
} catch (Exception e) {
// Failed to stop
}
this.server = null;
}
}

View File

@ -43,6 +43,9 @@ public class Settings {
// Settings, and other config files
private String userPath;
// Common to all networking (UI/API/P2P)
private String bindAddress = "::"; // Use IPv6 wildcard to listen on all local addresses
// Node management UI
private boolean uiEnabled = true;
private Integer uiPort;
@ -71,7 +74,6 @@ public class Settings {
// Peer-to-peer related
private boolean isTestNet = false;
private Integer listenPort;
private String bindAddress = "::"; // Use IPv6 wildcard to listen on all local addresses
/** Minimum number of peers to allow block generation / synchronization. */
private int minBlockchainPeers = 3;
/** Target number of outbound connections to peers we should make. */

View File

@ -1,5 +1,8 @@
package org.qora.ui;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import org.eclipse.jetty.rewrite.handler.RedirectPatternRule;
import org.eclipse.jetty.rewrite.handler.RewriteHandler;
import org.eclipse.jetty.server.Server;
@ -14,69 +17,70 @@ import org.qora.settings.Settings;
public class UiService {
public static final String DOWNLOADS_RESOURCE_PATH = "node-ui-downloads";
private final Server server;
public UiService() {
// Create node management UI server
this.server = new Server(Settings.getInstance().getUiPort());
// IP address based access control
InetAccessHandler accessHandler = new InetAccessHandler();
for (String pattern : Settings.getInstance().getUiWhitelist()) {
accessHandler.include(pattern);
}
this.server.setHandler(accessHandler);
// URL rewriting
RewriteHandler rewriteHandler = new RewriteHandler();
accessHandler.setHandler(rewriteHandler);
// Context
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
context.setContextPath("/");
rewriteHandler.setHandler(context);
// Cross-origin resource sharing
FilterHolder corsFilterHolder = new FilterHolder(CrossOriginFilter.class);
corsFilterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
corsFilterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET, POST, DELETE");
corsFilterHolder.setInitParameter(CrossOriginFilter.CHAIN_PREFLIGHT_PARAM, "false");
context.addFilter(corsFilterHolder, "/*", null);
ClassLoader loader = this.getClass().getClassLoader();
// Node management UI download servlet
ServletHolder uiDownloadServlet = new ServletHolder("node-ui-download", new DefaultServlet(new DownloadResourceService()));
uiDownloadServlet.setInitParameter("resourceBase", loader.getResource(DOWNLOADS_RESOURCE_PATH + "/").toString());
uiDownloadServlet.setInitParameter("dirAllowed", "true");
uiDownloadServlet.setInitParameter("pathInfoOnly", "true");
context.addServlet(uiDownloadServlet, "/downloads/*");
// Node management UI static content servlet
ServletHolder uiServlet = new ServletHolder("node-management-ui", DefaultServlet.class);
uiServlet.setInitParameter("resourceBase", loader.getResource("node-management-ui/").toString());
uiServlet.setInitParameter("dirAllowed", "true");
uiServlet.setInitParameter("pathInfoOnly", "true");
context.addServlet(uiServlet, "/*");
rewriteHandler.addRule(new RedirectPatternRule("", "/index.html")); // node management UI start page
}
private static UiService instance;
private Server server;
private UiService() {
}
public static UiService getInstance() {
if (instance == null) {
if (instance == null)
instance = new UiService();
}
return instance;
}
public void start() {
try {
// Create node management UI server
InetAddress bindAddr = InetAddress.getByName(Settings.getInstance().getBindAddress());
InetSocketAddress endpoint = new InetSocketAddress(bindAddr, Settings.getInstance().getUiPort());
this.server = new Server(endpoint);
// IP address based access control
InetAccessHandler accessHandler = new InetAccessHandler();
for (String pattern : Settings.getInstance().getUiWhitelist()) {
accessHandler.include(pattern);
}
this.server.setHandler(accessHandler);
// URL rewriting
RewriteHandler rewriteHandler = new RewriteHandler();
accessHandler.setHandler(rewriteHandler);
// Context
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
context.setContextPath("/");
rewriteHandler.setHandler(context);
// Cross-origin resource sharing
FilterHolder corsFilterHolder = new FilterHolder(CrossOriginFilter.class);
corsFilterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
corsFilterHolder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET, POST, DELETE");
corsFilterHolder.setInitParameter(CrossOriginFilter.CHAIN_PREFLIGHT_PARAM, "false");
context.addFilter(corsFilterHolder, "/*", null);
ClassLoader loader = this.getClass().getClassLoader();
// Node management UI download servlet
ServletHolder uiDownloadServlet = new ServletHolder("node-ui-download", new DefaultServlet(new DownloadResourceService()));
uiDownloadServlet.setInitParameter("resourceBase", loader.getResource(DOWNLOADS_RESOURCE_PATH + "/").toString());
uiDownloadServlet.setInitParameter("dirAllowed", "true");
uiDownloadServlet.setInitParameter("pathInfoOnly", "true");
context.addServlet(uiDownloadServlet, "/downloads/*");
// Node management UI static content servlet
ServletHolder uiServlet = new ServletHolder("node-management-ui", DefaultServlet.class);
uiServlet.setInitParameter("resourceBase", loader.getResource("node-management-ui/").toString());
uiServlet.setInitParameter("dirAllowed", "true");
uiServlet.setInitParameter("pathInfoOnly", "true");
context.addServlet(uiServlet, "/*");
rewriteHandler.addRule(new RedirectPatternRule("", "/index.html")); // node management UI start page
// Start server
server.start();
this.server.start();
} catch (Exception e) {
// Failed to start
throw new RuntimeException("Failed to start node management UI", e);
@ -86,10 +90,12 @@ public class UiService {
public void stop() {
try {
// Stop server
server.stop();
this.server.stop();
} catch (Exception e) {
// Failed to stop
}
this.server = null;
}
}